diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 3a0a291ccb24c..37e0a2ecf9cc6 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -36,6 +36,9 @@
/clang/lib/CIR @lanza @bcardosolopes @xlauko @andykaylor
/clang/tools/cir-* @lanza @bcardosolopes @xlauko @andykaylor
+# BEGIN SWIFT
+/lldb/**/*Swift* @adrian-prantl
+# END SWIFT
/lldb/ @JDevlieghere
# MLIR Interfaces.
diff --git a/.gitignore b/.gitignore
index 860b8ea12abd4..b273cb8e2e15e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,6 +23,9 @@
#OS X specific files.
.DS_store
+# Temporary file created by the automerger tool.
+.am.txt
+
# Ignore the user specified CMake presets in subproject directories.
/*/CMakeUserPresets.json
diff --git a/README.md b/README.md
index a9b29ecbc1a3a..390fda0b08a34 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,11 @@
+# Swift's fork of llvm-project
+
+This is Swift's fork of llvm-project. For more information on Swift's
+branching scheme, please see
+[apple-docs/AppleBranchingScheme.md](https://github.com/apple/llvm-project/tree/apple/main/apple-docs/AppleBranchingScheme.md).
+
+The LLVM project's main README follows.
+
# The LLVM Compiler Infrastructure
[](https://securityscorecards.dev/viewer/?uri=github.com/llvm/llvm-project)
diff --git a/apple-ci/amtool b/apple-ci/amtool
new file mode 100755
index 0000000000000..a0a9e2410cdc7
--- /dev/null
+++ b/apple-ci/amtool
@@ -0,0 +1,363 @@
+#!/usr/bin/env python3
+"""
+Tool to reproduce and resolve the issues reported by the automerger.
+"""
+
+import argparse
+import json
+import logging
+import os
+import shlex
+import subprocess
+import sys
+from typing import List, Optional
+
+log = logging.getLogger()
+
+REMOTE = 'git@github.com:swiftlang/llvm-project.git'
+
+class GitError(Exception):
+ """
+ An exception thrown if the git command failed.
+
+ Attributes
+ ----------
+ args : List[str]
+ The list of arguments passed to `git`.
+ returncode : int
+ The exit code of the `git` process.
+ stdout : str
+ The output of `git`.
+ stderr : str
+ The error output of `git`.
+ """
+
+ def __init__(self, args, returncode: int, stdout: str, stderr: str):
+ self.args = args
+ self.returncode = returncode
+ self.stdout = stdout
+ self.stderr = stderr
+
+ def __repr__(self):
+ return f'GitError({self.args}, {self.returncode}, "{self.stdout}", "{self.stderr}")'
+
+
+def _git_to_str(args: List[str]):
+ return 'git ' + ' '.join(map(lambda arg: shlex.quote(arg), args))
+
+
+def invoke(*cmd, git_dir: Optional[str] = None,
+ stdin: Optional[str] = None,
+ stdout=None,
+ stderr=subprocess.PIPE,
+ strip: bool = True, ignore_error: bool = False,
+ timeout: Optional[int] = None):
+ """ Invokes a git subprocess with the passed string arguments and return
+ the stdout of the git command as a string if text otherwise a file
+ handle.
+ """
+ if git_dir is not None:
+ all_args = ['-C', git_dir] + list(cmd)
+ else:
+ all_args = list(cmd)
+ log.debug('$ %s', _git_to_str(all_args))
+ p = subprocess.Popen(['git'] + all_args,
+ stdout=stdout,
+ stderr=stderr,
+ stdin=subprocess.PIPE if stdin else None,
+ universal_newlines=True)
+ out, err = p.communicate(input=stdin, timeout=timeout)
+ if p.returncode == 0:
+ if out:
+ if strip:
+ out = out.rstrip()
+ for line in out.splitlines():
+ log.debug('STDOUT: %s', line)
+ if err:
+ for line in err.rstrip().splitlines():
+ log.debug('STDERR: %s', line)
+ return out
+ log.debug('EXIT STATUS: %d', p.returncode)
+ if err:
+ for line in err.rstrip().splitlines():
+ log.debug('STDERR: %s', line)
+ if ignore_error:
+ return None
+ raise GitError(all_args, p.returncode, out, err)
+
+
+def git(*cmd, **kwargs):
+ """ Invokes a git subprocess with the passed string arguments and return
+ the stdout of the git command.
+ """
+ return invoke(*cmd, **kwargs, stdout=subprocess.PIPE)
+
+
+class Commit:
+ """ Represents the commit being merged."""
+ def __init__(self, sha: str):
+ self.sha = sha
+
+ def short_sha(self):
+ return self.sha[0:12]
+
+ def get_previous_commit(self):
+ return git('rev-parse', self.sha + '^')
+
+
+class MergeId:
+ """ Encapsulates the merge ID constructed by the automerger and the
+ corresponding git operations.
+ """
+ prefix = 'refs/am'
+
+ def __init__(self, merge_id: str):
+ self.merge_id = merge_id
+ parts = merge_id.split('_')
+ try:
+ self.commit = Commit(parts[0])
+ self.target_branch = '/'.join(parts[1:])
+ except IndexError:
+ log.error("Merge Id not correctly formed.")
+
+ @property
+ def ref_name(self):
+ return self.prefix + "/changes/" + self.merge_id
+
+ @property
+ def merge_candidate_ref_name(self):
+ return self.prefix + "/merge-candidate/" + self.merge_id
+
+ def get_previous_merge_id(self):
+ previous_commit = self.commit.get_previous_commit()
+ return MergeId(self.merge_id.replace(self.commit.sha, previous_commit))
+
+ @staticmethod
+ def fetch(*args):
+ """Helper function for the "git fetch" command."""
+ try:
+ git('fetch', *args)
+ return True
+ except GitError as e:
+ if e.returncode == 128:
+ return False
+ raise e
+
+ def fetch_ref_name(self):
+ refspec = self.ref_name + ":" + self.ref_name
+ return self.fetch(REMOTE, self.target_branch, refspec)
+
+ def fetch_merge_candidate_ref_name(self):
+ refspec = "+" + self.merge_candidate_ref_name + ":" + self.merge_candidate_ref_name
+ return self.fetch(REMOTE, refspec)
+
+ @staticmethod
+ def checkout(*args):
+ """Helper function for the "git checkout" command."""
+ try:
+ git('checkout', *args)
+ return (True, '')
+ except GitError as e:
+ return (False, e.stderr)
+
+ def checkout_merge_candidate(self):
+ """Checkout the merge candidate for this merge ID."""
+ return self.checkout(self.merge_candidate_ref_name)
+
+ def checkout_target_branch(self):
+ """Checkout the target branch for this merge ID."""
+ if self.fetch(REMOTE, self.target_branch):
+ return self.checkout('FETCH_HEAD')
+ return (False, '')
+
+ def get_source_branch_name(self):
+ """Get the source branch name (upstream) for this target branch."""
+ content = None
+ if self.fetch(REMOTE, 'repo/apple-llvm-config/am'):
+ content = git('cat-file', '-p',
+ 'FETCH_HEAD:apple-llvm-config/am/am-config.json')
+ if not content:
+ return None
+ config = json.loads(content)
+ if not config:
+ return None
+ for json_dict in config:
+ if json_dict['target'] == self.target_branch:
+ return json_dict['upstream']
+ return None
+
+ def merge(self):
+ source_branch = self.get_source_branch_name()
+ if not source_branch:
+ log.error(f"Could not figure out the source branch for {self.target_branch}.")
+ try:
+ git('merge', '--no-edit', "-X", "diff-algorithm=histogram",
+ "--summary", self.ref_name, '-m',
+ f"Merge commit '{self.commit.short_sha()}' from {source_branch} into {self.target_branch}")
+ return True
+ except GitError as e:
+ if 'CONFLICT' in e.stdout:
+ return False
+ raise e
+
+ def push(self):
+ try:
+ git('push', REMOTE, f'HEAD:{self.ref_name}')
+ return (True, '')
+ except GitError as e:
+ return (False, e.stdout)
+
+
+def parse_args():
+ """Parse the command line arguments."""
+
+ parser = argparse.ArgumentParser(description="Automerger Tool")
+ parser.add_argument('-v', '--verbose', action='https://github.com/store_true', required=False,
+ help='enable verbose outout and show commands being run')
+
+ subparsers = parser.add_subparsers(dest='command', required=True,
+ help='the command to run')
+ # Reproduce
+ parser_reproduce = subparsers.add_parser('reproduce',
+ help='Reproduce the issue observed when performing merge')
+ parser_reproduce.add_argument('id', help='the merge ID to reproduce')
+ # Push
+ parser_push = subparsers.add_parser('push',
+ help='push the resolution, so that the automerger can pick it up')
+ # Override push uncommitted change error
+ parser_push.add_argument('--ignore-uncommitted-changes', dest='ignore_uncommitted',
+ action='https://github.com/store_true', required=False,
+ help='allowing pushing a commit even if uncommitted changes exist')
+
+ args = parser.parse_args()
+ return args
+
+
+def main():
+ args = parse_args()
+
+ # Default to INFO level. Increase to DEBUG level if verbose flag passed.
+ log_level = logging.INFO
+ if args.verbose:
+ log_level = logging.DEBUG
+
+ log.setLevel(log_level)
+ # create console handler with a higher log level
+ ch = logging.StreamHandler()
+ ch.setLevel(log_level)
+ # create formatter and add it to the handlers
+ ch_fomatter = logging.Formatter('%(levelname)s: %(message)s')
+ ch.setFormatter(ch_fomatter)
+ # add the handlers to the logger
+ log.addHandler(ch)
+
+ # File to record the merge ID locally so we can use it in the `push`
+ # command without having the user enter it again.
+ record = '.am.txt'
+
+ # Reproduce mode.
+ if args.command == "reproduce":
+ log.info('Attempting to reproduce the issue.')
+ merge_id = MergeId(args.id)
+
+ # Record the ref locally so we can use it in the `push` command
+ # without having the user enter it again.
+ with open(record, 'w') as f:
+ f.write(args.id)
+
+ # Fetch the ref. If we failed to fetch then just return because it is
+ # likely that the commit has already been merged and the ref deleted.
+ log.info('Fetching the ref and the target branch ...')
+ status = merge_id.fetch_ref_name()
+ if not status:
+ log.error('Unable to fetch the ref. Are you in the right repo? Or, is it already merged?')
+ return 1
+ log.info('Successfully fetched.')
+
+ # Fetch the merge candidate ref for the previous commit and check it
+ # out in order to apply this commit on top of it. This allows us to
+ # reproduce just this issue and not any other issues in the prior
+ # commits which have not been merged yet.
+ # If we failed to fetch then it is likely that the previous commit has
+ # already been merged. Checkout the target branch in that case.
+ previous_merge_id = merge_id.get_previous_merge_id()
+ log.info('Fetching the previous commit ...')
+ status = previous_merge_id.fetch_merge_candidate_ref_name()
+ if not status:
+ log.info('Previous commit already merged. Checking out the target branch instead.')
+ status, msg = merge_id.checkout_target_branch()
+ if not status:
+ log.error('Failed to checkout.')
+ log.error(msg)
+ return 1
+ log.info('Successfully checked out the target branch.')
+ else:
+ log.info('Successfully fetched.')
+ log.info('Now checking out the previous commit.')
+ status, msg = previous_merge_id.checkout_merge_candidate()
+ if not status:
+ log.error('Failed to checkout.')
+ log.error(msg)
+ return 1
+ log.info('Successfully checked out the previous commit.')
+
+ # Perform the merge.
+ log.info('Performing the merge ...')
+ rc = merge_id.merge()
+ if not rc:
+ log.info('Please resolve the conflicts and push the merge commit.')
+ return 0
+ log.info('No merge conflict seen. Is this a build/test failure?')
+ log.info('Please resolve the issue and push the commit.')
+ return 0
+
+ # Push mode.
+ elif args.command == "push":
+ # Read the ref saved locally by the `reproduce` command.
+ try:
+ with open(record, 'r') as f:
+ content = f.read()
+ except FileNotFoundError:
+ log.error('Did you run the `reproduce` command before?')
+ return 1
+ log.debug(f'Content : {content}')
+
+ # Check if we happen to be still in the middle of the merge.
+ # Proceed to push if otherwise the merge has been concluded.
+ try:
+ git('rev-parse', '--verify', '--quiet', 'MERGE_HEAD')
+ log.error('Looks like you are in the middle of the merge.')
+ log.error('Please conclude the merge before pushing.')
+ return 1
+ except GitError:
+ pass
+
+ # Check if we have any unstaged or uncommitted changes in the tree.
+ if len(git('diff-index', 'HEAD')):
+ if args.ignore_uncommitted:
+ log.warning('Ignoring uncommitted changes.')
+ else:
+ log.error('Looks like you have unstaged or uncommitted changes.')
+ log.error('Please make sure everything has been added to the commit.')
+ log.error('Use `--ignore-uncommitted-changes` to ignore, and push anyway.')
+ return 1
+
+ # Save the commit sha so that we can include it in the output message.
+ merge_commit = git('rev-parse', 'HEAD')
+
+ # Perform the push.
+ merge_id = MergeId(content)
+ log.info("Pushing ...")
+ status, msg = merge_id.push()
+ if not status:
+ log.error('Failed to push.')
+ log.error(msg)
+ return 1
+ log.info(f'Successfully pushed `{merge_commit}`.')
+
+ # Clean up.
+ os.remove(record)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/apple-ci/clang/am/build.sh b/apple-ci/clang/am/build.sh
new file mode 100644
index 0000000000000..04ec23ecee0a1
--- /dev/null
+++ b/apple-ci/clang/am/build.sh
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+set -eu
+
+SRC_DIR=$PWD/llvm-project
+BUILD_DIR=$PWD/build
+
+if [[ -e llvm/CMakeLists.txt && -e clang && -e compiler-rt ]]; then
+ # Looks like we are already in the llvm-project directory.
+ # Adjust the source and build directory location variables accordingly.
+ SRC_DIR=$PWD
+ BUILD_DIR=$PWD/../build
+fi
+
+for arg; do
+ case $arg in
+ --src=*) SRC_DIR="${arg##*=}"; shift ;;
+ --build=*) BUILD_DIR="${arg##*=}"; shift ;;
+ *) echo "Incorrect usage." >&2; exit 1 ;;
+ esac
+done
+
+echo
+echo "SRC_DIR . . . . = $SRC_DIR"
+echo "BUILD_DIR . . . = $BUILD_DIR"
+echo
+
+NINJA=$(xcrun -f ninja)
+
+export CLANG_CRASH_DIAGNOSTICS_DIR=${BUILD_DIR}/.CLANG_CRASH_DIAGNOSTICS_DIR
+
+HOST_COMPILER_PATH=$(dirname $(xcrun -f clang))
+
+mkdir -p $BUILD_DIR && cd $_
+set -x
+xcrun cmake -G Ninja \
+ -DCMAKE_MAKE_PROGRAM=$NINJA \
+ -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_ASSERTIONS=ON \
+ -DCMAKE_C_COMPILER=$HOST_COMPILER_PATH/clang \
+ -DCMAKE_CXX_COMPILER=$HOST_COMPILER_PATH/clang++ \
+ -DCMAKE_C_COMPILER_LAUNCHER=$HOST_COMPILER_PATH/clang-cache \
+ -DCMAKE_CXX_COMPILER_LAUNCHER=$HOST_COMPILER_PATH/clang-cache \
+ -DLLVM_TARGETS_TO_BUILD="X86;ARM;AArch64" \
+ -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;compiler-rt;lldb" \
+ -DLLDB_ENABLE_SWIFT_SUPPORT=OFF \
+ -DLLDB_INCLUDE_TESTS=OFF \
+ $SRC_DIR/llvm && $NINJA
diff --git a/apple-ci/pr.sh b/apple-ci/pr.sh
new file mode 100755
index 0000000000000..f21587f77896b
--- /dev/null
+++ b/apple-ci/pr.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+# Build script for ci.swift.org PR testing.
+# Tools like cmake/ninja needs to be in $PATH
+# and run the script in build directory.
+
+LLVM_PROJECT_SRC=$1
+LLVM_ENABLE_PROJECTS=${2:-"clang;clang-tools-extra"}
+
+echo '--- CMake Config ---'
+cmake -G Ninja \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DLLVM_ENABLE_ASSERTIONS=On \
+ -DLLVM_ENABLE_PROJECTS=${LLVM_ENABLE_PROJECTS} \
+ '-DLLVM_TARGETS_TO_BUILD=X86;ARM;AArch64' \
+ '-DLLVM_LIT_ARGS=-v' \
+ ${LLVM_PROJECT_SRC}/llvm
+
+echo '--- Ninja Build ---'
+ninja -v
+echo '--- Ninja Test ---'
+ninja -v -k 0 check-all
diff --git a/apple-docs/AppleBranchingScheme.md b/apple-docs/AppleBranchingScheme.md
new file mode 100644
index 0000000000000..694d2166bd372
--- /dev/null
+++ b/apple-docs/AppleBranchingScheme.md
@@ -0,0 +1,102 @@
+# Apple's branching scheme for llvm-project
+
+This document explains the various important branches in
+[apple/llvm-project](https://github.com/apple/llvm-project),
+how they relate to one another, and how they correspond to branches in the
+[apple/swift](https://github.com/apple/swift) repository.
+
+These are the most important branches to know about:
+
+- [next](https://github.com/apple/llvm-project/tree/next)
+ is aligned with Swift's
+ [next](https://github.com/apple/swift/tree/next) branch.
+- The current `stable` branch (check
+ [update-checkout-config.json](https://github.com/apple/swift/blob/main/utils/update_checkout/update-checkout-config.json)
+ for up-to-date info) is aligned with Swift's
+ [main](https://github.com/apple/swift/tree/main) branch.
+- `swift/*` branches are aligned with the corresponding Swift branch without
+ the `swift/` prefix.
+
+## Upstream branches
+
+The `llvm.org/*` branches are forwarded, unchanged, from
+[github.com/llvm/llvm-project](https://github.com/llvm/llvm-project). These
+are read-only, exact copies of the upstream LLVM project's branches. They are
+forwarded here as a convenience for easy reference, to avoid the need for extra
+remotes.
+
+- [llvm.org/main](https://github.com/apple/llvm-project/tree/llvm.org/main)
+ is the most important branch here, matching the LLVM project's
+ [main](https://github.com/llvm/llvm-project/tree/main) branch.
+
+## Downstream branches
+
+Downstream branches contain changes on top of what is in the LLVM project.
+This includes some patches that have not yet been upstreamed to the LLVM
+project, including some special support for Swift.
+
+We are actively working on either upstreaming or reverting many of those
+differences. The goal is to fully eliminate all *non-Swift* differences between
+`next` and `llvm.org/main`.
+
+Any LLVM development that does not depend on the Swift repository should happen
+upstream. The only changes that are allowed to be submitted without going
+through upstream LLVM are those that are either directly related to upstreaming
+content or that are needed because of the existing differences (e.g., resolving
+merge conflicts or fixing build errors).
+
+- [next](https://github.com/apple/llvm-project/tree/next) is
+ downstream of
+ [llvm.org/main](https://github.com/apple/llvm-project/tree/llvm.org/main).
+ There is a gated automerger that does testing before merging in. Most
+ changes to this branch should be redirected to
+ (see also ). Changes made to a
+ stabilization branch are cherry-picked here.
+- `stable/*`: These branches are periodic stabilization branches, where
+ fixes are made or manually cherry-picked from `llvm.org/main`.
+- `swift/release/*`: These are Swift release branches, where fixed are cherry-
+ picked from a stabilization branch during release convergence.
+
+## Historical trivia
+
+### Mappings to branches from before the monorepo transition
+
+Before the LLVM project's monorepo transition, Apple maintained downstream
+forks of various split repositories. Here is a mapping from a few of the new
+branches in the llvm-project monorepo to their original split repositories.
+
+- [apple/main](https://github.com/apple/llvm-project/tree/apple/main) was
+ generated from the `upstream-with-swift` branches in
+ [swift-clang](https://github.com/apple/swift-clang/),
+ [swift-llvm](https://github.com/apple/swift-llvm/),
+ [swift-compiler-rt](https://github.com/apple/swift-compiler-rt/),
+ [swift-clang-tools-extra](https://github.com/apple/swift-clang-tools-extra/),
+ and [swift-libcxx](https://github.com/apple/swift-libcxx/), with the notable
+ **exclusion** of [swift-lldb](https://github.com/apple/swift-lldb/),
+- [swift/next](https://github.com/apple/llvm-project/tree/swift/next)
+ was generated from the `upstream-with-swift` branch in
+ [swift-lldb](https://github.com/apple/swift-lldb/), interleaved with merges
+ from [apple/main](https://github.com/apple/llvm-project/tree/apple/main).
+- [apple/stable/20190104](https://github.com/apple/llvm-project/tree/apple/stable/20190104)
+ was generated from the `swift-5.1-branch` branches in
+ [swift-clang](https://github.com/apple/swift-clang/),
+ [swift-llvm](https://github.com/apple/swift-llvm/),
+ [swift-compiler-rt](https://github.com/apple/swift-compiler-rt/),
+ [swift-clang-tools-extra](https://github.com/apple/swift-clang-tools-extra/),
+ and [swift-libcxx](https://github.com/apple/swift-libcxx/), with the notable
+ **exclusion** of [swift-lldb](https://github.com/apple/swift-lldb/),
+- [swift/swift-5.1-branch](https://github.com/apple/llvm-project/tree/swift/swift-5.1-branch)
+ was generated from the `swift-5.1-branch` branch in
+ [swift-lldb](https://github.com/apple/swift-lldb/), interleaved with merges
+ from
+ [apple/stable/20190104](https://github.com/apple/llvm-project/tree/apple/stable/20190104).
+- [swift/main](https://github.com/apple/llvm-project/tree/swift/main) was
+ generated from the `stable` branch from all six split repos.
+
+### Branching scheme prior to July 2021 change
+
+Prior to July 2021, the `apple:llvm-project` repository maintained two sets
+of downstream branches: one set that did not include any content that _depended
+on_ Swift, and another set that included all downstream changes. See
+[this forum thread](https://forums.swift.org/t/simplifying-the-apple-llvm-project-branches/50287)
+explaining the change.
diff --git a/apple-llvm-config/am/apple-master.json b/apple-llvm-config/am/apple-master.json
new file mode 100644
index 0000000000000..427b8b4bbf218
--- /dev/null
+++ b/apple-llvm-config/am/apple-master.json
@@ -0,0 +1,3 @@
+{
+ "upstream": "llvm.org/master"
+}
diff --git a/apple-llvm-config/am/swift-master-next.json b/apple-llvm-config/am/swift-master-next.json
new file mode 100644
index 0000000000000..6e0e6b553f348
--- /dev/null
+++ b/apple-llvm-config/am/swift-master-next.json
@@ -0,0 +1,3 @@
+{
+ "upstream": "apple/master"
+}
diff --git a/apple-llvm-config/pr.json b/apple-llvm-config/pr.json
new file mode 100644
index 0000000000000..9de9ce6265850
--- /dev/null
+++ b/apple-llvm-config/pr.json
@@ -0,0 +1,9 @@
+{
+"type": "github",
+"domain": "github.com",
+"user": "apple",
+"repo": "llvm-project",
+"test": {
+ "type":"swift-ci"
+}
+}
diff --git a/bolt/test/runtime/AArch64/r_aarch64_prelxx.s b/bolt/test/runtime/AArch64/r_aarch64_prelxx.s
new file mode 100644
index 0000000000000..89bc6ccf667fb
--- /dev/null
+++ b/bolt/test/runtime/AArch64/r_aarch64_prelxx.s
@@ -0,0 +1,37 @@
+// This test checks processing of R_AARCH64_PREL64/32/16 relocations
+
+// RUN: %clang %cflags -nostartfiles -nostdlib %s -o %t.exe -Wl,-q \
+// RUN: -Wl,-z,max-page-size=4
+// RUN: llvm-readelf -Wa %t.exe | FileCheck %s -check-prefix=CHECKPREL
+
+// CHECKPREL: R_AARCH64_PREL16 {{.*}} .dummy + 0
+// CHECKPREL-NEXT: R_AARCH64_PREL32 {{.*}} _start + 4
+// CHECKPREL-NEXT: R_AARCH64_PREL64 {{.*}} _start + 8
+
+// RUN: llvm-bolt %t.exe -o %t.bolt
+// RUN: llvm-readobj -S --section-data %t.bolt | FileCheck %s
+
+// CHECK: Name: .data
+// CHECK: SectionData (
+// CHECK: 0000: FCFF0000 44FF3F00 44FF3F00 00000000
+// CHECK: )
+
+ .text
+ .align 4
+ .globl _start
+ .type _start, %function
+_start:
+ adr x0, datatable
+ mov x0, #0
+ ret
+
+.section .dummy, "da"
+dummy:
+ .word 0
+
+.section .data
+datatable:
+ .hword dummy - datatable
+ .align 2
+ .word _start - datatable
+ .xword _start - datatable
diff --git a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp
index 487e5e299d132..f6f0f4928025f 100644
--- a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp
+++ b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp
@@ -253,6 +253,13 @@ void ExpandModularHeadersPPCallbacks::PragmaAssumeNonNullEnd(
SourceLocation Loc) {
parseToLocation(Loc);
}
+/*TO_UPSTREAM(BoundsSafety) ON*/
+void ExpandModularHeadersPPCallbacks::
+PragmaAbiPointerAttributesSet(SourceLocation Loc,
+ ArrayRef Spec) {
+ parseToLocation(Loc);
+}
+/*TO_UPSTREAM(BoundsSafety) OFF*/
void ExpandModularHeadersPPCallbacks::MacroExpands(const Token &MacroNameTok,
const MacroDefinition &,
SourceRange Range,
diff --git a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.h b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.h
index e599bda92c25c..b241481563fcd 100644
--- a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.h
+++ b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.h
@@ -100,6 +100,10 @@ class ExpandModularHeadersPPCallbacks : public PPCallbacks {
void PragmaWarningPop(SourceLocation Loc) override;
void PragmaAssumeNonNullBegin(SourceLocation Loc) override;
void PragmaAssumeNonNullEnd(SourceLocation Loc) override;
+ /*TO_UPSTREAM(BoundsSafety) ON*/
+ void PragmaAbiPointerAttributesSet(SourceLocation Loc,
+ ArrayRef) override;
+ /*TO_UPSTREAM(BoundsSafety) OFF*/
void MacroExpands(const Token &MacroNameTok, const MacroDefinition &,
SourceRange Range, const MacroArgs *) override;
void MacroDefined(const Token &MacroNameTok,
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index 0f765e96fb152..673e8c5b6b7a6 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -902,30 +902,53 @@ void ClangdLSPServer::onPrepareRename(const TextDocumentPositionParams &Params,
});
}
+/// Validate that `Edits` are valid and form a `WorkspaceEdit` that contains
+/// the edits as its `changes`.
+static llvm::Expected
+formWorkspaceEdit(const FileEdits &Edits, const ClangdServer &Server) {
+ if (auto Err = validateEdits(Server, Edits))
+ return std::move(Err);
+ WorkspaceEdit Result;
+ // FIXME: use documentChanges if SupportDocumentChanges is true.
+ Result.changes.emplace();
+ for (const auto &Rep : Edits) {
+ (*Result.changes)[URI::createFile(Rep.first()).toString()] =
+ Rep.second.asTextEdits();
+ }
+ return Result;
+}
+
void ClangdLSPServer::onRename(const RenameParams &Params,
Callback Reply) {
Path File = std::string(Params.textDocument.uri.file());
if (!Server->getDraft(File))
return Reply(llvm::make_error(
"onRename called for non-added file", ErrorCode::InvalidParams));
+ auto Callback = [Reply = std::move(Reply),
+ this](llvm::Expected R) mutable {
+ if (!R)
+ return Reply(R.takeError());
+ llvm::Expected WorkspaceEdit =
+ formWorkspaceEdit(R->GlobalChanges, *Server);
+ Reply(std::move(WorkspaceEdit));
+ };
Server->rename(File, Params.position, Params.newName, Opts.Rename,
- [File, Params, Reply = std::move(Reply),
- this](llvm::Expected R) mutable {
- if (!R)
- return Reply(R.takeError());
- if (auto Err = validateEdits(*Server, R->GlobalChanges))
- return Reply(std::move(Err));
- WorkspaceEdit Result;
- // FIXME: use documentChanges if SupportDocumentChanges is
- // true.
- Result.changes.emplace();
- for (const auto &Rep : R->GlobalChanges) {
- (*Result
- .changes)[URI::createFile(Rep.first()).toString()] =
- Rep.second.asTextEdits();
- }
- Reply(Result);
- });
+ std::move(Callback));
+}
+
+void ClangdLSPServer::onIndexedRename(const IndexedRenameParams &Params,
+ Callback Reply) {
+ auto Callback = [Reply = std::move(Reply),
+ this](llvm::Expected Edits) mutable {
+ if (!Edits) {
+ return Reply(Edits.takeError());
+ }
+ llvm::Expected WorkspaceEdit =
+ formWorkspaceEdit(*Edits, *Server);
+ Reply(std::move(WorkspaceEdit));
+ };
+ Server->indexedRename(Params.positions, Params.textDocument.uri.file(),
+ Params.oldName, Params.newName, std::move(Callback));
}
void ClangdLSPServer::onDocumentDidClose(
@@ -1695,6 +1718,7 @@ void ClangdLSPServer::bindMethods(LSPBinder &Bind,
Bind.method("textDocument/switchSourceHeader", this, &ClangdLSPServer::onSwitchSourceHeader);
Bind.method("textDocument/prepareRename", this, &ClangdLSPServer::onPrepareRename);
Bind.method("textDocument/rename", this, &ClangdLSPServer::onRename);
+ Bind.method("workspace/indexedRename", this, &ClangdLSPServer::onIndexedRename);
Bind.method("textDocument/hover", this, &ClangdLSPServer::onHover);
Bind.method("textDocument/documentSymbol", this, &ClangdLSPServer::onDocumentSymbol);
Bind.method("workspace/executeCommand", this, &ClangdLSPServer::onCommand);
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.h b/clang-tools-extra/clangd/ClangdLSPServer.h
index 6ada3fd9e6e47..07048cdcc8617 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.h
+++ b/clang-tools-extra/clangd/ClangdLSPServer.h
@@ -144,6 +144,7 @@ class ClangdLSPServer : private ClangdServer::Callbacks,
void onPrepareRename(const TextDocumentPositionParams &,
Callback);
void onRename(const RenameParams &, Callback);
+ void onIndexedRename(const IndexedRenameParams &, Callback);
void onHover(const TextDocumentPositionParams &,
Callback>);
void onPrepareTypeHierarchy(const TypeHierarchyPrepareParams &,
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp
index ac1e9aa5f0ff1..97e27ebf6558f 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -644,6 +644,50 @@ void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
WorkScheduler->runWithAST("Rename", File, std::move(Action));
}
+void ClangdServer::indexedRename(
+ const std::map> &Positions,
+ PathRef PrimaryFile, llvm::StringRef OldName, llvm::StringRef NewName,
+ Callback CB) {
+ ParseInputs Inputs;
+ Inputs.TFS = &TFS;
+ Inputs.CompileCommand = CDB.getCompileCommand(PrimaryFile)
+ .value_or(CDB.getFallbackCommand(PrimaryFile));
+ IgnoreDiagnostics IgnoreDiags;
+ std::unique_ptr CI =
+ buildCompilerInvocation(Inputs, IgnoreDiags);
+ if (!CI) {
+ return CB(llvm::make_error(
+ "Unable to get compiler arguments for primary file",
+ llvm::inconvertibleErrorCode()));
+ }
+ const LangOptions &LangOpts = CI->getLangOpts();
+
+ tooling::SymbolName OldSymbolName(OldName, LangOpts);
+ tooling::SymbolName NewSymbolName(NewName, LangOpts);
+
+ llvm::StringMap> FilesToRanges;
+ for (auto Entry : Positions) {
+ std::vector &Ranges = FilesToRanges[Entry.first.file()];
+ for (Position Pos : Entry.second) {
+ // Compute the range for the given position:
+ // - If the old name is a simple identifier, we can add its length to the
+ // start position's column because identifiers can't contain newlines
+ // - If we have a multi-piece symbol name, them `editsForLocations` will
+ // only look at the start of the range to call
+ // `findObjCSymbolSelectorPieces`. It is thus fine to use an empty
+ // range that points to the symbol's start.
+ Position End = Pos;
+ if (std::optional Identifier =
+ OldSymbolName.getSinglePiece()) {
+ End.line += Identifier->size();
+ }
+ Ranges.push_back({Pos, End});
+ }
+ }
+ CB(editsForLocations(FilesToRanges, OldSymbolName, NewSymbolName,
+ *getHeaderFS().view(std::nullopt), LangOpts));
+}
+
namespace {
// May generate several candidate selections, due to SelectionTree ambiguity.
// vector of pointers because GCC doesn't like non-copyable Selection.
diff --git a/clang-tools-extra/clangd/ClangdServer.h b/clang-tools-extra/clangd/ClangdServer.h
index 4a1eae188f7eb..41adf728a4244 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -354,6 +354,17 @@ class ClangdServer {
void rename(PathRef File, Position Pos, llvm::StringRef NewName,
const RenameOptions &Opts, Callback CB);
+ /// Rename all occurrences of a symbol named `OldName` to `NewName` at the
+ /// given `Positions`.
+ ///
+ /// `PrimaryFile` is used to determine the language options for the symbol to
+ /// rename, eg. to decide whether `OldName` and `NewName` are Objective-C
+ /// selectors or normal identifiers.
+ void
+ indexedRename(const std::map> &Positions,
+ PathRef PrimaryFile, llvm::StringRef OldName,
+ llvm::StringRef NewName, Callback CB);
+
struct TweakRef {
std::string ID; /// ID to pass for applyTweak.
std::string Title; /// A single-line message to show in the UI.
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index e4df7581f1315..0bb5ee8840975 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -102,6 +102,7 @@ toCompletionItemKind(index::SymbolKind Kind,
// the same as Unknown
case SK::IncludeDirective:
case SK::Unknown:
+ case SK::CommentTag:
return CompletionItemKind::Missing;
case SK::Module:
case SK::Namespace:
diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp
index 560b8e00ed377..6438043e0ce52 100644
--- a/clang-tools-extra/clangd/Protocol.cpp
+++ b/clang-tools-extra/clangd/Protocol.cpp
@@ -301,6 +301,7 @@ SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind) {
// the same as Unknown
case index::SymbolKind::IncludeDirective:
case index::SymbolKind::Unknown:
+ case index::SymbolKind::CommentTag:
return SymbolKind::Variable;
case index::SymbolKind::Module:
return SymbolKind::Module;
@@ -1267,6 +1268,15 @@ llvm::json::Value toJSON(const PrepareRenameResult &PRR) {
};
}
+bool fromJSON(const llvm::json::Value &Params,
+ IndexedRenameParams &IndexedRename, llvm::json::Path P) {
+ llvm::json::ObjectMapper O(Params, P);
+ return O && O.map("textDocument", IndexedRename.textDocument) &&
+ O.map("oldName", IndexedRename.oldName) &&
+ O.map("newName", IndexedRename.newName) &&
+ O.map("positions", IndexedRename.positions);
+}
+
llvm::json::Value toJSON(const DocumentHighlight &DH) {
return llvm::json::Object{
{"range", toJSON(DH.range)},
diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h
index 2248572060431..588831a7b41e3 100644
--- a/clang-tools-extra/clangd/Protocol.h
+++ b/clang-tools-extra/clangd/Protocol.h
@@ -128,6 +128,23 @@ struct URIForFile {
llvm::json::Value toJSON(const URIForFile &U);
bool fromJSON(const llvm::json::Value &, URIForFile &, llvm::json::Path);
+template
+bool fromJSON(const llvm::json::Value &E, std::map &Out,
+ llvm::json::Path P) {
+ if (auto *O = E.getAsObject()) {
+ Out.clear();
+ for (const auto &KV : *O) {
+ URIForFile URI;
+ fromJSON(llvm::json::Value(KV.first), URI, P);
+ if (!fromJSON(KV.second, Out[URI], P.field(KV.first)))
+ return false;
+ }
+ return true;
+ }
+ P.report("expected object");
+ return false;
+}
+
struct TextDocumentIdentifier {
/// The text document's URI.
URIForFile uri;
@@ -1459,6 +1476,37 @@ struct PrepareRenameResult {
};
llvm::json::Value toJSON(const PrepareRenameResult &PRR);
+/// Rename all occurrences of a symbol named `oldName` to `newName` at the
+/// given `positions`.
+///
+/// The use case of this method is for when the positions to rename are already
+/// known, eg. from an index lookup outside of clangd's built-in index. In
+/// particular, it determines the edits necessary to rename multi-piece
+/// Objective-C selector names.
+///
+/// `textDocument` is used to determine the language options for the symbol to
+/// rename, eg. to decide whether `oldName` and `newName` are Objective-C
+/// selectors or normal identifiers.
+///
+/// This is a clangd extension.
+struct IndexedRenameParams {
+ /// The document in which the declaration to rename is declared. Its compiler
+ /// arguments are used to infer language settings for the rename.
+ TextDocumentIdentifier textDocument;
+
+ /// The old name of the symbol.
+ std::string oldName;
+
+ /// The new name of the symbol.
+ std::string newName;
+
+ /// The positions at which the symbol is known to appear and that should be
+ /// renamed.
+ std::map> positions;
+};
+bool fromJSON(const llvm::json::Value &, IndexedRenameParams &,
+ llvm::json::Path);
+
enum class DocumentHighlightKind { Text = 1, Read = 2, Write = 3 };
/// A document highlight is a range inside a text document which deserves
diff --git a/clang-tools-extra/clangd/Quality.cpp b/clang-tools-extra/clangd/Quality.cpp
index dc4afe18cb354..794a2683afee6 100644
--- a/clang-tools-extra/clangd/Quality.cpp
+++ b/clang-tools-extra/clangd/Quality.cpp
@@ -149,6 +149,7 @@ categorize(const index::SymbolInfo &D) {
case index::SymbolKind::Using:
case index::SymbolKind::Module:
case index::SymbolKind::Unknown:
+ case index::SymbolKind::CommentTag:
return SymbolQualitySignals::Unknown;
}
llvm_unreachable("Unknown index::SymbolKind");
diff --git a/clang-tools-extra/clangd/ScanningProjectModules.cpp b/clang-tools-extra/clangd/ScanningProjectModules.cpp
index 672e99632019d..a6967f376961e 100644
--- a/clang-tools-extra/clangd/ScanningProjectModules.cpp
+++ b/clang-tools-extra/clangd/ScanningProjectModules.cpp
@@ -37,7 +37,8 @@ class ModuleDependencyScanner {
const ThreadsafeFS &TFS)
: CDB(CDB), TFS(TFS),
Service(tooling::dependencies::ScanningMode::CanonicalPreprocessing,
- tooling::dependencies::ScanningOutputFormat::P1689) {}
+ tooling::dependencies::ScanningOutputFormat::P1689,
+ CASOptions(), nullptr, nullptr, nullptr) {}
/// The scanned modules dependency information for a specific source file.
struct ModuleDependencyInfo {
diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp
index c56375b1a98d3..f6d4678efdadf 100644
--- a/clang-tools-extra/clangd/refactor/Rename.cpp
+++ b/clang-tools-extra/clangd/refactor/Rename.cpp
@@ -42,6 +42,8 @@ namespace clang {
namespace clangd {
namespace {
+using tooling::SymbolName;
+
std::optional filePath(const SymbolLocation &Loc,
llvm::StringRef HintFilePath) {
if (!Loc)
@@ -1073,6 +1075,47 @@ bool operator<(const SymbolRange &LHS, const SymbolRange &RHS) {
return LHS.range() < RHS.range();
}
+llvm::Expected
+editsForLocations(const llvm::StringMap> &Ranges,
+ const SymbolName &OldName, const SymbolName &NewName,
+ llvm::vfs::FileSystem &FS, const LangOptions &LangOpts) {
+ FileEdits Results;
+ for (auto &FileAndOccurrences : Ranges) {
+ llvm::StringRef FilePath = FileAndOccurrences.first();
+
+ auto ExpBuffer = FS.getBufferForFile(FilePath);
+ if (!ExpBuffer) {
+ elog("Fail to read file content: Fail to open file {0}: {1}", FilePath,
+ ExpBuffer.getError().message());
+ continue;
+ }
+ std::string RenameIdentifier = OldName.getNamePieces()[0];
+ llvm::SmallVector NewNames(NewName.getNamePieces());
+
+ auto AffectedFileCode = (*ExpBuffer)->getBuffer();
+ auto OldNameRenameSymbolName = RenameSymbolName(OldName.getNamePieces());
+ auto RenameRanges =
+ adjustRenameRanges(AffectedFileCode, OldNameRenameSymbolName,
+ std::move(FileAndOccurrences.second), LangOpts);
+ if (!RenameRanges) {
+ // Our heuristics fails to adjust rename ranges to the current state of
+ // the file, it is most likely the index is stale, so we give up the
+ // entire rename.
+ return error("Index results don't match the content of file {0} "
+ "(the index may be stale)",
+ FilePath);
+ }
+ auto RenameEdit =
+ buildRenameEdit(FilePath, AffectedFileCode, *RenameRanges, NewNames);
+ if (!RenameEdit)
+ return error("failed to rename in file {0}: {1}", FilePath,
+ RenameEdit.takeError());
+ if (!RenameEdit->Replacements.empty())
+ Results.insert({FilePath, std::move(*RenameEdit)});
+ }
+ return Results;
+}
+
llvm::Expected rename(const RenameInputs &RInputs) {
assert(!RInputs.Index == !RInputs.FS &&
"Index and FS must either both be specified or both null.");
diff --git a/clang-tools-extra/clangd/refactor/Rename.h b/clang-tools-extra/clangd/refactor/Rename.h
index ed18a3959668f..6f26f0137c82e 100644
--- a/clang-tools-extra/clangd/refactor/Rename.h
+++ b/clang-tools-extra/clangd/refactor/Rename.h
@@ -13,6 +13,7 @@
#include "SourceCode.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Tooling/Refactoring/Rename/SymbolName.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Error.h"
#include
@@ -95,6 +96,22 @@ struct RenameInputs {
RenameOptions Opts = {};
};
+/// Compute the edits that need to be applied to rename symbols in `Ranges` from
+/// `OldName` to `NewName`. The key of `Ranges` is the file path of the file in
+/// which the range resides.
+///
+/// If `OldName` and `NewName` are single-piece identifiers, this just creates
+/// edits to change the ranges to `NewName`.
+///
+/// If `OldName` and `NewName` are multi-piece Objective-C selectors, only the
+/// start of the ranges is considered and the file is lexed to find the argument
+/// labels of the selector to rename.
+llvm::Expected
+editsForLocations(const llvm::StringMap> &Ranges,
+ const tooling::SymbolName &OldName,
+ const tooling::SymbolName &NewName, llvm::vfs::FileSystem &FS,
+ const LangOptions &LangOpts);
+
struct RenameResult {
// The range of the symbol that the user can attempt to rename.
Range Target;
diff --git a/clang-tools-extra/clangd/unittests/RenameTests.cpp b/clang-tools-extra/clangd/unittests/RenameTests.cpp
index 42279b51230e7..688ed286f7314 100644
--- a/clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ b/clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -1563,6 +1563,7 @@ TEST(RenameTest, PrepareRename) {
/*NewName=*/std::nullopt, {});
// Verify that for multi-file rename, we only return main-file occurrences.
ASSERT_TRUE(bool(Results)) << Results.takeError();
+ ASSERT_EQ(Results->Placeholder, "func");
// We don't know the result is complete in prepareRename (passing a nullptr
// index internally), so GlobalChanges should be empty.
EXPECT_TRUE(Results->GlobalChanges.empty());
@@ -1594,6 +1595,38 @@ TEST(RenameTest, PrepareRename) {
}
}
+TEST(RenameTest, PrepareRenameObjC) {
+ Annotations Input(R"cpp(
+ @interface Foo
+ - (int)performA^ction:(int)action w^ith:(int)value;
+ @end
+ @implementation Foo
+ - (int)performA^ction:(int)action w^ith:(int)value {
+ return [self ^performAction^:action ^w^ith^:value];
+ }
+ @end
+ )cpp");
+ std::string Path = testPath("foo.m");
+ MockFS FS;
+ FS.Files[Path] = std::string(Input.code());
+
+ auto ServerOpts = ClangdServer::optsForTest();
+ ServerOpts.BuildDynamicSymbolIndex = true;
+
+ trace::TestTracer Tracer;
+ MockCompilationDatabase CDB;
+ CDB.ExtraClangFlags = {"-xobjective-c"};
+ ClangdServer Server(CDB, FS, ServerOpts);
+ runAddDocument(Server, Path, Input.code());
+
+ for (Position Point : Input.points()) {
+ auto Results = runPrepareRename(Server, Path, Point,
+ /*NewName=*/std::nullopt, {});
+ ASSERT_TRUE(bool(Results)) << Results.takeError();
+ ASSERT_EQ(Results->Placeholder, "performAction:with:");
+ }
+}
+
TEST(CrossFileRenameTests, DirtyBuffer) {
Annotations FooCode("class [[Foo]] {};");
std::string FooPath = testPath("foo.cc");
@@ -2122,8 +2155,9 @@ TEST(CrossFileRenameTests, ObjC) {
}
@end
)cpp",
- }};
-
+ }
+ };
+
trace::TestTracer Tracer;
for (const auto &T : Cases) {
SCOPED_TRACE(T.FooH);
@@ -2499,6 +2533,130 @@ TEST(CrossFileRenameTests, adjustmentCost) {
}
}
+static URIForFile uriForPath(StringRef Path) {
+ URI Uri = llvm::cantFail(URI::parse(("file://" + Path).str()));
+ return llvm::cantFail(URIForFile::fromURI(Uri, /*HintPath=*/""));
+}
+
+TEST(IndexedRename, IndexedRename) {
+ MockCompilationDatabase CDB;
+ CDB.ExtraClangFlags = {"-xobjective-c"};
+ // rename is runnning on all "^" points in FooH, and "[[]]" ranges are the
+ // expected rename occurrences.
+ struct Case {
+ llvm::StringRef FooH;
+ llvm::StringRef FooM;
+ llvm::StringRef OldName;
+ llvm::StringRef NewName;
+ llvm::StringRef ExpectedFooH;
+ llvm::StringRef ExpectedFooM;
+ };
+ Case Cases[] = {
+ {
+ // Input
+ R"cpp(
+ void ^foo();
+ )cpp",
+ R"cpp(
+ void ^foo() {
+ return ^foo();
+ }
+ )cpp",
+ // Old name
+ "foo",
+ // New name
+ "bar",
+ // Expected
+ R"cpp(
+ void bar();
+ )cpp",
+ R"cpp(
+ void bar() {
+ return bar();
+ }
+ )cpp",
+ },
+ {
+ // Input
+ R"cpp(
+ @interface Foo
+ - (int)^performAction:(int)action with:(int)value;
+ @end
+ )cpp",
+ R"cpp(
+ @implementation Foo
+ - (int)^performAction:(int)action with:(int)value {
+ [self ^performAction:action with:value];
+ }
+ @end
+ )cpp",
+ // Old name
+ "performAction:with:",
+ // New name
+ "performNewAction:by:",
+ // Expected
+ R"cpp(
+ @interface Foo
+ - (int)performNewAction:(int)action by:(int)value;
+ @end
+ )cpp",
+ R"cpp(
+ @implementation Foo
+ - (int)performNewAction:(int)action by:(int)value {
+ [self performNewAction:action by:value];
+ }
+ @end
+ )cpp",
+ }
+ };
+ trace::TestTracer Tracer;
+ for (const auto &T : Cases) {
+ SCOPED_TRACE(T.FooH);
+ Annotations FooH(T.FooH);
+ Annotations FooM(T.FooM);
+ std::string FooHPath = testPath("foo.h");
+ std::string FooMPath = testPath("foo.m");
+
+ MockFS FS;
+ FS.Files[FooHPath] = std::string(FooH.code());
+ FS.Files[FooMPath] = std::string(FooM.code());
+
+ auto ServerOpts = ClangdServer::optsForTest();
+ ClangdServer Server(CDB, FS, ServerOpts);
+
+ std::map> Positions;
+ Positions[uriForPath(FooHPath)] = FooH.points();
+ Positions[uriForPath(FooMPath)] = FooM.points();
+ FileEdits Edits = llvm::cantFail(
+ runIndexedRename(Server, Positions, FooHPath, T.OldName, T.NewName));
+
+ EXPECT_THAT(applyEdits(std::move(Edits)),
+ UnorderedElementsAre(Pair(Eq(FooHPath), Eq(T.ExpectedFooH)),
+ Pair(Eq(FooMPath), Eq(T.ExpectedFooM))));
+ }
+}
+
+TEST(IndexedRename, IndexedRenameDoesntCrashIfNoCompilerCommandsExistForFile) {
+ Annotations FooM(R"cpp(
+ void ^foo();
+ )cpp");
+ std::string Path = testPath("foo.swift");
+
+ MockFS FS;
+ FS.Files[Path] = std::string(FooM.code());
+
+ auto ServerOpts = ClangdServer::optsForTest();
+ MockCompilationDatabase CDB;
+ ClangdServer Server(CDB, FS, ServerOpts);
+
+ std::map> Positions;
+ Positions[uriForPath(Path)] = FooM.points();
+ llvm::Expected Edits =
+ runIndexedRename(Server, Positions, Path, "cFunc", "dFunc");
+ EXPECT_FALSE((bool)Edits);
+ consumeError(Edits.takeError());
+}
+
} // namespace
} // namespace clangd
} // namespace clang
diff --git a/clang-tools-extra/clangd/unittests/SyncAPI.cpp b/clang-tools-extra/clangd/unittests/SyncAPI.cpp
index 7e8c8e22acf95..f0e31a6fa32ce 100644
--- a/clang-tools-extra/clangd/unittests/SyncAPI.cpp
+++ b/clang-tools-extra/clangd/unittests/SyncAPI.cpp
@@ -106,6 +106,15 @@ llvm::Expected runRename(ClangdServer &Server, PathRef File,
return std::move(*Result);
}
+llvm::Expected runIndexedRename(
+ ClangdServer &Server, std::map> Positions,
+ PathRef PrimaryFile, llvm::StringRef OldName, llvm::StringRef NewName) {
+ std::optional> Result;
+ Server.indexedRename(Positions, PrimaryFile, OldName, NewName,
+ capture(Result));
+ return std::move(*Result);
+}
+
llvm::Expected
runPrepareRename(ClangdServer &Server, PathRef File, Position Pos,
std::optional NewName,
diff --git a/clang-tools-extra/clangd/unittests/SyncAPI.h b/clang-tools-extra/clangd/unittests/SyncAPI.h
index 35ebd2574dda3..89dfd8ac6416f 100644
--- a/clang-tools-extra/clangd/unittests/SyncAPI.h
+++ b/clang-tools-extra/clangd/unittests/SyncAPI.h
@@ -47,6 +47,10 @@ llvm::Expected runRename(ClangdServer &Server, PathRef File,
Position Pos, StringRef NewName,
const clangd::RenameOptions &RenameOpts);
+llvm::Expected runIndexedRename(
+ ClangdServer &Server, std::map> Positions,
+ PathRef PrimaryFile, llvm::StringRef OldName, llvm::StringRef NewName);
+
llvm::Expected
runPrepareRename(ClangdServer &Server, PathRef File, Position Pos,
std::optional NewName,
diff --git a/clang/CONTRIBUTING.md b/clang/CONTRIBUTING.md
new file mode 100644
index 0000000000000..a0c1644fc66a2
--- /dev/null
+++ b/clang/CONTRIBUTING.md
@@ -0,0 +1,14 @@
+By submitting a pull request, you represent that you have the right to license
+your contribution to Apple and the community, and agree by submitting the patch
+that your contributions are licensed under the [Swift
+license](https://swift.org/LICENSE.txt).
+
+---
+
+Changes to this repository follow special considerations as described on
+Swift.org under "[LLVM and Swift](https://swift.org/contributing/#llvm-and-swift)".
+Please make sure your change is appropriate for this repository.
+
+Before submitting a pull request, please make sure you have tested your
+changes and that they follow the Swift project [guidelines for contributing
+code](https://swift.org/contributing/#contributing-code).
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index da97bd375608c..e03f3155b0f38 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -1109,6 +1109,12 @@ def is_unexposed(self):
# Represents a C++26 pack indexing expression.
PACK_INDEXING_EXPR = 156
+ # TO_UPSTREAM(BoundsSafety) ON
+ FORGE_PTR_EXPR = 198
+ GET_BOUND_EXPR = 199
+ LAST_EXPR = GET_BOUND_EXPR
+ # TO_UPSTREAM(BoundsSafety) OFF
+
# A statement whose specific kind is not exposed via this interface.
#
# Unexposed statements have the same operations as any other kind of
diff --git a/clang/cmake/caches/Apple-stage2.cmake b/clang/cmake/caches/Apple-stage2.cmake
index e919c56739679..2e1ccec785aa2 100644
--- a/clang/cmake/caches/Apple-stage2.cmake
+++ b/clang/cmake/caches/Apple-stage2.cmake
@@ -56,6 +56,8 @@ set(LLVM_TOOLCHAIN_TOOLS
llvm-size
llvm-cxxfilt
llvm-config
+ llvm-cas
+ llvm-cas-dump
CACHE STRING "")
set(LLVM_BUILD_UTILS ON CACHE BOOL "")
@@ -73,6 +75,7 @@ set(LLVM_DISTRIBUTION_COMPONENTS
clang-format
clang-resource-headers
Remarks
+ clang-features-file
${LLVM_TOOLCHAIN_TOOLS}
${LLVM_TOOLCHAIN_UTILITIES}
CACHE STRING "")
diff --git a/clang/docs/PointerAuthentication.rst b/clang/docs/PointerAuthentication.rst
index 7e65f4b1b4915..83f089cc4b0be 100644
--- a/clang/docs/PointerAuthentication.rst
+++ b/clang/docs/PointerAuthentication.rst
@@ -52,8 +52,8 @@ This document serves four purposes:
ways in which programmers can strengthen its protections (including
recommendations for language implementors).
-- It documents the stable ABI of the C, C++, and Objective-C languages on arm64e
- platforms.
+- It documents the stable ABI of the C, C++, Objective-C, and Swift languages on
+ arm64e platforms.
Basic concepts
@@ -722,7 +722,7 @@ remove the signature.
as ``pointer``. This operation is not required to have the same behavior on
a null pointer that the language implementation would.
-In the future when Clang makes safe derivation guarantees, the result of
+In the future when Clang makes `safe derivation`_ guarantees, the result of
this operation should be considered safely-derived.
``ptrauth_sign_generic_data``
@@ -1663,6 +1663,80 @@ or less safely, and introducing the possibility of an
:ref:`signing or authentication oracle`, an unauthencaticated
temporary may be used as intermediate storage.
+Swift class methods
+~~~~~~~~~~~~~~~~~~~
+
+Class methods in Swift are signed in the class object with the ``IA`` key using
+address diversity and a constant discriminator equal to the string hash (see
+`ptrauth_string_discriminator`_) of the mangling of the original overridable
+method.
+
+Resilient class-method lookup relies on passing a method descriptor; this method
+descriptor should be signed but currently isn't. The lookup function returns a
+function pointer that is signed using ``IA`` without address diversity and with
+the correct constant discriminator for the looked-up method.
+
+Swift's equivalent of a C++ v-table pointer is the ``isa`` pointer of an object.
+On arm64e, this is constrained by Objective-C compatibility and so has the
+same :ref:`C signing schema`.
+
+Swift heap destructors
+~~~~~~~~~~~~~~~~~~~~~~
+
+Objects that are retained and released with Swift's native reference-counting
+system, including both native classes and temporary "box" allocations, must
+provide a destructor function in their metadata. This destructor function is
+signed with the ``IA`` key using address diversity and a constant discriminator
+of ``0xbbbf``.
+
+Swift protocol requirements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Protocol function requirements are signed in the protocol witness table with the
+``IA`` key using address diversity and a constant discriminator equal to the
+string hash (see `ptrauth_string_discriminator`_) of the mangling of the
+protocol requirement.
+
+Swift function types
+~~~~~~~~~~~~~~~~~~~~
+
+The invocation pointers of Swift function values are signed using the ``IA`` key
+without address diversity and with a constant discriminator derived loosely from
+the function type.
+
+Address diversity cannot be used by default for function values because function
+types are intended to be a "loadable" type which can be held and passed in
+registers.
+
+The constant discriminator currently accounts for potential abstraction in the
+function signature in ways that decrease the diversity of signatures; improving
+this is under investigation.
+
+Swift metadata
+~~~~~~~~~~~~~~
+
+Type metadata pointers in Swift are not signed.
+
+Type context descriptors must be signed because they frequently contain
+`relative addresses`_. Type context descriptors are signed with the ``DA`` key
+without address diversity (except when stored in type metadata) and with a
+constant discriminator of ``0xae86``.
+
+Swift value witnesses
+~~~~~~~~~~~~~~~~~~~~~
+
+Value witness functions in Swift are signed in the value witness table using the
+``IA`` key with address diversity and an operation-specific constant
+discriminator which can be found in the Swift project headers.
+
+Swift coroutines
+~~~~~~~~~~~~~~~~
+
+Resumption functions for Swift coroutines are signed using the ``IA`` key
+without address diversity and with a constant discriminator derived from the
+yield type of the coroutine. Resumption functions cannot be signed with address
+diversity as they are returned directly in registers from the coroutine.
+
Alternative implementations
---------------------------
diff --git a/clang/include/clang-c/CAS.h b/clang/include/clang-c/CAS.h
new file mode 100644
index 0000000000000..a9aecbc6c51f6
--- /dev/null
+++ b/clang/include/clang-c/CAS.h
@@ -0,0 +1,390 @@
+/*==-- clang-c/CAS.h - CAS Interface ------------------------------*- C -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header provides interfaces for creating and working with CAS and *|
+|* ActionCache interfaces. *|
+|* *|
+|* An example of its usage is available in c-index-test/core_main.cpp. *|
+|* *|
+|* EXPERIMENTAL: These interfaces are experimental and will change. If you *|
+|* use these be prepared for them to change without notice on any commit. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_CLANG_C_CAS_H
+#define LLVM_CLANG_C_CAS_H
+
+#include "clang-c/CXErrorCode.h"
+#include "clang-c/CXString.h"
+#include "clang-c/Platform.h"
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \defgroup CAS CAS and ActionCache interface.
+ * @{
+ */
+
+/**
+ * Configuration options for ObjectStore and ActionCache.
+ */
+typedef struct CXOpaqueCASOptions *CXCASOptions;
+
+/**
+ * Encapsulates instances of ObjectStore and ActionCache, created from a
+ * particular configuration of \p CXCASOptions.
+ */
+typedef struct CXOpaqueCASDatabases *CXCASDatabases;
+
+/**
+ * Content-addressable storage for objects.
+ */
+typedef struct CXOpaqueCASObjectStore *CXCASObjectStore;
+
+/**
+ * A cache from a key describing an action to the result of doing it.
+ */
+typedef struct CXOpaqueCASActionCache *CXCASActionCache;
+
+typedef struct CXOpaqueCASObject *CXCASObject;
+
+/**
+ * Result of \c clang_experimental_cas_getCachedCompilation.
+ */
+typedef struct CXOpaqueCASCachedCompilation *CXCASCachedCompilation;
+
+/**
+ * Result of \c clang_experimental_cas_replayCompilation.
+ */
+typedef struct CXOpaqueCASReplayResult *CXCASReplayResult;
+
+/**
+ * Used for cancelling asynchronous actions.
+ */
+typedef struct CXOpaqueCASCancellationToken *CXCASCancellationToken;
+
+/**
+ * Create a \c CXCASOptions object.
+ */
+CINDEX_LINKAGE CXCASOptions clang_experimental_cas_Options_create(void);
+
+/**
+ * Dispose of a \c CXCASOptions object.
+ */
+CINDEX_LINKAGE void clang_experimental_cas_Options_dispose(CXCASOptions);
+
+/**
+ * Configure the file path to use for on-disk CAS/cache instances.
+ */
+CINDEX_LINKAGE void
+clang_experimental_cas_Options_setOnDiskPath(CXCASOptions, const char *Path);
+
+/**
+ * Configure the path to a library that implements the LLVM CAS plugin API.
+ */
+CINDEX_LINKAGE void
+clang_experimental_cas_Options_setPluginPath(CXCASOptions, const char *Path);
+
+/**
+ * Set a value for a named option that the CAS plugin supports.
+ */
+CINDEX_LINKAGE void
+clang_experimental_cas_Options_setPluginOption(CXCASOptions, const char *Name,
+ const char *Value);
+
+/**
+ * Creates instances for a CAS object store and action cache based on the
+ * configuration of a \p CXCASOptions.
+ *
+ * \param Opts configuration options.
+ * \param[out] Error The error string to pass back to client (if any).
+ *
+ * \returns The resulting instances object, or null if there was an error.
+ */
+CINDEX_LINKAGE CXCASDatabases
+clang_experimental_cas_Databases_create(CXCASOptions Opts, CXString *Error);
+
+/**
+ * Dispose of a \c CXCASDatabases object.
+ */
+CINDEX_LINKAGE void clang_experimental_cas_Databases_dispose(CXCASDatabases);
+
+/**
+ * Get the local storage size of the CAS/cache data in bytes.
+ *
+ * \param[out] OutError The error object to pass back to client (if any).
+ * If non-null the object must be disposed using \c clang_Error_dispose.
+ * \returns the local storage size of the CAS/cache data, or -1 if the
+ * implementation does not support reporting such size, or -2 if an error
+ * occurred.
+ */
+CINDEX_LINKAGE int64_t clang_experimental_cas_Databases_get_storage_size(
+ CXCASDatabases, CXError *OutError);
+
+/**
+ * Set the size for limiting disk storage growth.
+ *
+ * \param size_limit the maximum size limit in bytes. 0 means no limit. Negative
+ * values are invalid.
+ * \returns an error object if there was an error, NULL otherwise.
+ * If non-null the object must be disposed using \c clang_Error_dispose.
+ */
+CINDEX_LINKAGE CXError clang_experimental_cas_Databases_set_size_limit(
+ CXCASDatabases, int64_t size_limit);
+
+/**
+ * Prune local storage to reduce its size according to the desired size limit.
+ * Pruning can happen concurrently with other operations.
+ *
+ * \returns an error object if there was an error, NULL otherwise.
+ * If non-null the object must be disposed using \c clang_Error_dispose.
+ */
+CINDEX_LINKAGE
+CXError clang_experimental_cas_Databases_prune_ondisk_data(CXCASDatabases);
+
+/**
+ * Checks whether an object is materialized in the database using its printed
+ * \p CASID.
+ *
+ * \param CASID The printed CASID string for the object.
+ * \param[out] OutError The error object to pass back to client (if any).
+ * If non-null the object must be disposed using \c clang_Error_dispose.
+ *
+ * \returns whether the object is materialized in the database.
+ */
+CINDEX_LINKAGE bool clang_experimental_cas_isMaterialized(CXCASDatabases,
+ const char *CASID,
+ CXError *OutError);
+
+/**
+ * Loads an object using its printed \p CASID.
+ *
+ * \param CASID The printed CASID string for the object.
+ * \param[out] OutError The error object to pass back to client (if any).
+ * If non-null the object must be disposed using \c clang_Error_dispose.
+ *
+ * \returns The resulting object, or null if the object was not found or an
+ * error occurred. The object should be disposed using
+ * \c clang_experimental_cas_CASObject_dispose.
+ */
+CINDEX_LINKAGE CXCASObject clang_experimental_cas_loadObjectByString(
+ CXCASDatabases, const char *CASID, CXError *OutError);
+
+/**
+ * Asynchronous version of \c clang_experimental_cas_loadObjectByString.
+ *
+ * \param CASID The printed CASID string for the object.
+ * \param Ctx opaque value to pass to the callback.
+ * \param Callback receives a \c CXCASObject, or \c CXError if an error occurred
+ * or both NULL if the object was not found or the call was cancelled.
+ * The objects should be disposed with
+ * \c clang_experimental_cas_CASObject_dispose or \c clang_Error_dispose.
+ * \param[out] OutToken if non-null receives a \c CXCASCancellationToken that
+ * can be used to cancel the call using
+ * \c clang_experimental_cas_CancellationToken_cancel. The object should be
+ * disposed using \c clang_experimental_cas_CancellationToken_dispose.
+ */
+CINDEX_LINKAGE void clang_experimental_cas_loadObjectByString_async(
+ CXCASDatabases, const char *CASID, void *Ctx,
+ void (*Callback)(void *Ctx, CXCASObject, CXError),
+ CXCASCancellationToken *OutToken);
+
+/**
+ * Dispose of a \c CXCASObject object.
+ */
+CINDEX_LINKAGE void clang_experimental_cas_CASObject_dispose(CXCASObject);
+
+/**
+ * Looks up a cache key and returns the associated set of compilation output IDs
+ *
+ * \param CacheKey The printed compilation cache key string.
+ * \param Globally if true it is a hint to the underlying CAS implementation
+ * that the lookup is profitable to be done on a distributed caching level, not
+ * just locally.
+ * \param[out] OutError The error object to pass back to client (if any).
+ * If non-null the object must be disposed using \c clang_Error_dispose.
+ *
+ * \returns The resulting object, or null if the cache key was not found or an
+ * error occurred. The object should be disposed using
+ * \c clang_experimental_cas_CachedCompilation_dispose.
+ */
+CINDEX_LINKAGE CXCASCachedCompilation
+clang_experimental_cas_getCachedCompilation(CXCASDatabases,
+ const char *CacheKey, bool Globally,
+ CXError *OutError);
+
+/**
+ * Asynchronous version of \c clang_experimental_cas_getCachedCompilation.
+ *
+ * \param CacheKey The printed compilation cache key string.
+ * \param Globally if true it is a hint to the underlying CAS implementation
+ * that the lookup is profitable to be done on a distributed caching level, not
+ * just locally.
+ * \param Ctx opaque value to pass to the callback.
+ * \param Callback receives a \c CXCASCachedCompilation, or \c CXError if an
+ * error occurred or both NULL if the object was not found or the call was
+ * cancelled. The objects should be disposed with
+ * \c clang_experimental_cas_CachedCompilation_dispose or \c clang_Error_dispose
+ * \param[out] OutToken if non-null receives a \c CXCASCancellationToken that
+ * can be used to cancel the call using
+ * \c clang_experimental_cas_CancellationToken_cancel. The object should be
+ * disposed using \c clang_experimental_cas_CancellationToken_dispose.
+ */
+CINDEX_LINKAGE void clang_experimental_cas_getCachedCompilation_async(
+ CXCASDatabases, const char *CacheKey, bool Globally, void *Ctx,
+ void (*Callback)(void *Ctx, CXCASCachedCompilation, CXError),
+ CXCASCancellationToken *OutToken);
+
+/**
+ * Dispose of a \c CXCASCachedCompilation object.
+ */
+CINDEX_LINKAGE void
+ clang_experimental_cas_CachedCompilation_dispose(CXCASCachedCompilation);
+
+/**
+ * \returns number of compilation outputs.
+ */
+CINDEX_LINKAGE size_t clang_experimental_cas_CachedCompilation_getNumOutputs(
+ CXCASCachedCompilation);
+
+/**
+ * \returns the compilation output name given the index via \p OutputIdx.
+ */
+CINDEX_LINKAGE CXString clang_experimental_cas_CachedCompilation_getOutputName(
+ CXCASCachedCompilation, size_t OutputIdx);
+
+/**
+ * \returns the compilation output printed CASID given the index via
+ * \p OutputIdx.
+ */
+CINDEX_LINKAGE CXString
+clang_experimental_cas_CachedCompilation_getOutputCASIDString(
+ CXCASCachedCompilation, size_t OutputIdx);
+
+/**
+ * \returns whether the compilation output data exist in the local CAS given the
+ * index via \p OutputIdx.
+ */
+CINDEX_LINKAGE bool
+clang_experimental_cas_CachedCompilation_isOutputMaterialized(
+ CXCASCachedCompilation, size_t OutputIdx);
+
+/**
+ * If distributed caching is available it uploads the compilation outputs and
+ * the association of key <-> outputs to the distributed cache.
+ * This allows separating the task of computing the compilation outputs and
+ * storing them in the local cache, from the task of "uploading" them.
+ *
+ * \param Ctx opaque value to pass to the callback.
+ * \param Callback receives a \c CXError if an error occurred. The error will be
+ * NULL if the call was successful or cancelled. The error should be disposed
+ * via \c clang_Error_dispose.
+ * \param[out] OutToken if non-null receives a \c CXCASCancellationToken that
+ * can be used to cancel the call using
+ * \c clang_experimental_cas_CancellationToken_cancel. The object should be
+ * disposed using \c clang_experimental_cas_CancellationToken_dispose.
+ */
+CINDEX_LINKAGE void clang_experimental_cas_CachedCompilation_makeGlobal(
+ CXCASCachedCompilation, void *Ctx, void (*Callback)(void *Ctx, CXError),
+ CXCASCancellationToken *OutToken);
+
+/**
+ * Replays a cached compilation by writing the cached outputs to the filesystem
+ * and/or stderr based on the given compilation arguments.
+ *
+ * \param argc number of compilation arguments.
+ * \param argv array of compilation arguments.
+ * \param WorkingDirectory working directory to use, can be NULL.
+ * \param reserved for future use, caller must pass NULL.
+ * \param[out] OutError The error object to pass back to client (if any).
+ * If non-null the object must be disposed using \c clang_Error_dispose.
+ *
+ * \returns a \c CXCASReplayResult object or NULL if an error occurred or a
+ * compilation output was not found in the CAS. The object should be disposed
+ * via \c clang_experimental_cas_ReplayResult_dispose.
+ */
+CINDEX_LINKAGE CXCASReplayResult clang_experimental_cas_replayCompilation(
+ CXCASCachedCompilation, int argc, const char *const *argv,
+ const char *WorkingDirectory, void *reserved, CXError *OutError);
+
+/**
+ * Dispose of a \c CXCASReplayResult object.
+ */
+CINDEX_LINKAGE void
+ clang_experimental_cas_ReplayResult_dispose(CXCASReplayResult);
+
+/**
+ * Get the diagnostic text of a replayed cached compilation.
+ */
+CINDEX_LINKAGE
+CXString clang_experimental_cas_ReplayResult_getStderr(CXCASReplayResult);
+
+/**
+ * Cancel an asynchronous CAS-related action.
+ */
+CINDEX_LINKAGE void
+ clang_experimental_cas_CancellationToken_cancel(CXCASCancellationToken);
+
+/**
+ * Dispose of a \c CXCASCancellationToken object.
+ */
+CINDEX_LINKAGE void
+ clang_experimental_cas_CancellationToken_dispose(CXCASCancellationToken);
+
+/**
+ * Dispose of a \c CXCASObjectStore object.
+ */
+CINDEX_LINKAGE void
+clang_experimental_cas_ObjectStore_dispose(CXCASObjectStore CAS);
+
+/**
+ * Dispose of a \c CXCASActionCache object.
+ */
+CINDEX_LINKAGE void
+clang_experimental_cas_ActionCache_dispose(CXCASActionCache Cache);
+
+/**
+ * Gets or creates a persistent on-disk CAS object store at \p Path.
+ * Deprecated, use \p clang_experimental_cas_Databases_create() instead.
+ *
+ * \param Path The path to locate the object store.
+ * \param[out] Error The error string to pass back to client (if any).
+ *
+ * \returns The resulting object store, or null if there was an error.
+ */
+CINDEX_DEPRECATED CINDEX_LINKAGE CXCASObjectStore
+clang_experimental_cas_OnDiskObjectStore_create(const char *Path,
+ CXString *Error);
+
+/**
+ * Gets or creates a persistent on-disk action cache at \p Path.
+ * Deprecated, use \p clang_experimental_cas_Databases_create() instead.
+ *
+ * \param Path The path to locate the object store.
+ * \param[out] Error The error string to pass back to client (if any).
+ *
+ * \returns The resulting object store, or null if there was an error.
+ */
+CINDEX_DEPRECATED CINDEX_LINKAGE CXCASActionCache
+clang_experimental_cas_OnDiskActionCache_create(const char *Path,
+ CXString *Error);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LLVM_CLANG_C_CAS_H
diff --git a/clang/include/clang-c/CXDiagnostic.h b/clang/include/clang-c/CXDiagnostic.h
index 911d001f06697..faa7e816de47e 100644
--- a/clang/include/clang-c/CXDiagnostic.h
+++ b/clang/include/clang-c/CXDiagnostic.h
@@ -148,6 +148,30 @@ CINDEX_LINKAGE void clang_disposeDiagnosticSet(CXDiagnosticSet Diags);
*/
CINDEX_LINKAGE CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic D);
+/**
+ * Get the contents if the given file that was provided via diagnostics.
+ *
+ * \param diags the diagnostics set to query for the contents of the file.
+ * \param file the file to get the contents of.
+ * \param outFileSize if non-null, set to the file size on success.
+ * \returns on success, a pointer to the file contents. Otherwise, NULL.
+ */
+CINDEX_LINKAGE const char *clang_getDiagnosticFileContents(
+ CXDiagnosticSet diags, CXFile file, size_t *outFileSize);
+
+/**
+ * Retrieve the original source range if the given file was provided via
+ * diagnostics and is conceptually a replacement for the original source range.
+ *
+ * \param diags the diagnostics set to query for the contents of the file.
+ * \param file the file to get the contents of.
+ * \returns on success, the source range (into another file) that is
+ * conceptually replaced by the contents of the given file (available via
+ * \c clang_getDiagnosticFileContents).
+ */
+CINDEX_LINKAGE CXSourceRange clang_getDiagnosticFileOriginalSourceRange(
+ CXDiagnosticSet diags, CXFile file);
+
/**
* Destroy a diagnostic.
*/
@@ -314,6 +338,14 @@ clang_getDiagnosticCategoryName(unsigned Category);
*/
CINDEX_LINKAGE CXString clang_getDiagnosticCategoryText(CXDiagnostic);
+/**
+ * Retrieve the diagnostic category's URL for a given diagnostic.
+ *
+ * \returns The URL that provides additional documentation for the
+ * category of this diagnostic.
+ */
+CINDEX_LINKAGE CXString clang_getDiagnosticCategoryURL(CXDiagnostic);
+
/**
* Determine the number of source ranges associated with the given
* diagnostic.
diff --git a/clang/include/clang-c/CXErrorCode.h b/clang/include/clang-c/CXErrorCode.h
index b3a0b9d66d5f8..e284b2843a7ff 100644
--- a/clang/include/clang-c/CXErrorCode.h
+++ b/clang/include/clang-c/CXErrorCode.h
@@ -53,9 +53,47 @@ enum CXErrorCode {
/**
* An AST deserialization error has occurred.
*/
- CXError_ASTReadError = 4
+ CXError_ASTReadError = 4,
+
+ /**
+ * \brief A refactoring action is not available at the given location
+ * or in the given source range.
+ */
+ CXError_RefactoringActionUnavailable = 5,
+
+ /**
+ * \brief A refactoring action is not able to use the given name because
+ * it contains an unexpected number of strings.
+ */
+ CXError_RefactoringNameSizeMismatch = 6,
+
+ /**
+ * \brief A name of a symbol is invalid, i.e. it is reserved by the source
+ * language and can't be used as a name for this symbol.
+ */
+ CXError_RefactoringNameInvalid = 7
};
+/**
+ * Represents an error with error code and description string.
+ */
+typedef struct CXOpaqueError *CXError;
+
+/**
+ * \returns the error code.
+ */
+CINDEX_LINKAGE enum CXErrorCode clang_Error_getCode(CXError);
+
+/**
+ * \returns the error description string.
+ */
+CINDEX_LINKAGE const char *clang_Error_getDescription(CXError);
+
+/**
+ * Dispose of a \c CXError object.
+ */
+CINDEX_LINKAGE void clang_Error_dispose(CXError);
+
LLVM_CLANG_C_EXTERN_C_END
#endif
diff --git a/clang/include/clang-c/CXString.h b/clang/include/clang-c/CXString.h
index 63dce4d140ce2..47909540537c4 100644
--- a/clang/include/clang-c/CXString.h
+++ b/clang/include/clang-c/CXString.h
@@ -16,6 +16,7 @@
#include "clang-c/ExternC.h"
#include "clang-c/Platform.h"
+#include
LLVM_CLANG_C_EXTERN_C_BEGIN
@@ -44,6 +45,14 @@ typedef struct {
unsigned Count;
} CXStringSet;
+/**
+ * An array of C strings.
+ */
+typedef struct {
+ const char **Strings;
+ size_t Count;
+} CXCStringArray;
+
/**
* Retrieve the character data associated with the given string.
*
diff --git a/clang/include/clang-c/Dependencies.h b/clang/include/clang-c/Dependencies.h
new file mode 100644
index 0000000000000..511f7ba837afa
--- /dev/null
+++ b/clang/include/clang-c/Dependencies.h
@@ -0,0 +1,804 @@
+/*==-- clang-c/Dependencies.h - Dependency Discovery C Interface --*- C -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header provides a dependency discovery interface similar to *|
+|* clang-scan-deps. *|
+|* *|
+|* An example of its usage is available in c-index-test/core_main.cpp. *|
+|* *|
+|* EXPERIMENTAL: These interfaces are experimental and will change. If you *|
+|* use these be prepared for them to change without notice on any commit. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_CLANG_C_DEPENDENCIES_H
+#define LLVM_CLANG_C_DEPENDENCIES_H
+
+#include "clang-c/BuildSystem.h"
+#include "clang-c/CAS.h"
+#include "clang-c/CXDiagnostic.h"
+#include "clang-c/CXErrorCode.h"
+#include "clang-c/CXString.h"
+#include "clang-c/Platform.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \defgroup SCAN_DEPS Dependency scanning service.
+ * @{
+ */
+
+/**
+ * An output file kind needed by module dependencies.
+ */
+typedef enum {
+ CXOutputKind_ModuleFile = 0,
+ CXOutputKind_Dependencies = 1,
+ CXOutputKind_DependenciesTarget = 2,
+ CXOutputKind_SerializedDiagnostics = 3,
+} CXOutputKind;
+
+/**
+ * Object encapsulating instance of a dependency scanner service.
+ *
+ * The dependency scanner service is a global instance that owns the
+ * global cache and other global state that's shared between the dependency
+ * scanner workers. The service APIs are thread safe.
+ *
+ * The service aims to provide a consistent view of file content throughout
+ * its lifetime. A client that wants to see changes to file content should
+ * create a new service at the time. For example, a build system might use
+ * one service for each build.
+ *
+ * TODO: Consider using DirectoryWatcher to get notified about file changes
+ * and adding an API that allows clients to invalidate changed files. This
+ * could allow a build system to reuse a single service between builds.
+ */
+typedef struct CXOpaqueDependencyScannerService *CXDependencyScannerService;
+
+/**
+ * The mode to report module dependencies in.
+ */
+typedef enum {
+ /**
+ * Flatten all module dependencies. This reports the full transitive set of
+ * header and module map dependencies needed to do an implicit module build.
+ */
+ CXDependencyMode_Flat,
+
+ /**
+ * Report the full module graph. This reports only the direct dependencies of
+ * each file, and calls a callback for each module that is discovered.
+ */
+ CXDependencyMode_Full,
+} CXDependencyMode;
+
+/**
+ * Options used to construct a \c CXDependencyScannerService.
+ */
+typedef struct CXOpaqueDependencyScannerServiceOptions
+ *CXDependencyScannerServiceOptions;
+
+/**
+ * Creates a default set of service options.
+ * Must be disposed with \c
+ * clang_experimental_DependencyScannerServiceOptions_dispose.
+ */
+CINDEX_LINKAGE CXDependencyScannerServiceOptions
+clang_experimental_DependencyScannerServiceOptions_create(void);
+
+/**
+ * Dispose of a \c CXDependencyScannerServiceOptions object.
+ */
+CINDEX_LINKAGE void clang_experimental_DependencyScannerServiceOptions_dispose(
+ CXDependencyScannerServiceOptions);
+
+/**
+ * Specify a \c CXDependencyMode in the given options.
+ */
+CINDEX_LINKAGE void
+clang_experimental_DependencyScannerServiceOptions_setDependencyMode(
+ CXDependencyScannerServiceOptions Opts, CXDependencyMode Mode);
+
+/**
+ * Specify the object store and action cache databases in the given options.
+ * With this set, the scanner will produce cached commands.
+ */
+CINDEX_LINKAGE void
+clang_experimental_DependencyScannerServiceOptions_setCASDatabases(
+ CXDependencyScannerServiceOptions Opts, CXCASDatabases);
+
+/**
+ * Specify the specific CAS options for the scanner to use for the produced
+ * compiler arguments.
+ */
+CINDEX_LINKAGE void
+clang_experimental_DependencyScannerServiceOptions_setCASOptions(
+ CXDependencyScannerServiceOptions Opts, CXCASOptions);
+
+/**
+ * Set the working directory optimization option.
+ * The dependency scanner service option Opts will indicate to the scanner that
+ * the current working directory can or cannot be ignored when computing the
+ * pcms' context hashes. The scanner will then determine if it is safe to
+ * optimize each module and act accordingly.
+ *
+ * \param Value If it is non zero, the option is on. Otherwise the
+ * option is off.
+ */
+CINDEX_LINKAGE void
+clang_experimental_DependencyScannerServiceOptions_setCWDOptimization(
+ CXDependencyScannerServiceOptions Opts, int Value);
+
+/**
+ * Specify a \c CXCASObjectStore in the given options. If an object store and
+ * action cache are available, the scanner will produce cached commands.
+ * Deprecated, use
+ * \p clang_experimental_DependencyScannerServiceOptions_setCASDatabases()
+ * instead.
+ */
+CINDEX_DEPRECATED CINDEX_LINKAGE void
+clang_experimental_DependencyScannerServiceOptions_setObjectStore(
+ CXDependencyScannerServiceOptions Opts, CXCASObjectStore CAS);
+
+/**
+ * Specify a \c CXCASActionCache in the given options. If an object store and
+ * action cache are available, the scanner will produce cached commands.
+ * Deprecated, use
+ * \p clang_experimental_DependencyScannerServiceOptions_setCASDatabases()
+ * instead.
+ */
+CINDEX_DEPRECATED CINDEX_LINKAGE void
+clang_experimental_DependencyScannerServiceOptions_setActionCache(
+ CXDependencyScannerServiceOptions Opts, CXCASActionCache Cache);
+
+/**
+ * Create a \c CXDependencyScannerService object.
+ * Must be disposed with \c
+ * clang_experimental_DependencyScannerService_dispose_v0().
+ */
+CINDEX_LINKAGE CXDependencyScannerService
+clang_experimental_DependencyScannerService_create_v1(
+ CXDependencyScannerServiceOptions Opts);
+
+/**
+ * Dispose of a \c CXDependencyScannerService object.
+ *
+ * The service object must be disposed of after the workers are disposed of.
+ */
+CINDEX_LINKAGE void clang_experimental_DependencyScannerService_dispose_v0(
+ CXDependencyScannerService);
+
+/**
+ * Object encapsulating instance of a dependency scanner worker.
+ *
+ * The dependency scanner workers are expected to be used in separate worker
+ * threads. An individual worker is not thread safe.
+ *
+ * Operations on a worker are not thread-safe and should only be used from a
+ * single thread at a time. They are intended to be used by a single dedicated
+ * thread in a thread pool, but they are not inherently pinned to a thread.
+ */
+typedef struct CXOpaqueDependencyScannerWorker *CXDependencyScannerWorker;
+
+/**
+ * Create a \c CXDependencyScannerWorker object.
+ * Must be disposed with
+ * \c clang_experimental_DependencyScannerWorker_dispose_v0().
+ */
+CINDEX_LINKAGE CXDependencyScannerWorker
+ clang_experimental_DependencyScannerWorker_create_v0(
+ CXDependencyScannerService);
+
+CINDEX_LINKAGE void clang_experimental_DependencyScannerWorker_dispose_v0(
+ CXDependencyScannerWorker);
+
+/**
+ * A callback that is called to determine the paths of output files for each
+ * module dependency. The ModuleFile (pcm) path mapping is mandatory.
+ *
+ * \param Context the MLOContext that was passed to
+ * \c clang_experimental_DependencyScannerWorkerScanSettings_create().
+ * \param ModuleName the name of the dependent module.
+ * \param ContextHash the context hash of the dependent module.
+ * See \c clang_experimental_DepGraphModule_getContextHash().
+ * \param OutputKind the kind of module output to lookup.
+ * \param[out] Output the output path(s) or name, whose total size must be <=
+ * \p MaxLen. In the case of multiple outputs of the same
+ * kind, this can be a null-separated list.
+ * \param MaxLen the maximum size of Output.
+ *
+ * \returns the actual length of Output. If the return value is > \p MaxLen,
+ * the callback will be repeated with a larger buffer.
+ */
+typedef size_t CXModuleLookupOutputCallback(void *Context,
+ const char *ModuleName,
+ const char *ContextHash,
+ CXOutputKind OutputKind,
+ char *Output, size_t MaxLen);
+
+/**
+ * Output of \c clang_experimental_DependencyScannerWorker_getDepGraph.
+ */
+typedef struct CXOpaqueDepGraph *CXDepGraph;
+
+/**
+ * An individual module dependency that is part of an overall compilation
+ * \c CXDepGraph.
+ */
+typedef struct CXOpaqueDepGraphModule *CXDepGraphModule;
+
+/**
+ * An individual command-line invocation that is part of an overall compilation
+ * \c CXDepGraph.
+ */
+typedef struct CXOpaqueDepGraphTUCommand *CXDepGraphTUCommand;
+
+/**
+ * Settings to use for the
+ * \c clang_experimental_DependencyScannerWorker_getDepGraph action.
+ */
+typedef struct CXOpaqueDependencyScannerWorkerScanSettings
+ *CXDependencyScannerWorkerScanSettings;
+
+/**
+ * A callback that is called to determine the paths of output files for each
+ * module dependency. The ModuleFile (pcm) path mapping is mandatory.
+ *
+ * \param Context the MLOContext that was passed to
+ * \c clang_experimental_DependencyScannerWorker_getFileDependencies_vX.
+ * \param CXDepMod the ModuleDep that represents the dependent module.
+ * \param OutputKind the kind of module output to lookup.
+ * \param[out] Output the output path(s) or name, whose total size must be <=
+ * \p MaxLen. In the case of multiple outputs of the same
+ * kind, this can be a null-separated list.
+ * \param MaxLen the maximum size of Output.
+ *
+ * \returns the actual length of Output. If the return value is > \p MaxLen,
+ * the callback will be repeated with a larger buffer.
+ */
+typedef size_t CXModuleLookupOutputCallback_v2(void *Context,
+ CXDepGraphModule CXDepMod,
+ CXOutputKind OutputKind,
+ char *Output, size_t MaxLen);
+
+/**
+ * Creates a set of settings for
+ * \c clang_experimental_DependencyScannerWorker_getDepGraph action.
+ * Must be disposed with
+ * \c clang_experimental_DependencyScannerWorkerScanSettings_dispose.
+ * Memory for settings is not copied. Any provided pointers must be valid until
+ * the call to \c clang_experimental_DependencyScannerWorker_getDepGraph.
+ *
+ * \param argc the number of compiler invocation arguments (including argv[0]).
+ * \param argv the compiler driver invocation arguments (including argv[0]).
+ * \param ModuleName If non-null, the dependencies of the named module are
+ * returned. Otherwise, the dependencies of the whole
+ * translation unit are returned.
+ * \param WorkingDirectory the directory in which the invocation runs.
+ * \param MLOContext the context that will be passed to \c MLO each time it is
+ * called.
+ * \param MLO a callback that is called to determine the paths of output files
+ * for each module dependency. This may receive the same module on
+ * different workers. This should be NULL if
+ * \c clang_experimental_DependencyScannerService_create_v1 was
+ * called with \c CXDependencyMode_Flat. This callback will be called
+ * on the same thread that called \c
+ * clang_experimental_DependencyScannerWorker_getDepGraph.
+ */
+CINDEX_LINKAGE CXDependencyScannerWorkerScanSettings
+clang_experimental_DependencyScannerWorkerScanSettings_create(
+ int argc, const char *const *argv, const char *ModuleName,
+ const char *WorkingDirectory, void *MLOContext,
+ CXModuleLookupOutputCallback *MLO);
+
+/**
+ * Override the ModuleLookupOutputCallback with \c
+ * CXModuleLookupOutputCallback_v2 in the scanner settings for queries of module
+ * dependencies. This is required for handling output paths of modules that
+ * depend on attributes encoded in
+ * \c CXDepGraphModule.
+ *
+ * \param Settings object created via
+ * \c clang_experimental_DependencyScannerWorkerScanSettings_create.
+ * \param MLO a callback that is called to determine the paths of output files
+ * for each module dependency. This may receive the same module on
+ * different workers.
+ */
+CINDEX_LINKAGE void
+clang_experimental_DependencyScannerWorkerScanSettings_setModuleLookupCallback(
+ CXDependencyScannerWorkerScanSettings, CXModuleLookupOutputCallback_v2 *);
+
+/**
+ * Dispose of a \c CXDependencyScannerWorkerScanSettings object.
+ */
+CINDEX_LINKAGE void
+ clang_experimental_DependencyScannerWorkerScanSettings_dispose(
+ CXDependencyScannerWorkerScanSettings);
+
+/**
+ * Produces the dependency graph for a particular compiler invocation.
+ *
+ * \param Settings object created via
+ * \c clang_experimental_DependencyScannerWorkerScanSettings_create.
+ * \param [out] Out A non-NULL pointer to store the resulting dependencies. The
+ * output must be freed by calling
+ * \c clang_experimental_DepGraph_dispose.
+ *
+ * \returns \c CXError_Success on success; otherwise a non-zero \c CXErrorCode
+ * indicating the kind of error. When returning \c CXError_Failure there will
+ * be a \c CXDepGraph object on \p Out that can be used to get diagnostics via
+ * \c clang_experimental_DepGraph_getDiagnostics.
+ */
+CINDEX_LINKAGE enum CXErrorCode
+clang_experimental_DependencyScannerWorker_getDepGraph(
+ CXDependencyScannerWorker, CXDependencyScannerWorkerScanSettings Settings,
+ CXDepGraph *Out);
+
+/**
+ * Dispose of a \c CXDepGraph object.
+ */
+CINDEX_LINKAGE void clang_experimental_DepGraph_dispose(CXDepGraph);
+
+/**
+ * \returns the number of \c CXDepGraphModule objects in the graph.
+ */
+CINDEX_LINKAGE size_t clang_experimental_DepGraph_getNumModules(CXDepGraph);
+
+/**
+ * \returns the \c CXDepGraphModule object at the given \p Index.
+ *
+ * The \c CXDepGraphModule object is only valid to use while \c CXDepGraph is
+ * valid. Must be disposed with \c clang_experimental_DepGraphModule_dispose.
+ */
+CINDEX_LINKAGE CXDepGraphModule
+clang_experimental_DepGraph_getModule(CXDepGraph, size_t Index);
+
+/**
+ * \returns the \c CXDepGraphModule object at the given \p Index in
+ * a topologically sorted list.
+ *
+ * The \c CXDepGraphModule object is only valid to use while \c CXDepGraph is
+ * valid. Must be disposed with \c clang_experimental_DepGraphModule_dispose.
+ */
+CINDEX_LINKAGE CXDepGraphModule
+clang_experimental_DepGraph_getModuleTopological(CXDepGraph, size_t Index);
+
+CINDEX_LINKAGE void clang_experimental_DepGraphModule_dispose(CXDepGraphModule);
+
+/**
+ * \returns the name of the module. This may include `:` for C++20 module
+ * partitions, or a header-name for C++20 header units.
+ *
+ * The string is only valid to use while the \c CXDepGraphModule object is
+ * valid.
+ */
+CINDEX_LINKAGE
+const char *clang_experimental_DepGraphModule_getName(CXDepGraphModule);
+
+/**
+ * \returns the context hash of a module represents the set of compiler options
+ * that may make one version of a module incompatible from another. This
+ * includes things like language mode, predefined macros, header search paths,
+ * etc...
+ *
+ * Modules with the same name but a different \c ContextHash should be treated
+ * as separate modules for the purpose of a build.
+ *
+ * The string is only valid to use while the \c CXDepGraphModule object is
+ * valid.
+ */
+CINDEX_LINKAGE
+const char *clang_experimental_DepGraphModule_getContextHash(CXDepGraphModule);
+
+/**
+ * \returns the path to the modulemap file which defines this module. If there's
+ * no modulemap (e.g. for a C++ module) returns \c NULL.
+ *
+ * This can be used to explicitly build this module. This file will
+ * additionally appear in \c FileDeps as a dependency.
+ *
+ * The string is only valid to use while the \c CXDepGraphModule object is
+ * valid.
+ */
+CINDEX_LINKAGE const char *
+ clang_experimental_DepGraphModule_getModuleMapPath(CXDepGraphModule);
+
+/**
+ * \returns the list of files which this module directly depends on.
+ *
+ * If any of these change then the module needs to be rebuilt.
+ *
+ * The strings are only valid to use while the \c CXDepGraphModule object is
+ * valid.
+ */
+CINDEX_LINKAGE CXCStringArray
+ clang_experimental_DepGraphModule_getFileDeps(CXDepGraphModule);
+
+/**
+ * \returns the list of modules which this module direct depends on.
+ *
+ * This does include the context hash. The format is
+ * `:`
+ *
+ * The strings are only valid to use while the \c CXDepGraphModule object is
+ * valid.
+ */
+CINDEX_LINKAGE CXCStringArray
+ clang_experimental_DepGraphModule_getModuleDeps(CXDepGraphModule);
+
+/**
+ * \returns whether the provided module is comprised of
+ * inputs that resolve into stable directories.
+ */
+CINDEX_LINKAGE bool
+ clang_experimental_DepGraphModule_isInStableDirs(CXDepGraphModule);
+
+/**
+ * \returns the canonical command line to build this module.
+ *
+ * The strings are only valid to use while the \c CXDepGraphModule object is
+ * valid.
+ */
+CINDEX_LINKAGE CXCStringArray
+ clang_experimental_DepGraphModule_getBuildArguments(CXDepGraphModule);
+
+/**
+ * @returns the CASID of the filesystem root for this module, if any.
+ *
+ * The string is only valid to use while the \c CXDepGraphModule object is
+ * valid.
+ */
+CINDEX_LINKAGE const char *
+ clang_experimental_DepGraphModule_getFileSystemRootID(CXDepGraphModule);
+
+/**
+ * @returns the CASID of the include-tree for this module, if any.
+ *
+ * The string is only valid to use while the \c CXDepGraphModule object is
+ * valid.
+ */
+CINDEX_LINKAGE const char *
+ clang_experimental_DepGraphModule_getIncludeTreeID(CXDepGraphModule);
+
+/**
+ * \returns the \c ActionCache key for this module, if any.
+ *
+ * The string is only valid to use while the \c CXDepGraphModule object is
+ * valid.
+ */
+CINDEX_LINKAGE
+const char *clang_experimental_DepGraphModule_getCacheKey(CXDepGraphModule);
+
+/**
+ * \returns 1 if the scanner ignores the current working directory when
+ * computing the module's context hash. Otherwise returns 0.
+ */
+CINDEX_LINKAGE
+int clang_experimental_DepGraphModule_isCWDIgnored(CXDepGraphModule);
+
+/**
+ * \returns the number \c CXDepGraphTUCommand objects in the graph.
+ */
+CINDEX_LINKAGE size_t clang_experimental_DepGraph_getNumTUCommands(CXDepGraph);
+
+/**
+ * \returns the \c CXDepGraphTUCommand object at the given \p Index.
+ *
+ * The \c CXDepGraphTUCommand object is only valid to use while \c CXDepGraph is
+ * valid. Must be disposed with \c clang_experimental_DepGraphTUCommand_dispose.
+ */
+CINDEX_LINKAGE CXDepGraphTUCommand
+clang_experimental_DepGraph_getTUCommand(CXDepGraph, size_t Index);
+
+/**
+ * Dispose of a \c CXDepGraphTUCommand object.
+ */
+CINDEX_LINKAGE void
+ clang_experimental_DepGraphTUCommand_dispose(CXDepGraphTUCommand);
+
+/**
+ * \returns the executable name for the command.
+ *
+ * The string is only valid to use while the \c CXDepGraphTUCommand object is
+ * valid.
+ */
+CINDEX_LINKAGE const char *
+ clang_experimental_DepGraphTUCommand_getExecutable(CXDepGraphTUCommand);
+
+/**
+ * \returns the canonical command line to build this translation unit.
+ *
+ * The strings are only valid to use while the \c CXDepGraphTUCommand object is
+ * valid.
+ */
+CINDEX_LINKAGE CXCStringArray
+ clang_experimental_DepGraphTUCommand_getBuildArguments(CXDepGraphTUCommand);
+
+/**
+ * \returns the \c ActionCache key for this translation unit, if any.
+ *
+ * The string is only valid to use while the \c CXDepGraphTUCommand object is
+ * valid.
+ */
+CINDEX_LINKAGE const char *
+ clang_experimental_DepGraphTUCommand_getCacheKey(CXDepGraphTUCommand);
+
+/**
+ * \returns the list of files which this translation unit directly depends on.
+ *
+ * The strings are only valid to use while the \c CXDepGraph object is valid.
+ */
+CINDEX_LINKAGE
+CXCStringArray clang_experimental_DepGraph_getTUFileDeps(CXDepGraph);
+
+/**
+ * \returns the list of modules which this translation unit direct depends on.
+ *
+ * This does include the context hash. The format is
+ * `:`
+ *
+ * The strings are only valid to use while the \c CXDepGraph object is valid.
+ */
+CINDEX_LINKAGE
+CXCStringArray clang_experimental_DepGraph_getTUModuleDeps(CXDepGraph);
+
+/**
+ * @returns the CASID of the filesystem root for this TU, if any.
+ *
+ * This string is only valid to use while the \c CXDepGraph object is valid.
+ */
+CINDEX_LINKAGE
+const char *clang_experimental_DepGraph_getTUFileSystemRootID(CXDepGraph);
+
+/**
+ * @returns the CASID of the include-tree for this TU, if any.
+ *
+ * The string is only valid to use while the \c CXDepGraph object is valid.
+ */
+CINDEX_LINKAGE
+const char *clang_experimental_DepGraph_getTUIncludeTreeID(CXDepGraph);
+
+/**
+ * \returns the context hash of the C++20 module this translation unit exports.
+ *
+ * If the translation unit is not a module then this is empty.
+ *
+ * The string is only valid to use while the \c CXDepGraph object is valid.
+ */
+CINDEX_LINKAGE
+const char *clang_experimental_DepGraph_getTUContextHash(CXDepGraph);
+
+/**
+ * \returns The diagnostics emitted during scanning. These must be always freed
+ * by calling \c clang_disposeDiagnosticSet.
+ */
+CINDEX_LINKAGE
+CXDiagnosticSet clang_experimental_DepGraph_getDiagnostics(CXDepGraph);
+
+/**
+ * The kind of scanning file system cache out-of-date entries.
+ */
+typedef enum {
+ /**
+ * The entry is negatively stat cached (which indicates the file did not exist
+ * the first time it was looked up during scanning), but the cached file
+ * exists on the underlying file system.
+ */
+ NegativelyCached,
+
+ /**
+ * The entry indicates that for the cached file, its cached size
+ * is different from its size reported by the underlying file system.
+ */
+ SizeChanged
+} CXDepScanFSCacheOutOfDateKind;
+
+/**
+ * The opaque object that contains the scanning file system cache's out-of-date
+ * entires.
+ */
+typedef struct CXOpaqueDepScanFSOutOfDateEntrySet *CXDepScanFSOutOfDateEntrySet;
+
+/**
+ * The opaque object that represents a single scanning file system cache's out-
+ * of-date entry.
+ */
+typedef struct CXOpaqueDepScanFSOutOfDateEntry *CXDepScanFSOutOfDateEntry;
+
+/**
+ * Returns all the file system cache out-of-date entries given a
+ * \c CXDependencyScannerService .
+ *
+ * This function is intended to be called when the build has finished,
+ * and the \c CXDependencyScannerService instance is about to be disposed.
+ *
+ * The \c CXDependencyScannerService instance owns the strings used
+ * by the out-of-date entries and should be disposed after the
+ * out-of-date entries are used and disposed.
+ */
+CINDEX_LINKAGE CXDepScanFSOutOfDateEntrySet
+clang_experimental_DependencyScannerService_getFSCacheOutOfDateEntrySet(
+ CXDependencyScannerService S);
+
+/**
+ * Returns the number of out-of-date entries contained in a
+ * \c CXDepScanFSOutOfDateEntrySet .
+ */
+CINDEX_LINKAGE size_t
+clang_experimental_DepScanFSCacheOutOfDateEntrySet_getNumOfEntries(
+ CXDepScanFSOutOfDateEntrySet Entries);
+
+/**
+ * Returns the out-of-date entry at offset \p Idx of the \c
+ * CXDepScanFSOutOfDateEntrySet instance.
+ */
+CINDEX_LINKAGE CXDepScanFSOutOfDateEntry
+clang_experimental_DepScanFSCacheOutOfDateEntrySet_getEntry(
+ CXDepScanFSOutOfDateEntrySet Entries, size_t Idx);
+
+/**
+ * Given an instance of \c CXDepScanFSOutOfDateEntry, returns its Kind.
+ */
+CINDEX_LINKAGE CXDepScanFSCacheOutOfDateKind
+clang_experimental_DepScanFSCacheOutOfDateEntry_getKind(
+ CXDepScanFSOutOfDateEntry Entry);
+
+/**
+ * Given an instance of \c CXDepScanFSOutOfDateEntry, returns the path.
+ */
+CINDEX_LINKAGE CXString clang_experimental_DepScanFSCacheOutOfDateEntry_getPath(
+ CXDepScanFSOutOfDateEntry Entry);
+
+/**
+ * Given an instance of \c CXDepScanFSOutOfDateEntry of kind SizeChanged,
+ * returns the cached size.
+ */
+CINDEX_LINKAGE uint64_t
+clang_experimental_DepScanFSCacheOutOfDateEntry_getCachedSize(
+ CXDepScanFSOutOfDateEntry Entry);
+
+/**
+ * Given an instance of \c CXDepScanFSOutOfDateEntry of kind SizeChanged,
+ * returns the actual size on the underlying file system.
+ */
+CINDEX_LINKAGE uint64_t
+clang_experimental_DepScanFSCacheOutOfDateEntry_getActualSize(
+ CXDepScanFSOutOfDateEntry Entry);
+
+/**
+ * Dispose the \c CXDepScanFSOutOfDateEntrySet instance.
+ */
+CINDEX_LINKAGE void
+clang_experimental_DepScanFSCacheOutOfDateEntrySet_disposeSet(
+ CXDepScanFSOutOfDateEntrySet Entries);
+
+/**
+ * Options used to generate a reproducer.
+ */
+typedef struct CXOpaqueDependencyScannerReproducerOptions
+ *CXDependencyScannerReproducerOptions;
+
+/**
+ * Creates a set of settings for
+ * \c clang_experimental_DependencyScanner_generateReproducer action.
+ * Must be disposed with
+ * \c clang_experimental_DependencyScannerReproducerOptions_dispose.
+ *
+ * \param argc the number of compiler invocation arguments (including argv[0]).
+ * \param argv the compiler driver invocation arguments (including argv[0]).
+ * \param ModuleName If non-NULL, reproduce building the named module and all
+ * the intermediate modules. Otherwise, reproduce building
+ * the whole translation unit.
+ * \param WorkingDirectory the directory in which the invocation runs.
+ * \param ReproducerLocation the directory where to store the reproducer files.
+ * If NULL, use a temporary location.
+ * \param UseUniqueReproducerName if reproducer files should have unique names
+ * to avoid collisions with existing files.
+ */
+CINDEX_LINKAGE CXDependencyScannerReproducerOptions
+clang_experimental_DependencyScannerReproducerOptions_create(
+ int argc, const char *const *argv, const char *ModuleName,
+ const char *WorkingDirectory, const char *ReproducerLocation,
+ bool UseUniqueReproducerName);
+
+CINDEX_LINKAGE void
+ clang_experimental_DependencyScannerReproducerOptions_dispose(
+ CXDependencyScannerReproducerOptions);
+
+/**
+ * Generates a reproducer to compile a requested file with required modules.
+ *
+ * Here the reproducer means the required input data with the commands to
+ * compile intermediate modules and a requested file. Required intermediate
+ * modules and the order of their compilation are determined by the function
+ * and don't need to be provided.
+ *
+ * \param CXOptions object created via
+ * \c clang_experimental_DependencyScannerReproducerOptions_create.
+ * \param [out] MessageOut A pointer to store the human-readable message
+ * describing the result of the operation. If non-NULL,
+ * owned and should be disposed by the caller.
+ *
+ * \returns \c CXError_Success on success; otherwise a non-zero \c CXErrorCode
+ * indicating the kind of error. \p MessageOut is guaranteed to be populated
+ * for a success case but is allowed to be empty when encountered an error.
+ */
+CINDEX_LINKAGE enum CXErrorCode
+clang_experimental_DependencyScanner_generateReproducer(
+ CXDependencyScannerReproducerOptions CXOptions, CXString *MessageOut);
+
+/**
+ * An opaque object that contains a \c CXDepGraphModule 's list of link
+ * libraries.
+ */
+typedef struct CXOpaqueDepGraphModuleLinkLibrarySet
+ *CXDepGraphModuleLinkLibrarySet;
+
+/**
+ * An opaque object that contains information about a link library.
+ */
+typedef struct CXOpaqueDepGraphModuleLinkLibrary *CXDepGraphModuleLinkLibrary;
+
+/**
+ * Get the set of link libraries given a \c CXDepGraphModule instance.
+ * The returned set is a pointer into memory that the \c CXDepGraphModule
+ * instance owns. Therefore the set does not need to be disposed, and it has
+ * the same lifetime as the \c CXDepGraphModule instance.
+ */
+CINDEX_LINKAGE CXDepGraphModuleLinkLibrarySet
+ clang_experimental_DepGraphModule_getLinkLibrarySet(CXDepGraphModule);
+
+/**
+ * Get the size of \c CXDepGraphModuleLinkLibrarySet .
+ */
+CINDEX_LINKAGE size_t clang_experimental_DepGraphModuleLinkLibrarySet_getSize(
+ CXDepGraphModuleLinkLibrarySet);
+
+/**
+ * Retrieve the \c CXDepGraphModuleLinkLibrary instance at index \p Idx from the
+ * \c CXDepGraphModuleLinkLibrarySet instance. The returned object is owned
+ * by the \c CXDepGraphModule instance where the
+ * \c CXDepGraphModuleLinkLibrarySet was retrieved from, and has the same
+ * lifetime as the \c CXDepGraphModule instance.
+ */
+CINDEX_LINKAGE CXDepGraphModuleLinkLibrary
+clang_experimental_DepGraphModuleLinkLibrarySet_getLinkLibrary(
+ CXDepGraphModuleLinkLibrarySet, size_t Idx);
+
+/**
+ * Get the `Library` string from the \c CXDepGraphModuleLinkLibrary instance.
+ * `Library` could be a library name, or an absolute path to a library or a
+ * framework, as specified in the corresponding \c CXDepGraphModule instance's
+ * modulemap. The returned \c CXString is a reference to a string owned
+ * by the \c CXDepGraphModule instance, and has the same lifetime as the
+ * the \c CXDepGraphModule instance.
+ */
+CINDEX_LINKAGE CXString clang_experimental_DepGraphModuleLinkLibrary_getLibrary(
+ CXDepGraphModuleLinkLibrary);
+
+/**
+ * Returns true if the \c CXDepGraphModuleLinkLibrary is a framework, false
+ * otherwise.
+ */
+CINDEX_LINKAGE bool clang_experimental_DepGraphModuleLinkLibrary_isFramework(
+ CXDepGraphModuleLinkLibrary);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LLVM_CLANG_C_DEPENDENCIES_H
diff --git a/clang/include/clang-c/Driver.h b/clang/include/clang-c/Driver.h
new file mode 100644
index 0000000000000..54dd1b0b043a3
--- /dev/null
+++ b/clang/include/clang-c/Driver.h
@@ -0,0 +1,78 @@
+/*==-- clang-c/Driver.h - A C Interface for the Clang Driver ------*- C -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header provides a C API for extracting information from the clang *|
+|* driver. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+
+#ifndef CLANG_CLANG_C_DRIVER
+#define CLANG_CLANG_C_DRIVER
+
+#include "clang-c/Index.h"
+#include "clang-c/Platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Contains the command line arguments for an external action. Same format as
+ * provided to main.
+ */
+typedef struct {
+ /* Number of arguments in ArgV */
+ int ArgC;
+ /* Null terminated array of pointers to null terminated argument strings */
+ const char **ArgV;
+} CXExternalAction;
+
+/**
+ * Contains the list of external actions clang would invoke.
+ */
+typedef struct {
+ int Count;
+ CXExternalAction **Actions;
+} CXExternalActionList;
+
+/**
+ * Get the external actions that the clang driver will invoke for the given
+ * command line.
+ *
+ * \param ArgC number of arguments in \p ArgV.
+ * \param ArgV array of null terminated arguments. Doesn't need to be null
+ * terminated.
+ * \param Environment must be null.
+ * \param WorkingDirectory a null terminated path to the working directory to
+ * use for this invocation. `nullptr` to use the current working directory of
+ * the process.
+ * \param OutDiags will be set to a \c CXDiagnosticSet if there's an error.
+ * Must be freed by calling \c clang_disposeDiagnosticSet .
+ * \returns A pointer to a \c CXExternalActionList on success, null on failure.
+ * The returned \c CXExternalActionList must be freed by calling
+ * \c clang_Driver_ExternalActionList_dispose .
+ */
+CINDEX_LINKAGE CXExternalActionList *
+clang_Driver_getExternalActionsForCommand_v0(int ArgC, const char **ArgV,
+ const char **Environment,
+ const char *WorkingDirectory,
+ CXDiagnosticSet *OutDiags);
+
+/**
+ * Deallocate a \c CXExternalActionList
+ */
+CINDEX_LINKAGE void
+clang_Driver_ExternalActionList_dispose(CXExternalActionList *EAL);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // CLANG_CLANG_C_DRIVER
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index f13d9c9307b40..7227010325a52 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -34,7 +34,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 64
+#define CINDEX_VERSION_MINOR 65
#define CINDEX_VERSION_ENCODE(major, minor) (((major) * 10000) + ((minor) * 1))
@@ -1691,7 +1691,17 @@ enum CXCursorKind {
*/
CXCursor_PackIndexingExpr = 156,
- CXCursor_LastExpr = CXCursor_PackIndexingExpr,
+ /* TO_UPSTREAM(BoundsSafety) ON */
+ /**
+ * BoundsSafety '__builtin_unsafe_forge_bidi_indexable(addr, size)' or
+ * '__builtin_forge_single(addr)
+ */
+ CXCursor_ForgePtrExpr = 198,
+
+ CXCursor_GetBoundExpr = 199,
+
+ CXCursor_LastExpr = CXCursor_GetBoundExpr,
+ /* TO_UPSTREAM(BoundsSafety) OFF */
/* Statements */
CXCursor_FirstStmt = 200,
diff --git a/clang/include/clang-c/Refactor.h b/clang/include/clang-c/Refactor.h
new file mode 100644
index 0000000000000..983a652481d9e
--- /dev/null
+++ b/clang/include/clang-c/Refactor.h
@@ -0,0 +1,1313 @@
+/*==-- clang-c/Refactor.h - Refactoring Public C Interface --------*- C -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header provides a public inferface to a Clang library for performing *|
+|* refactoring actions on projects without exposing the full Clang C++ API. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_CLANG_C_REFACTOR_H
+#define LLVM_CLANG_C_REFACTOR_H
+
+#include "clang-c/Index.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \defgroup CINDEX_REFACTOR Refactoring options.
+ *
+ * @{
+ */
+
+/**
+ * \brief The refactoring options that can be specified for each refactoring
+ * action.
+ */
+enum CXRefactoringOption {
+ /**
+ * \brief The refactoring actions like 'rename' will avoid looking for
+ * occurrences of the renamed symbol in comments if this option is enabled.
+ */
+ CXRefactorOption_AvoidTextualMatches = 1
+};
+
+/**
+ * \brief Opaque pointer representing a set of options that can be given to
+ * a refactoring action.
+ */
+typedef void *CXRefactoringOptionSet;
+
+/**
+ * \brief Returns a new option set.
+ */
+CINDEX_LINKAGE
+CXRefactoringOptionSet clang_RefactoringOptionSet_create(void);
+
+/**
+ * \brief Parses and returns a new option set or NULL if the given string is
+ * invalid.
+ */
+CINDEX_LINKAGE
+CXRefactoringOptionSet
+clang_RefactoringOptionSet_createFromString(const char *String);
+
+/**
+ * \brief Adds a new option to the given refactoring option set.
+ */
+CINDEX_LINKAGE
+void clang_RefactoringOptionSet_add(CXRefactoringOptionSet Set,
+ enum CXRefactoringOption Option);
+
+/**
+ * \brief Converts the given refactoring option set to a string value.
+ */
+CINDEX_LINKAGE
+CXString clang_RefactoringOptionSet_toString(CXRefactoringOptionSet Set);
+
+/**
+ * \brief Free the given option set.
+ *
+ * Option sets should be freed by this function only when they were created
+ * using the \c clang_RefactoringOptionSet_create* methods.
+ */
+CINDEX_LINKAGE
+void clang_RefactoringOptionSet_dispose(CXRefactoringOptionSet Set);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_REFACTOR Refactoring actions.
+ *
+ * @{
+ */
+
+/**
+ * \brief The refactoring actions that can be performed by libclang.
+ */
+enum CXRefactoringActionType {
+ /**
+ * \brief The 'rename' refactoring action.
+ */
+ CXRefactor_Rename = 0,
+
+ /**
+ * \brief The local 'rename' refactoring action.
+ */
+ CXRefactor_Rename_Local = 1,
+
+ /**
+ * \brief The 'extract' refactoring action extracts source code into a
+ * new function.
+ */
+ CXRefactor_Extract = 2,
+
+ /**
+ * \brief The sub-action of 'extract' that extracts source code into a new
+ * method.
+ */
+ CXRefactor_Extract_Method = 3,
+
+ /**
+ * \brief The action that converts an if/else constructs to a switch block.
+ */
+ CXRefactor_IfSwitchConversion = 4,
+
+ /**
+ * \brief The action that wraps an Objective-C string literal in an
+ * NSLocalizedString macro.
+ */
+ CXRefactor_LocalizeObjCStringLiteral = 5,
+
+ /**
+ * \brief The action that adds missing switch cases to an switch over an enum.
+ */
+ CXRefactor_FillInEnumSwitchCases = 6,
+
+ /**
+ * \brief The action that adds missing protocol methods to an Objective-C
+ * class.
+ */
+ CXRefactor_FillInMissingProtocolStubs = 7,
+
+ /**
+ * \brief The action that extracts an expression that's repeated in a function
+ * into a new variable.
+ */
+ CXRefactor_ExtractRepeatedExpressionIntoVariable = 8,
+
+ /**
+ * \brief The action that adds missing abstract class method overrides to a
+ * class.
+ */
+ CXRefactor_FillInMissingMethodStubsFromAbstractClasses = 9,
+
+ /**
+ * \brief The action that generates dummy method definitions for method
+ * declarations without respective definitions.
+ */
+ CXRefactor_ImplementDeclaredMethods = 10,
+
+ /**
+ * \brief The sub-action of 'extract' that extracts source expression into a
+ * new variable.
+ */
+ CXRefactor_Extract_Expression = 11,
+};
+
+/**
+ * \brief Return the name of the given refactoring action.
+ */
+CINDEX_LINKAGE
+CXString
+clang_RefactoringActionType_getName(enum CXRefactoringActionType Action);
+
+/**
+ * \brief A set of refactoring actions that can be performed at some specific
+ * location in a source file.
+ *
+ * The actions in the action set are ordered by their priority: most important
+ * actions are placed before the less important ones.
+ */
+typedef struct {
+ const enum CXRefactoringActionType *Actions;
+ unsigned NumActions;
+} CXRefactoringActionSet;
+
+/**
+ * \brief Free the given refactoring action set.
+ */
+CINDEX_LINKAGE void
+clang_RefactoringActionSet_dispose(CXRefactoringActionSet *Set);
+
+typedef struct {
+ enum CXRefactoringActionType Action;
+ /**
+ * \brief The set of diagnostics that describes the reason why this action
+ * couldn't be initiated. This set of diagnostics is managed by the
+ * \c CXRefactoringActionSetWithDiagnostics and shouldn't be freed manually.
+ */
+ CXDiagnosticSet Diagnostics;
+} CXRefactoringActionWithDiagnostics;
+
+/**
+ * \brief A set of refactoring actions that couldn't be initiated at some
+ * location and their respective diagnostics that describe the reason why
+ * the initiation failed.
+ */
+typedef struct {
+ CXRefactoringActionWithDiagnostics *Actions;
+ unsigned NumActions;
+} CXRefactoringActionSetWithDiagnostics;
+
+/**
+ * \brief Free the given refactoring action set with diagnostics.
+ */
+CINDEX_LINKAGE void clang_RefactoringActionSetWithDiagnostics_dispose(
+ CXRefactoringActionSetWithDiagnostics *Set);
+
+/**
+ * \brief Find the set of refactoring actions that can be performed at the given
+ * location.
+ *
+ * This function examines the AST around the given source range and creates a
+ * \c CXRefactoringActionSet that contains all of the actions that can be
+ * performed in the given source range.
+ *
+ * \param TU The translation unit which contains the given source range.
+ *
+ * \param Location The location at which the refactoring action will be
+ * performed.
+ *
+ * \param SelectionRange The range in which the AST should be checked. Usually
+ * corresponds to the selection range or location of the cursor in the editor.
+ * Can be a null range.
+ *
+ * \param Options The optional refactoring options that might influence the way
+ * the search is performed.
+ *
+ * \param[out] OutSet A non-NULL pointer to store the created
+ * \c CXRefactoringActionSet.
+ *
+ * \returns Zero on success, CXError_RefactoringActionUnavailable when
+ * there are no actions available in the given range, or an error code
+ * otherwise.
+ */
+CINDEX_LINKAGE
+enum CXErrorCode
+clang_Refactoring_findActionsAt(CXTranslationUnit TU, CXSourceLocation Location,
+ CXSourceRange SelectionRange,
+ CXRefactoringOptionSet Options,
+ CXRefactoringActionSet *OutSet);
+
+/**
+ * \brief Find the set of refactoring actions that can be performed at the given
+ * location.
+ *
+ * This function examines the AST around the given source range and creates a
+ * \c CXRefactoringActionSet that contains all of the actions that can be
+ * performed in the given source range. It also creates a
+ * \c CXRefactoringActionSetWithDiagnostics that might describe the reason why
+ * some refactoring actions are not be available.
+ *
+ * \param TU The translation unit which contains the given source range.
+ *
+ * \param Location The location at which the refactoring action will be
+ * performed.
+ *
+ * \param SelectionRange The range in which the AST should be checked. Usually
+ * corresponds to the selection range or location of the cursor in the editor.
+ * Can be a null range.
+ *
+ * \param Options The optional refactoring options that might influence the way
+ * the search is performed.
+ *
+ * \param[out] OutSet A non-NULL pointer to store the created
+ * \c CXRefactoringActionSet.
+ *
+ * \param[out] OutFailureSet An optional pointer to store the created
+ * \c CXRefactoringActionSetWithDiagnostics that describes the failures reasons
+ * for some of the refactoring actions.
+ *
+ * \returns Zero on success, CXError_RefactoringActionUnavailable when
+ * there are no actions available in the given range, or an error code
+ * otherwise.
+ */
+CINDEX_LINKAGE
+enum CXErrorCode clang_Refactoring_findActionsWithInitiationFailureDiagnosicsAt(
+ CXTranslationUnit TU, CXSourceLocation Location,
+ CXSourceRange SelectionRange, CXRefactoringOptionSet Options,
+ CXRefactoringActionSet *OutSet,
+ CXRefactoringActionSetWithDiagnostics *OutFailureSet);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_REFACTOR_INITIATE Refactoring initiation
+ *
+ * @{
+ */
+
+/**
+ * \brief Opaque pointer representing the initiated refactoring action.
+ */
+typedef void *CXRefactoringAction;
+
+/**
+ * \brief Free the given refactoring action.
+ *
+ * The refactoring action should be freed before the initiation and/or
+ * implementation translation units.
+ */
+CINDEX_LINKAGE void clang_RefactoringAction_dispose(CXRefactoringAction Action);
+
+/**
+ * \brief Return the source range that's associated with the initiated
+ * refactoring action.
+ *
+ * The returned source range covers the source that will be modified by the
+ * given refactoring action. If the action has no associated source range,
+ * then this function will return a null \c CXSourceRange.
+ */
+CINDEX_LINKAGE CXSourceRange
+clang_RefactoringAction_getSourceRangeOfInterest(CXRefactoringAction Action);
+
+/**
+ * \brief Return the type of the initiated action, which might be different
+ * to the type of the requested action. For an operation 'rename', the action
+ * could actually initiate the local 'rename' operation.
+ */
+CINDEX_LINKAGE
+enum CXRefactoringActionType
+clang_RefactoringAction_getInitiatedActionType(CXRefactoringAction Action);
+
+/**
+ * \brief Return a non-zero value when the refactoring action requires access
+ * to an additional translation unit that contains an implementation of some
+ * declaration.
+ */
+// TODO: Remove (this is no longer needed due to refactoring continuations).
+CINDEX_LINKAGE
+int clang_RefactoringAction_requiresImplementationTU(
+ CXRefactoringAction Action);
+
+/**
+ * \brief Return a USR that corresponds to the declaration whose implementation
+ * is required in order for the given refactoring action to work correctly.
+ */
+// TODO: Remove (this is no longer needed due to refactoring continuations).
+CINDEX_LINKAGE
+CXString clang_RefactoringAction_getUSRThatRequiresImplementationTU(
+ CXRefactoringAction Action);
+
+/**
+ * \brief Set the translation unit that contains the declaration whose
+ * implementation is required for the given refactoring action to work
+ * correctly.
+ */
+// TODO: Remove (this is no longer needed due to refactoring continuations).
+CINDEX_LINKAGE
+enum CXErrorCode
+clang_RefactoringAction_addImplementationTU(CXRefactoringAction Action,
+ CXTranslationUnit TU);
+
+/**
+ * \brief A refactoring candidate determines on which piece of source code the
+ * action should be applied.
+ *
+ * Most refactoring actions have just one candidate, but some actions, like
+ * 'Extract' can produce multiple candidates.
+ *
+ * The candidates are managed by the refactoring action, and their description
+ * string doesn't need to be freed manually.
+ */
+typedef struct { CXString Description; } CXRefactoringCandidate;
+
+/**
+ * \brief A set of refactoring candidates on which the previously initiatied
+ * refactoring action can be performed.
+ *
+ * The candidates in the candidate set are ordered by their priority: the
+ * ones that are more likely to be selected are placed before the other ones.
+ *
+ * A non-empty refactoring candidate set always has more than one refactoring
+ * candidate, because when a refactoring action has just one candidate,
+ * \c clang_RefactoringAction_getRefactoringCandidates will return an empty
+ * candidate set.
+ */
+typedef struct {
+ const CXRefactoringCandidate *Candidates;
+ unsigned NumCandidates;
+} CXRefactoringCandidateSet;
+
+/**
+ * \brief Returns the given action's refactoring candidates.
+ *
+ * The resulting refactoring candidate set will be empty when the given \c
+ * CXRefactoringAction has just one refactoring candidate.
+ *
+ * \param Action A previously initiated \c CXRefactoringAction.
+ *
+ * \param[out] OutRefactoringCandidateSet An pointer to store the action's
+ * refactoring candidate set.
+ *
+ * \returns Zero on success, or an error code otherwise.
+ */
+CINDEX_LINKAGE
+enum CXErrorCode clang_RefactoringAction_getRefactoringCandidates(
+ CXRefactoringAction Action,
+ CXRefactoringCandidateSet *OutRefactoringCandidateSet);
+
+/**
+ * \brief Tells the given refactoring action that it has to perform the
+ * operation on the refactoring candidate that's located at \p Index in the \c
+ * CXRefactoringCandidateSet.
+ */
+CINDEX_LINKAGE
+enum CXErrorCode
+clang_RefactoringAction_selectRefactoringCandidate(CXRefactoringAction Action,
+ unsigned Index);
+
+// TODO: Remove.
+CINDEX_LINKAGE
+enum CXErrorCode clang_Refactoring_initiateActionAt(
+ CXTranslationUnit TU, CXSourceLocation Location,
+ CXSourceRange SelectionRange, enum CXRefactoringActionType ActionType,
+ CXRefactoringOptionSet Options, CXRefactoringAction *OutAction,
+ CXString *OutFailureReason);
+
+/**
+ * \brief Initiate a specific refactoring action at the given location.
+ *
+ * This function initiates an \p ActionType refactoring action when it can
+ * be initiated at the given location and creates a \c CXRefactoringAction
+ * action that will allow the control.
+ *
+ * \param TU The translation unit in which the action should be initiated.
+ *
+ * \param Location The location at which the refactoring action will be
+ * performed.
+ *
+ * \param SelectionRange The range in which the AST should be checked. Usually
+ * corresponds to the selection range or location of the cursor in the editor.
+ * Can be a null range.
+ *
+ * \param ActionType The type of action that should be initiated.
+ *
+ * \param Options The optional refactoring options that might have an influence
+ * on the initiation process.
+ *
+ * \param[out] OutAction A non-NULL pointer to store the created
+ * \c CXRefactoringAction.
+ *
+ * \param[out] OutDiagnostics An optional pointer to store any diagnostics that
+ * describe why the action wasn't initiated.
+ *
+ * \returns Zero on success, CXError_RefactoringActionUnavailable when
+ * the given refactoring action can't be performed at the given location, or an
+ * error code otherwise.
+ */
+CINDEX_LINKAGE
+enum CXErrorCode clang_Refactoring_initiateAction(
+ CXTranslationUnit TU, CXSourceLocation Location,
+ CXSourceRange SelectionRange, enum CXRefactoringActionType ActionType,
+ CXRefactoringOptionSet Options, CXRefactoringAction *OutAction,
+ CXDiagnosticSet *OutDiagnostics);
+
+/**
+ * \brief Initiate a specific refactoring action on a particular declaration.
+ *
+ * This function searches for the declaration that corresponds to \p DeclUSR
+ * and initiates an \p ActionType a refactoring action on that declaration
+ * if possible.
+ *
+ * \param TU The translation unit in which the declaration is defined.
+ *
+ * \param DeclUSR The USR that corresponds to the declaration of interest.
+ *
+ * \param ActionType The type of action that should be initiated.
+ *
+ * \param Options The optional refactoring options that might have an influence
+ * on the initiation process.
+ *
+ * \param[out] OutAction A non-NULL pointer to store the created
+ * \c CXRefactoringAction.
+ *
+ * \returns Zero on success, CXError_RefactoringActionUnavailable when
+ * the given refactoring action can't be performed on the found declaration, or
+ * an error code otherwise.
+ */
+// TODO: Remove (not needed).
+CINDEX_LINKAGE
+enum CXErrorCode clang_Refactoring_initiateActionOnDecl(
+ CXTranslationUnit TU, const char *DeclUSR,
+ enum CXRefactoringActionType ActionType, CXRefactoringOptionSet Options,
+ CXRefactoringAction *OutAction, CXString *OutFailureReason);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_REFACTOR_REPLACEMENT Refactoring replacement
+ *
+ * @{
+ */
+
+/**
+ * \brief A source location in a single file that is independent of \c
+ * CXTranslationUnit.
+ */
+typedef struct { unsigned Line, Column; } CXFileLocation;
+
+/**
+ * \brief A source range in a single file that is independent of \c
+ * CXTranslationUnit.
+ */
+typedef struct { CXFileLocation Begin, End; } CXFileRange;
+
+// TODO: Remove
+typedef struct {
+ CXFileRange Range;
+ CXString ReplacementString;
+} CXRefactoringReplacement_Old;
+
+// TODO: Remove
+typedef struct {
+ CXString Filename;
+ const CXRefactoringReplacement_Old *Replacements;
+ unsigned NumReplacements;
+} CXRefactoringFileReplacementSet_Old;
+
+// TODO: Remove
+typedef struct {
+ const CXRefactoringFileReplacementSet_Old *FileReplacementSets;
+ unsigned NumFileReplacementSets;
+} CXRefactoringReplacements_Old;
+
+/**
+ * \brief Identifies a character range in the source code of a single file that
+ * should be replaced with the replacement string.
+ *
+ * Replacements are managed by the result of a specific refactoring action,
+ * like \c CXRenamingResult, and are invalidated when the refactoring result is
+ * destroyed.
+ */
+typedef struct {
+ CXFileRange Range;
+ CXString ReplacementString;
+ void *AssociatedData;
+} CXRefactoringReplacement;
+
+/**
+* \brief A set of refactoring replacements that are applicable to a certain
+ * file.
+ */
+typedef struct {
+ CXString Filename;
+ const CXRefactoringReplacement *Replacements;
+ unsigned NumReplacements;
+} CXRefactoringFileReplacementSet;
+
+/**
+ * \brief A set of refactoring replacements that have been produced by a
+ * refactoring operation.
+ *
+ * The refactoring replacements depend on \c CXRefactoringResult, and can't be
+ * used after the refactoring result is freed.
+ */
+typedef struct {
+ const CXRefactoringFileReplacementSet *FileReplacementSets;
+ unsigned NumFileReplacementSets;
+} CXRefactoringReplacements;
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_SYMBOL_OPERATION Symbol-based refactoring operation
+ * (e.g. Rename).
+ *
+ * @{
+ */
+
+/**
+ * \brief The type of a symbol occurrence.
+ *
+ * The occurrence kind determines if an occurrence can be renamed automatically
+ * or if the user has to make the decision whether or not this occurrence
+ * should be renamed.
+ */
+enum CXSymbolOccurrenceKind {
+ /**
+ * \brief This occurrence is an exact match and can be renamed automatically.
+ */
+ CXSymbolOccurrence_MatchingSymbol = 0,
+
+ /**
+ * \brief This is an occurrence of a matching selector. It can't be renamed
+ * automatically unless the indexer proves that this selector refers only
+ * to the declarations that correspond to the renamed symbol.
+ */
+ CXSymbolOccurrence_MatchingSelector = 1,
+
+ /**
+ * \brief This is an occurrence of an implicit property that uses the
+ * renamed method.
+ */
+ CXSymbolOccurrence_MatchingImplicitProperty = 2,
+
+ /**
+ * \brief This is an occurrence of an symbol name in a comment.
+ */
+ CXSymbolOccurrence_MatchingCommentString = 3,
+
+ /**
+ * \brief This is an occurrence of an symbol name in a documentation comment.
+ */
+ CXSymbolOccurrence_MatchingDocCommentString = 4,
+
+ /**
+ * \brief This is an occurrence of an symbol name in a filename in an inclusion
+ * directive.
+ */
+ CXSymbolOccurrence_MatchingFilename = 5,
+
+ /**
+ * \brief This is an occurrence of an symbol name in a string literal.
+ */
+ CXSymbolOccurrence_MatchingStringLiteral = 6,
+
+ /**
+ * \brief This is an occurrence of a symbol name that belongs to the extracted
+ * declaration. Note: this occurrence can be in two replacements as we might
+ * extract an out-of-line method that will be both declared and defined.
+ */
+ CXSymbolOccurrence_ExtractedDeclaration = 100,
+
+ /**
+ * \brief This is an occurrence of a symbol name that references the extracted
+ * declaration.
+ */
+ CXSymbolOccurrence_ExtractedDeclaration_Reference = 101,
+};
+
+// TODO: Remove
+typedef struct {
+ const CXRefactoringReplacement_Old *Replacements;
+ unsigned ReplacementCount;
+ enum CXSymbolOccurrenceKind Kind;
+ /**
+ * Whether or not this occurrence is inside a macro. When this is true, the
+ * replacements of the occurrence contain just a single empty replacement that
+ * points to the location of the macro expansion.
+ */
+ int IsMacroExpansion;
+} CXRenamedSymbolOccurrence;
+
+/**
+ * \brief An occurrence of a symbol.
+ *
+ * Contains the source ranges that represent the pieces of the name of the
+ * symbol. The occurrences are managed by \c CXRenamingResult, and are
+ * invalidated when \c CXRenamingResult is destroyed.
+ */
+typedef struct {
+ const CXFileRange *NamePieces;
+ unsigned NumNamePieces;
+ enum CXSymbolOccurrenceKind Kind;
+ /**
+ * Whether or not this occurrence is inside a macro. When this is true, the
+ * replacements of the occurrence contain just a single empty replacement that
+ * points to the location of the macro expansion.
+ */
+ int IsMacroExpansion;
+ unsigned SymbolIndex;
+} CXSymbolOccurrence;
+
+// TODO: Remove
+typedef struct {
+ CXString Filename;
+ const CXRenamedSymbolOccurrence *Occurrences;
+ unsigned NumOccurrences;
+} CXFileRenamingResult; // TODO: Remove
+
+/**
+* \brief A set of symbol occurrences that occur in a single file.
+ */
+typedef struct {
+ CXString Filename;
+ /**
+ * The set of occurrences for each symbol of interest.
+ */
+ const CXSymbolOccurrence *Occurrences;
+ unsigned NumOccurrences;
+} CXSymbolOccurrencesInFile;
+
+/**
+ * \brief Opaque pointer representing all of the renames that should take place
+ * in a single translation unit.
+ *
+ * The result of a renaming action is indepedent from \c CXRenamingAction, and
+ * remains valid after \c CXRenamingAction is destroyed.
+ */
+typedef void *CXRenamingResult;
+
+/**
+ * \brief Opaque pointer representing all of the symbol occurrences from a
+ * single TU/file.
+ *
+ * The result of a symbol search occurrence search operation is indepedent from
+ * \c CXRefactoringAction, and remains valid after \c CXRefactoringAction is
+ * destroyed.
+ */
+typedef void *CXSymbolOccurrencesResult;
+
+/**
+ * \brief Find the cursor that's being renamed at the given location.
+ *
+ * \param TU The translation unit in which the cursor is present.
+ *
+ * \param Location The location at which the refactoring action will be
+ * performed.
+ *
+ * \param SelectionRange The range in which the AST should be checked. Usually
+ * corresponds to the selection range or location of the cursor in the editor.
+ * Can be a null range.
+ *
+ * \returns Zero on success, CXError_RefactoringActionUnavailable when
+ * there's no suitable cursor at the given location, or an error code otherwise.
+ */
+CINDEX_LINKAGE
+enum CXErrorCode clang_Refactoring_findRenamedCursor(
+ CXTranslationUnit TU, CXSourceLocation Location,
+ CXSourceRange SelectionRange, CXCursor *OutCursor);
+
+/**
+ * \brief Initiates a renaming operation on a previously initiated refactoring
+ * action.
+ *
+ * The initiation process finds the symbols that have to be renamed for a
+ * previously initiated \c CXRefactor_Rename refactoring action.
+ *
+ * \returns Zero on success, or an error code otherwise.
+ */
+// TODO: Remove
+CINDEX_LINKAGE
+enum CXErrorCode
+clang_Refactoring_initiateRenamingOperation(CXRefactoringAction Action);
+
+/**
+ * \brief Set the new name of the renamed symbol in the given \c
+ * RenamingAction.
+ *
+ * \returns Zero on success, CXError_RefactoringNameInvalid when the new name
+ * isn't a valid identifier, CXError_RefactoringNameSizeMismatch when the new
+ * name has an incorrect number of pieces or a different error code otherwise.
+ */
+// TODO: Remove
+CINDEX_LINKAGE
+enum CXErrorCode clang_RenamingOperation_setNewName(CXRefactoringAction Action,
+ const char *NewName);
+
+/**
+ * \brief Return the number of symbols that are renamed by the given renaming
+ * action.
+ *
+ * A renaming action typically works on just one symbol. However, there are
+ * certain language constructs that require work with more than one symbol in
+ * order for them to be renamed correctly. Property declarations in Objective-C
+ * are the perfect example: in addition to the actual property, the action has
+ * to rename the corresponding getters and setters, as well as the backing ivar.
+ */
+// TODO: Remove
+CINDEX_LINKAGE
+unsigned clang_RenamingOperation_getNumSymbols(CXRefactoringAction Action);
+
+/**
+ * \brief Return the USR of the declaration that was found for the symbol at the
+ * given \p Index in the given renaming action.
+ */
+// TODO: Remove
+CINDEX_LINKAGE
+CXString clang_RenamingOperation_getUSRForSymbol(CXRefactoringAction Action,
+ unsigned Index);
+
+// TODO: Remove
+CINDEX_LINKAGE
+CXRenamingResult clang_Refactoring_findRenamedOccurrencesInPrimaryTUs(
+ CXRefactoringAction Action, const char *const *CommandLineArgs,
+ int NumCommandLineArgs, struct CXUnsavedFile *UnsavedFiles,
+ unsigned NumUnsavedFiles);
+
+/**
+ * \brief Find all of the occurrences of the symbol that is being searched for
+ * by the given refactoring action in the translation unit that was used to
+ * initiate the refactoring action.
+ *
+ * This function searches for all of the \c CXSymbolOccurrence in the
+ * translation units that are referenced by the given \c CXRefactoringAction by
+ * iterating through the AST of the each translation unit. The occurrences that
+ * are found don't have to be from the main file in the translation unit, they
+ * can be from files included in that translation unit.
+ *
+ * \param Action The \c CXRefactoringAction operation that was inititated by
+ * \c clang_Refactoring_initiateActionAt().
+ *
+ * \param CommandLineArgs The command-line arguments that would be
+ * passed to the \c clang executable if it were being invoked out-of-process.
+ *
+ * \param NumCommandLineArgs The number of command-line arguments in
+ * \c CommandLineArgs.
+ *
+ * \param UnsavedFiles the files that have not yet been saved to disk
+ * but may be required for parsing, including the contents of
+ * those files. The contents and name of these files (as specified by
+ * CXUnsavedFile) are copied when necessary, so the client only needs to
+ * guarantee their validity until the call to this function returns.
+ *
+ * \param NumUnsavedFiles the number of unsaved file entries in \p
+ * UnsavedFiles.
+ *
+ * \returns If successful, a new \c CXSymbolOccurrencesResult structure
+ * containing the occurrences of the symbol in the initiation translation unit,
+ * which should eventually be freed with \c clang_SymbolOccurrences_dispose().
+ * If symbol search fails, returns NULL.
+ */
+CINDEX_LINKAGE
+CXSymbolOccurrencesResult clang_Refactoring_findSymbolOccurrencesInInitiationTU(
+ CXRefactoringAction Action, const char *const *CommandLineArgs,
+ int NumCommandLineArgs, struct CXUnsavedFile *UnsavedFiles,
+ unsigned NumUnsavedFiles);
+
+// TODO: Remove
+typedef struct {
+ CXFileLocation Location;
+ /**
+ * The kind of the declaration/expression that was indexed at this location.
+ * This is particularly important for Objective-C selectors. The refactoring
+ * engine requires the following cursor kinds for the following indexed
+ * occurrences:
+ * - ObjC method declaration: CXCursor_ObjC(Instance/Class)MethodDecl
+ * - ObjC method message send: CXCursor_ObjCMessageExpr
+ * Other occurrences can use any other cursor cursor kinds.
+ */
+ enum CXCursorKind CursorKind;
+} CXRenamedIndexedSymbolLocation;
+
+// TODO: Remove
+typedef struct {
+ /**
+ * An array of occurrences that represent indexed occurrences of a symbol.
+ * It's valid to pass-in no indexed locations, the refactoring engine will
+ * just perform textual search in that case.
+ */
+ const CXRenamedIndexedSymbolLocation *IndexedLocations;
+ unsigned IndexedLocationCount;
+ /**
+ * The kind of the declaration that is being renamed.
+ * This is particularly important for Objective-C selectors. The refactoring
+ * engine requires the following cursor kinds for the following renamed
+ * declaration:
+ * - ObjC methods: CXCursor_ObjC(Instance/Class)MethodDecl
+ * Other declarations can use any other cursor cursor kinds.
+ */
+ enum CXCursorKind CursorKind;
+ const char *Name;
+ const char *NewName;
+} CXRenamedIndexedSymbol;
+
+// TODO: Remove
+CINDEX_LINKAGE
+enum CXErrorCode clang_Refactoring_findRenamedOccurrencesInIndexedFile(
+ const CXRenamedIndexedSymbol *Symbols, unsigned NumSymbols, CXIndex CIdx,
+ const char *Filename, const char *const *CommandLineArgs,
+ int NumCommandLineArgs, struct CXUnsavedFile *UnsavedFiles,
+ unsigned NumUnsavedFiles, CXRefactoringOptionSet Options,
+ CXRenamingResult *OutResult);
+
+/**
+ * \brief A location of an already known occurrence of a symbol.
+ *
+ * Used for rename-indexed operation where the renaming is performed on an
+ * already indexed source file.
+ */
+typedef struct {
+ CXFileLocation Location;
+ /**
+ * The kind of the declaration/expression that was indexed at this location.
+ * This is particularly important for Objective-C selectors. The refactoring
+ * engine requires the following cursor kinds for the following indexed
+ * occurrences:
+ * - ObjC method declaration: CXCursor_ObjC(Instance/Class)MethodDecl
+ * - ObjC method message send: CXCursor_ObjCMessageExpr
+ * - filename in an #include: CXCursor_InclusionDirective
+ * Other occurrences can use any other cursor cursor kinds.
+ */
+ enum CXCursorKind CursorKind;
+} CXIndexedSymbolLocation;
+
+/**
+ * \brief A symbol that should be found the an indexer symbol search operation.
+ *
+ * Used for rename-indexed operation where the renaming is performed on an
+ * already indexed source file.
+ */
+typedef struct {
+ /**
+ * An array of occurrences that represent indexed occurrences of a symbol.
+ * It's valid to pass-in no indexed locations, the refactoring engine will
+ * just perform textual search in that case.
+ */
+ const CXIndexedSymbolLocation *IndexedLocations;
+ unsigned IndexedLocationCount;
+ /**
+ * The kind of the declaration that is being renamed.
+ * This is particularly important for Objective-C selectors. The refactoring
+ * engine requires the following cursor kinds for the following renamed
+ * declaration:
+ * - ObjC methods: CXCursor_ObjC(Instance/Class)MethodDecl
+ * - ObjC class: CXCursor_ObjCInterfaceDecl
+ * Other declarations can use any other cursor cursor kinds.
+ */
+ enum CXCursorKind CursorKind;
+ /**
+ * The name of the symbol. Objective-C selector names should be specified
+ * using the ':' separator for selector pieces.
+ */
+ const char *Name;
+} CXIndexedSymbol;
+
+/**
+ * \brief Find all of the occurrences of a symbol in an indexed file.
+ *
+ * This function searches for all of the \c CXIndexedSymbol in the
+ * given file by inspecting the source code at the given indexed locations.
+ *
+ * The indexed operations are thread-safe and can be performed concurrently.
+ *
+ * \param Symbols The information about the symbols that includes the locations
+ * for a symbol in the file as determined by the indexer.
+ *
+ * \param NumSymbols The number of symbols in \p Symbols.
+ *
+ * \param CIdx The index object with which the translation unit will be
+ * associated.
+ *
+ * \param Filename The name of the source file that contains the given
+ * \p Locations.
+ *
+ * \param CommandLineArgs The command-line arguments that would be
+ * passed to the \c clang executable if it were being invoked out-of-process.
+ * These command-line options will be parsed and will affect how the translation
+ * unit is parsed.
+ *
+ * \param NumCommandLineArgs The number of command-line arguments in
+ * \c CommandLineArgs.
+ *
+ * \param UnsavedFiles the files that have not yet been saved to disk
+ * but may be required for parsing, including the contents of
+ * those files. The contents and name of these files (as specified by
+ * CXUnsavedFile) are copied when necessary, so the client only needs to
+ * guarantee their validity until the call to this function returns.
+ *
+ * \param NumUnsavedFiles the number of unsaved file entries in \p
+ * UnsavedFiles.
+ *
+ * \param Options The optional refactoring options that might have an influence
+ * on the initiation process.
+ *
+ * \param[out] OutResult A non-NULL pointer to store the created
+ * \c CXSymbolOccurrencesResult.
+ *
+ * \returns Zero on success, or a different error code otherwise.
+ */
+CINDEX_LINKAGE
+enum CXErrorCode clang_Refactoring_findSymbolOccurrencesInIndexedFile(
+ const CXIndexedSymbol *Symbols, unsigned NumSymbols, CXIndex CIdx,
+ const char *Filename, const char *const *CommandLineArgs,
+ int NumCommandLineArgs, struct CXUnsavedFile *UnsavedFiles,
+ unsigned NumUnsavedFiles, CXRefactoringOptionSet Options,
+ CXSymbolOccurrencesResult *OutResult);
+
+// TODO: Remove
+CINDEX_LINKAGE
+unsigned clang_RenamingResult_getNumModifiedFiles(CXRenamingResult Result);
+
+// TODO: Remove
+CINDEX_LINKAGE
+void clang_RenamingResult_getResultForFile(CXRenamingResult Result,
+ unsigned FileIndex,
+ CXFileRenamingResult *OutResult);
+
+// TODO: Remove
+CINDEX_LINKAGE
+void clang_RenamingResult_dispose(CXRenamingResult Result);
+
+/**
+ * \brief Return the number of files that have occurrences of the specific
+ * symbol.
+ */
+CINDEX_LINKAGE
+unsigned clang_SymbolOccurrences_getNumFiles(CXSymbolOccurrencesResult Result);
+
+/**
+ * \brief Return the set of symbol occurrences in a single file.
+ *
+ * The resulting \c CXSymbolOccurrencesInFile is managed by the
+ * \c CXSymbolOccurrencesResult and doesn't have to be disposed of manually.
+ */
+CINDEX_LINKAGE
+void clang_SymbolOccurrences_getOccurrencesForFile(
+ CXSymbolOccurrencesResult Result, unsigned FileIndex,
+ CXSymbolOccurrencesInFile *OutResult);
+
+// TODO: Support refactoring continuations for \c CXSymbolOccurrencesResult,
+// e.g. for function parameter name rename.
+
+/**
+ * \brief Free the given symbol occurrences result.
+ */
+CINDEX_LINKAGE
+void clang_SymbolOccurrences_dispose(CXSymbolOccurrencesResult Result);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_REFACTOR_PERFORM Performing refactoring operations.
+ *
+ * @{
+ */
+
+/**
+ * \brief Opaque pointer representing the results of the refactoring operation.
+ *
+ * The result of a refactoring action depends on the \c CXRefactoringAction, and
+ * is invalidated after \c CXRefactoringAction is destroyed.
+ */
+typedef void *CXRefactoringResult;
+
+/**
+ * \brief Opaque pointer representing a refactoring continuation.
+ *
+ * Refactoring continuations allow refactoring operations to run in external
+ * AST units with some results that were obtained after querying the indexer.
+ *
+ * The refactoring continuation is not dependent on the \c CXRefactoringAction
+ * or \c CXRefactoringResult. It does depend on the initiation
+ * \c CXTranslationUnit initially, but that dependency can be terminated.
+ */
+typedef void *CXRefactoringContinuation;
+
+/**
+ * \brief Opaque pointer representing a query to the indexer.
+ */
+typedef void *CXIndexerQuery;
+
+/**
+ * \brief Performs the previously initiated refactoring operation.
+ *
+ * This function executes the refactoring operation which produces a set of
+ * candidate source replacements that can be applied to the source files.
+ *
+ * \param Action The refactoring action.
+ *
+ * \param CommandLineArgs The command-line arguments that would be
+ * passed to the \c clang executable if it were being invoked out-of-process.
+ * These command-line options will be parsed and will affect how the translation
+ * unit is parsed.
+ *
+ * \param NumCommandLineArgs The number of command-line arguments in
+ * \c CommandLineArgs.
+ *
+ * \param UnsavedFiles the files that have not yet been saved to disk
+ * but may be required for parsing, including the contents of
+ * those files. The contents and name of these files (as specified by
+ * CXUnsavedFile) are copied when necessary, so the client only needs to
+ * guarantee their validity until the call to this function returns.
+ *
+ * \param NumUnsavedFiles the number of unsaved file entries in \p
+ * UnsavedFiles.
+ *
+ * \param Options The optional refactoring options that might have an influence
+ * on the way the particular action will be performed.
+ *
+ * \param[out] OutFailureReason An optional pointer to store a message that
+ * describes why the action wasn't performed.
+ *
+ * \returns If successful, a new \c CXRefactoringResult structure containing the
+ * source replacement candidates, which should eventually be freed with
+ * \c clang_RefactoringResult_dispose(). If the refactoring operation fails,
+ * returns NULL.
+ */
+CINDEX_LINKAGE
+CXRefactoringResult clang_Refactoring_performOperation(
+ CXRefactoringAction Action, const char *const *CommandLineArgs,
+ int NumCommandLineArgs, struct CXUnsavedFile *UnsavedFiles,
+ unsigned NumUnsavedFiles, CXRefactoringOptionSet Options,
+ CXString *OutFailureReason);
+
+// TODO: Remove. This is the deprecated API.
+CINDEX_LINKAGE
+void clang_RefactoringResult_getReplacements(
+ CXRefactoringResult Result, CXRefactoringReplacements_Old *OutReplacements);
+
+/**
+ * \brief Return the set of refactoring source replacements.
+ *
+ * The resulting \c CXRefactoringReplacements are managed by the
+ * \c CXRefactoringResult and don't have to be disposed of manually.
+ */
+CINDEX_LINKAGE
+CXRefactoringReplacements
+clang_RefactoringResult_getSourceReplacements(CXRefactoringResult Result);
+
+/**
+ * \brief Represents a set of symbol occurrences that are associated with a
+ * single refactoring replacement.
+ *
+ * The symbol occurrences depend on \c CXRefactoringResult, and can't be
+ * used after the refactoring result is freed.
+ */
+typedef struct {
+ const CXSymbolOccurrence *AssociatedSymbolOccurrences;
+ unsigned NumAssociatedSymbolOccurrences;
+} CXRefactoringReplacementAssociatedSymbolOccurrences;
+
+/**
+ * \brief Return the set of symbol occurrences that are associated with the
+ * given \p Replacement.
+ */
+CINDEX_LINKAGE
+CXRefactoringReplacementAssociatedSymbolOccurrences
+clang_RefactoringReplacement_getAssociatedSymbolOccurrences(
+ CXRefactoringReplacement Replacement);
+
+/**
+ * \brief Returns the refactoring continuation associated with this result, or
+ * NULL if this result has no refactoring continuation.
+ */
+CINDEX_LINKAGE
+CXRefactoringContinuation
+clang_RefactoringResult_getContinuation(CXRefactoringResult Result);
+
+/**
+ * \brief Free the given refactoring result.
+ */
+CINDEX_LINKAGE
+void clang_RefactoringResult_dispose(CXRefactoringResult Result);
+
+/**
+ * \brief Load the indexer query results from a YAML string.
+ *
+ * Mainly used for testing.
+ */
+CINDEX_LINKAGE
+enum CXErrorCode
+clang_RefactoringContinuation_loadSerializedIndexerQueryResults(
+ CXRefactoringContinuation Continuation, const char *Source);
+
+/**
+ * \brief Return the number of indexer queries that a refactoring continuation
+ * has.
+ */
+CINDEX_LINKAGE
+unsigned clang_RefactoringContinuation_getNumIndexerQueries(
+ CXRefactoringContinuation Continuation);
+
+/**
+ * \brief Return the indexer query at index \p Index.
+ */
+CINDEX_LINKAGE
+CXIndexerQuery clang_RefactoringContinuation_getIndexerQuery(
+ CXRefactoringContinuation Continuation, unsigned Index);
+
+/**
+ * \brief Verify that the all of the indexer queries are satisfied by the
+ * continuation.
+ *
+ * \returns Null if all of the queries are satisfied an no errors have been
+ * reported, or a set of diagnostics that describes why the continuation should
+ * not be run.
+ */
+CINDEX_LINKAGE
+CXDiagnosticSet clang_RefactoringContinuation_verifyBeforeFinalizing(
+ CXRefactoringContinuation Continuation);
+
+/**
+ * \brief Terminate the connection between the initiation TU and the refactoring
+ * continuation.
+ *
+ * The continuation converts all the TU-specific state to TU-independent state.
+ * The indexer queries that are associate with this continuation are also
+ * invalidated.
+ */
+CINDEX_LINKAGE
+void clang_RefactoringContinuation_finalizeEvaluationInInitationTU(
+ CXRefactoringContinuation Continuation);
+
+/**
+ * \brief Continue performing the previously initiated and performed refactoring
+ * operation in the given translation unit \p TU.
+ */
+CINDEX_LINKAGE
+CXRefactoringResult clang_RefactoringContinuation_continueOperationInTU(
+ CXRefactoringContinuation Continuation, CXTranslationUnit TU,
+ CXString *OutFailureReason);
+
+/**
+ * \brief Free the given refactoring continuation.
+ */
+CINDEX_LINKAGE
+void clang_RefactoringContinuation_dispose(
+ CXRefactoringContinuation Continuation);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_REFACTOR_INDEXER_QUERY Indexer Queries.
+ *
+ * @{
+ */
+
+/**
+ * \brief The types of indexer queries.
+ */
+enum CXIndexerQueryKind {
+ CXIndexerQuery_Unknown = 0,
+
+ /**
+ * \brief The indexer should find the file that contains/should contain the
+ * implementation of some declaration.
+ * A file result is expected.
+ */
+ CXIndexerQuery_Decl_FileThatShouldImplement = 1,
+
+ /**
+ * \brief The indexer should determine if the some declaration is defined.
+ * An integer result is expected.
+ */
+ CXIndexerQuery_Decl_IsDefined = 2,
+};
+
+/**
+ * \brief Return the kind of the indexer query \p Query.
+ */
+CINDEX_LINKAGE
+enum CXIndexerQueryKind clang_IndexerQuery_getKind(CXIndexerQuery Query);
+
+/**
+ * \brief Return the number of cursors that the \p Query has.
+ */
+CINDEX_LINKAGE
+unsigned clang_IndexerQuery_getNumCursors(CXIndexerQuery Query);
+
+/**
+ * \brief Return the cursor at the given \p CursorIndex.
+ */
+CINDEX_LINKAGE
+CXCursor clang_IndexerQuery_getCursor(CXIndexerQuery Query,
+ unsigned CursorIndex);
+
+/**
+ * \brief The action that the indexer should take after evaluating the query.
+ */
+enum CXIndexerQueryAction {
+ /**
+ * \brief This result requires no further action.
+ */
+ CXIndexerQueryAction_None = 0,
+
+ /**
+ * \brief The indexer should run the \c CXRefactoringContinuaton in a
+ * translation unit that contains this file.
+ */
+ CXIndexerQueryAction_RunContinuationInTUThatHasThisFile = 1,
+};
+
+/**
+ * \brief Consumes an integer/boolean query result.
+ */
+CINDEX_LINKAGE
+enum CXIndexerQueryAction
+clang_IndexerQuery_consumeIntResult(CXIndexerQuery Query, unsigned CursorIndex,
+ int Value);
+
+/**
+ * \brief Consumes a filename query result.
+ *
+ * This function may return
+ * \c CXIndexerQueryAction_RunContinuationInTUThatHasThisFile which
+ * should tell the indexer that it has to run the refactoring continuation in
+ * the TU that contains this file.
+ */
+CINDEX_LINKAGE
+enum CXIndexerQueryAction
+clang_IndexerQuery_consumeFileResult(CXIndexerQuery Query, unsigned CursorIndex,
+ const char *Filename);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LLVM_CLANG_C_REFACTOR_H */
diff --git a/clang/include/clang/APINotes/APINotesReader.h b/clang/include/clang/APINotes/APINotesReader.h
index baf6334064024..00513258c263c 100644
--- a/clang/include/clang/APINotes/APINotesReader.h
+++ b/clang/include/clang/APINotes/APINotesReader.h
@@ -46,6 +46,13 @@ class APINotesReader {
APINotesReader(const APINotesReader &) = delete;
APINotesReader &operator=(const APINotesReader &) = delete;
+ /// Retrieve the name of the module for which this reader is providing API
+ /// notes.
+ llvm::StringRef getModuleName() const;
+
+ /// Retrieve the module options
+ ModuleOptions getModuleOptions() const;
+
/// Captures the completed versioned information for a particular part of
/// API notes, including both unversioned API notes and each versioned API
/// note for that particular entity.
diff --git a/clang/include/clang/APINotes/APINotesWriter.h b/clang/include/clang/APINotes/APINotesWriter.h
index 3cc16c3d959fa..6a5e59f96869e 100644
--- a/clang/include/clang/APINotes/APINotesWriter.h
+++ b/clang/include/clang/APINotes/APINotesWriter.h
@@ -130,6 +130,9 @@ class APINotesWriter {
/// \param Info Information about this typedef.
void addTypedef(std::optional Ctx, llvm::StringRef Name,
const TypedefInfo &Info, llvm::VersionTuple SwiftVersion);
+
+ /// Add module options
+ void addModuleOptions(ModuleOptions opts);
};
} // namespace api_notes
} // namespace clang
diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h
index fb2b91a3e1750..11dac027e3e3c 100644
--- a/clang/include/clang/APINotes/Types.h
+++ b/clang/include/clang/APINotes/Types.h
@@ -338,6 +338,72 @@ inline bool operator!=(const ContextInfo &LHS, const ContextInfo &RHS) {
return !(LHS == RHS);
}
+/* TO_UPSTREAM(BoundsSafety) ON */
+class BoundsSafetyInfo {
+public:
+ enum class BoundsSafetyKind {
+ CountedBy = 0,
+ CountedByOrNull,
+ SizedBy,
+ SizedByOrNull,
+ EndedBy,
+ };
+
+private:
+ /// Whether this property has been audited for nullability.
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned KindAudited : 1;
+
+ /// The kind of nullability for this property. Only valid if the nullability
+ /// has been audited.
+ LLVM_PREFERRED_TYPE(BoundsSafetyKind)
+ unsigned Kind : 3;
+
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned LevelAudited : 1;
+
+ unsigned Level : 3;
+
+public:
+ std::string ExternalBounds;
+
+ BoundsSafetyInfo()
+ : KindAudited(false), Kind(0), LevelAudited(false), Level(0),
+ ExternalBounds("") {}
+
+ std::optional getKind() const {
+ return KindAudited ? std::optional(
+ static_cast(Kind))
+ : std::nullopt;
+ }
+
+ void setKindAudited(BoundsSafetyKind kind) {
+ KindAudited = true;
+ Kind = static_cast(kind);
+ }
+
+ std::optional getLevel() const {
+ return LevelAudited ? std::optional(Level) : std::nullopt;
+ }
+
+ void setLevelAudited(unsigned level) {
+ LevelAudited = true;
+ Level = level;
+ }
+
+ friend bool operator==(const BoundsSafetyInfo &, const BoundsSafetyInfo &);
+
+ LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
+};
+
+inline bool operator==(const BoundsSafetyInfo &LHS,
+ const BoundsSafetyInfo &RHS) {
+ return LHS.KindAudited == RHS.KindAudited && LHS.Kind == RHS.Kind &&
+ LHS.LevelAudited == RHS.LevelAudited && LHS.Level == RHS.Level &&
+ LHS.ExternalBounds == RHS.ExternalBounds;
+}
+/* TO_UPSTREAM(BoundsSafety) OFF */
+
/// API notes for a variable/property.
class VariableInfo : public CommonEntityInfo {
/// Whether this property has been audited for nullability.
@@ -477,10 +543,14 @@ class ParamInfo : public VariableInfo {
unsigned RawRetainCountConvention : 3;
public:
+ /* TO_UPSTREAM(BoundsSafety) ON */
+ std::optional BoundsSafety;
+ /* TO_UPSTREAM(BoundsSafety) OFF */
+
ParamInfo()
: NoEscapeSpecified(false), NoEscape(false),
LifetimeboundSpecified(false), Lifetimebound(false),
- RawRetainCountConvention() {}
+ RawRetainCountConvention(), BoundsSafety(std::nullopt) {}
std::optional isNoEscape() const {
return NoEscapeSpecified ? std::optional(NoEscape) : std::nullopt;
@@ -526,6 +596,11 @@ class ParamInfo : public VariableInfo {
if (!RawRetainCountConvention)
RawRetainCountConvention = RHS.RawRetainCountConvention;
+ /* TO_UPSTREAM(BoundsSafety) ON */
+ if (!BoundsSafety)
+ BoundsSafety = RHS.BoundsSafety;
+ /* TO_UPSTREAM(BoundsSafety) OFF */
+
return *this;
}
@@ -540,7 +615,10 @@ inline bool operator==(const ParamInfo &LHS, const ParamInfo &RHS) {
LHS.NoEscape == RHS.NoEscape &&
LHS.LifetimeboundSpecified == RHS.LifetimeboundSpecified &&
LHS.Lifetimebound == RHS.Lifetimebound &&
- LHS.RawRetainCountConvention == RHS.RawRetainCountConvention;
+ LHS.RawRetainCountConvention == RHS.RawRetainCountConvention &&
+ /* TO_UPSTREAM(BoundsSafety) ON */
+ LHS.BoundsSafety == RHS.BoundsSafety;
+ /* TO_UPSTREAM(BoundsSafety) OFF */
}
inline bool operator!=(const ParamInfo &LHS, const ParamInfo &RHS) {
@@ -583,6 +661,11 @@ class FunctionInfo : public CommonEntityInfo {
/// Ownership convention for return value
std::string SwiftReturnOwnership;
+ /* TO_UPSTREAM(BoundsSafety) ON */
+ /// Bounds annotations for the return value
+ std::optional ReturnBoundsSafety;
+ /* TO_UPSTREAM(BoundsSafety) OFF */
+
/// The function parameters.
std::vector Params;
@@ -700,6 +783,9 @@ class ObjCMethodInfo : public FunctionInfo {
}
LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
+
+ void mergePropInfoIntoGetter(const ObjCPropertyInfo &pInfo);
+ void mergePropInfoIntoSetter(const ObjCPropertyInfo &pInfo);
};
inline bool operator==(const ObjCMethodInfo &LHS, const ObjCMethodInfo &RHS) {
@@ -929,6 +1015,11 @@ struct ObjCSelectorRef {
unsigned NumArgs;
llvm::ArrayRef Identifiers;
};
+
+/// Descripts a series of options for a module
+struct ModuleOptions {
+ bool SwiftInferImportAsMember = false;
+};
} // namespace api_notes
} // namespace clang
diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h
index cb942ea865e2d..21903ebb4f9a5 100644
--- a/clang/include/clang/AST/APValue.h
+++ b/clang/include/clang/AST/APValue.h
@@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_AST_APVALUE_H
#define LLVM_CLANG_AST_APVALUE_H
+#include "clang/AST/CharUnits.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/APFixedPoint.h"
#include "llvm/ADT/APFloat.h"
@@ -29,7 +30,6 @@ template class BasicReaderBase;
class AddrLabelExpr;
class ASTContext;
- class CharUnits;
class CXXRecordDecl;
class Decl;
class DiagnosticBuilder;
@@ -88,6 +88,60 @@ class DynamicAllocLValue {
static constexpr int NumLowBitsAvailable = 3;
};
+
+/* TO_UPSTREAM(BoundsSafety) ON*/
+/// Symbolic representation of a size forged pointer
+class ForgedPtrLValue {
+ const ValueDecl *Base;
+
+public:
+ ForgedPtrLValue() : Base(nullptr) {}
+ explicit ForgedPtrLValue(const ValueDecl *Base) : Base(Base) {}
+ explicit operator bool() const { return Base; }
+
+ const ValueDecl *getBaseValueDecl() const { return Base; }
+
+ void *getOpaqueValue() { return const_cast(Base); }
+ static ForgedPtrLValue getFromOpaqueValue(void *Value) {
+ ForgedPtrLValue V;
+ V.Base = reinterpret_cast(Value);
+ return V;
+ }
+};
+
+/// This represents a pointer union that is either DynamicAllocLValue or
+/// ForgedPtrLValue.
+///
+/// This is a hack to be able to add ForgedPtrLValue as another pointer member
+/// to the pointer union of APValue::LValueBase because it already has the
+/// maximum number of members for the available low bits, i.e., 2.
+/// DynamicAllocLValue and ValueDecl* have 3 low bits available and thus we can
+/// use this one more remaining bit to encode ForgedPtrLValue.
+class DynamicAllocOrForgedPtrLValue
+ : public llvm::PointerUnion {
+
+public:
+ using BaseTy = llvm::PointerUnion;
+
+ DynamicAllocOrForgedPtrLValue() = default;
+ DynamicAllocOrForgedPtrLValue(DynamicAllocLValue LV) : BaseTy(LV) {}
+ DynamicAllocOrForgedPtrLValue(ForgedPtrLValue LV) : BaseTy(LV) {}
+
+ explicit operator bool() const {
+ PointerUnion pu = *this;
+ if (isa(pu)) {
+ return static_cast(cast(pu));
+ }
+ return static_cast(cast(pu));
+ }
+
+ static DynamicAllocOrForgedPtrLValue getFromOpaqueValue(void *Value) {
+ DynamicAllocOrForgedPtrLValue V;
+ V.Val.setFromOpaqueValue(Value);
+ return V;
+ }
+};
+/* TO_UPSTREAM(BoundsSafety) OFF*/
}
namespace llvm {
@@ -113,6 +167,28 @@ template<> struct PointerLikeTypeTraits {
static constexpr int NumLowBitsAvailable =
clang::DynamicAllocLValue::NumLowBitsAvailable;
};
+
+/* TO_UPSTREAM(BoundsSafety) ON*/
+template <> struct PointerLikeTypeTraits {
+ static void *getAsVoidPointer(clang::ForgedPtrLValue V) {
+ return V.getOpaqueValue();
+ }
+ static clang::ForgedPtrLValue getFromVoidPointer(void *P) {
+ return clang::ForgedPtrLValue::getFromOpaqueValue(P);
+ }
+ static constexpr int NumLowBitsAvailable = 3;
+};
+
+template <> struct PointerLikeTypeTraits {
+ static void *getAsVoidPointer(clang::DynamicAllocOrForgedPtrLValue V) {
+ return V.getOpaqueValue();
+ }
+ static clang::DynamicAllocOrForgedPtrLValue getFromVoidPointer(void *P) {
+ return clang::DynamicAllocOrForgedPtrLValue::getFromOpaqueValue(P);
+ }
+ static constexpr int NumLowBitsAvailable = 2;
+};
+/* TO_UPSTREAM(BoundsSafety) OFF*/
}
namespace clang {
@@ -145,27 +221,53 @@ class APValue {
class alignas(uint64_t) LValueBase {
typedef llvm::PointerUnion
+ DynamicAllocOrForgedPtrLValue>
PtrTy;
+ template
+ static constexpr bool IsDAOrForgedV =
+ std::is_same::value ||
+ std::is_same::value;
+
+ template
+ using EnableIfDAOrForged =
+ typename std::enable_if, U>::type;
+
+ template
+ using EnableIfNotDANorForged =
+ typename std::enable_if, U>::type;
+
public:
LValueBase() : Local{} {}
LValueBase(const ValueDecl *P, unsigned I = 0, unsigned V = 0);
LValueBase(const Expr *P, unsigned I = 0, unsigned V = 0);
static LValueBase getDynamicAlloc(DynamicAllocLValue LV, QualType Type);
static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo);
+ static LValueBase getForgedPtr(ForgedPtrLValue LV, QualType Type);
void Profile(llvm::FoldingSetNodeID &ID) const;
- template bool is() const { return isa(Ptr); }
+ template EnableIfNotDANorForged is() const {
+ return isa(Ptr);
+ }
+
+ template EnableIfDAOrForged is() const;
+
+ template EnableIfNotDANorForged get() const {
+ return cast(Ptr);
+ }
- template T get() const { return cast(Ptr); }
+ template EnableIfDAOrForged get() const;
- template T dyn_cast() const {
+ template EnableIfNotDANorForged dyn_cast() const {
return dyn_cast_if_present(Ptr);
}
+ template EnableIfDAOrForged dyn_cast() const;
+
void *getOpaqueValue() const;
+ // TO_UPSTREAM(BoundsSafety)
+ const ValueDecl *getValueDecl() const;
bool isNull() const;
@@ -175,6 +277,7 @@ class APValue {
unsigned getVersion() const;
QualType getTypeInfoType() const;
QualType getDynamicAllocType() const;
+ QualType getForgedPtrAsArrayType() const;
QualType getType() const;
@@ -196,6 +299,8 @@ class APValue {
void *TypeInfoType;
/// The QualType, if this is a DynamicAllocLValue.
void *DynamicAllocType;
+ /// The QualType, if this is a ForgedPtrLValue.
+ void *ForgedPtrAsArrayType;
};
};
@@ -306,10 +411,45 @@ class APValue {
};
struct MemberPointerData;
+ /* TO_UPSTREAM(BoundsSafety) ON */
+ struct LVBase {
+ APValue::LValueBase Base;
+ CharUnits Offset;
+ // BoundsSafety : While the base also holds a corresponding constant array type
+ // for forged pointer, we still keep track of forged size because the array
+ // size will be different from the actual forged size if it is not a multiple
+ // of element type size after a bitcast. The codegen doesn't round up/down
+ // the bounds to be a type-size multiple, we should keep it the same for
+ // constant emission. Once __builtin_forge_* has a type as an argument, we
+ // may consider round down the size with the element type size.
+ CharUnits ForgedSize;
+ // While 'Offset' is the offset within the LValue, 'ForgedOffset' is the
+ // offset of the base pointer of __builtin_unsafe_forge*. For example, in
+ // the following,
+ // '__bidi_indexable_unsafe_forge_bidi_indexable(base + N) + M'
+ // 'N' should be 'ForgedOffset' and 'M' should be 'Offset'. This way, the
+ // forged pointer itself becomes an LValue starting at base + 'ForgedOffset'.
+ CharUnits ForgedOffset;
+ unsigned PathLength;
+ bool IsNullPtr : 1;
+ bool IsOnePastTheEnd : 1;
+ bool IsForgeBidi : 1;
+ bool IsForgeSingle : 1;
+ bool IsForgeTerminatedBy : 1;
+ };
+
+ struct LVPlaceHolder {
+ LVBase Base;
+ LValuePathEntry Path[1];
+ };
+ /* TO_UPSTREAM(BoundsSafety) OFF */
+
// We ensure elsewhere that Data is big enough for LV and MemberPointerData.
typedef llvm::AlignedCharArrayUnion DataType;
+ UnionData, AddrLabelDiffData,
+ // TO_UPSTREAM(BoundsSafety)
+ LVPlaceHolder> DataType;
static const size_t DataSize = sizeof(DataType);
DataType Data;
@@ -553,12 +693,33 @@ class APValue {
const CharUnits &getLValueOffset() const {
return const_cast(this)->getLValueOffset();
}
+
+ /* TO_UPSTREAM(BoundsSafety) ON */
+ CharUnits &getLValueForgedSize();
+ const CharUnits &getLValueForgedSize() const {
+ return const_cast(this)->getLValueForgedSize();
+ }
+
+ CharUnits &getLValueForgedOffset();
+ const CharUnits &getLValueForgedOffset() const {
+ return const_cast(this)->getLValueForgedOffset();
+ }
+
+ CharUnits getUnwrappedLValueOffset() const;
+ /* TO_UPSTREAM(BoundsSafety) OFF */
+
bool isLValueOnePastTheEnd() const;
bool hasLValuePath() const;
ArrayRef getLValuePath() const;
unsigned getLValueCallIndex() const;
unsigned getLValueVersion() const;
bool isNullPointer() const;
+ /* TO_UPSTREAM(BoundsSafety) ON */
+ bool isLValueForgeBidi() const;
+ bool isLValueForgeSingle() const;
+ bool isLValueForgeTerminatedBy() const;
+ bool isLValueForge() const;
+ /* TO_UPSTREAM(BoundsSafety) OFF */
APValue &getVectorElt(unsigned I) {
assert(isVector() && "Invalid accessor");
@@ -694,6 +855,12 @@ class APValue {
((AddrLabelDiffData *)(char *)&Data)->RHSExpr = RHSExpr;
}
+ /* TO_UPSTREAM(BoundsSafety) ON */
+ void setLValueForgedBidi(const CharUnits &Size, const CharUnits &Offset);
+ void setLValueForgedSingle(const CharUnits &Offset);
+ void setLValueForgedTerminatedBy(const CharUnits &Offset);
+ /* TO_UPSTREAM(BoundsSafety) OFF */
+
private:
void DestroyDataAndMakeUninit();
void MakeInt() {
diff --git a/clang/include/clang/AST/ASTConsumer.h b/clang/include/clang/AST/ASTConsumer.h
index 447f2592d2359..6cf4504dcfa60 100644
--- a/clang/include/clang/AST/ASTConsumer.h
+++ b/clang/include/clang/AST/ASTConsumer.h
@@ -27,6 +27,7 @@ namespace clang {
class VarDecl;
class FunctionDecl;
class ImportDecl;
+ class TargetInfo;
/// ASTConsumer - This is an abstract interface that should be implemented by
/// clients that read ASTs. This abstraction layer allows the client to be
@@ -47,6 +48,14 @@ class ASTConsumer {
/// ASTContext.
virtual void Initialize(ASTContext &Context) {}
+ /// Initialize - This is called to initialize the consumer, providing the
+ /// ASTContext. 'CodeGenTargetInfo' specifies the code-generation configuration
+ /// for this compilation instance, which may differ from the one carried
+ /// by the Context itself only in the OS Version number -
+ /// for example when type-checking must be performed against an epoch OS version
+ /// while code-generation must run according to the user-specified OS version.
+ virtual void Initialize(ASTContext &Context, const TargetInfo &CodeGenTargetInfo) {}
+
/// HandleTopLevelDecl - Handle the specified top-level declaration. This is
/// called by the parser to process every top-level Decl*.
///
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 33aa2d343aa7a..57621ad75f2cc 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -27,6 +27,7 @@
#include "clang/AST/TemplateName.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
@@ -296,6 +297,14 @@ class ASTContext : public RefCountedBase {
mutable llvm::FoldingSet CountAttributedTypes;
+ /* TO_UPSTREAM(BoundsSafety) ON */
+ mutable llvm::FoldingSet
+ DynamicRangePointerTypes;
+
+ mutable llvm::ContextualFoldingSet
+ ValueTerminatedTypes;
+ /* TO_UPSTREAM(BoundsSafety) OFF */
+
mutable llvm::FoldingSet QualifiedTemplateNames;
mutable llvm::FoldingSet DependentTemplateNames;
mutable llvm::FoldingSet
@@ -542,6 +551,24 @@ class ASTContext : public RefCountedBase {
ASTContext &this_() { return *this; }
+ mutable std::optional ObjCMsgSendUsageFile;
+ llvm::SmallVector ObjCMsgSendUsage;
+
+public:
+ /// Check whether env variable CLANG_COMPILER_OBJC_MESSAGE_TRACE_PATH is set.
+ /// If it is set, assign the value to ObjCMsgSendUsageFile.
+ bool isObjCMsgSendUsageFileSpecified() const;
+
+ /// Return the file name stored in ObjCMsgSendUsageFile if it has a value,
+ /// return an empty string otherwise.
+ std::string getObjCMsgSendUsageFilename() const;
+
+ /// Record an ObjC method.
+ void recordObjCMsgSendUsage(const ObjCMethodDecl *Method);
+
+ /// Write the collected ObjC method tracing information to a file.
+ void writeObjCMsgSendUsages(const std::string &Filename);
+
public:
/// A type synonym for the TemplateOrInstantiation mapping.
using TemplateOrSpecializationInfo =
@@ -888,6 +915,37 @@ class ASTContext : public RefCountedBase {
return DiagAllocator;
}
+ struct AvailabilityDomainInfo {
+ FeatureAvailKind Kind = FeatureAvailKind::None;
+ clang::Decl *Decl = nullptr;
+ ImplicitCastExpr *Call = nullptr;
+ bool IsDeprecated = false;
+ bool isInvalid() const { return Kind == FeatureAvailKind::None; }
+ };
+
+ std::map AvailabilityDomainMap;
+
+ void addAvailabilityDomainMap(StringRef Name, VarDecl *VD) {
+ AvailabilityDomainMap[Name] = VD;
+ }
+
+ std::pair
+ checkNewFeatureAvailability(Decl *D, StringRef DomainName, bool Unavailable);
+
+ bool hasFeatureAvailabilityAttr(const Decl *D) const;
+
+ // Retrieve availability domain information for a feature.
+ AvailabilityDomainInfo getFeatureAvailInfo(StringRef FeatureName) const;
+
+ // Retrieve feature name and availability domain information on a decl. If the
+ // decl doesn't have attribute availability_domain on it, the name will be
+ // empty and AvailabilityDomainInfo::Kind will be set to
+ // FeatureAvailKind::None.
+ std::pair
+ getFeatureAvailInfo(Decl *D) const;
+
+ bool hasUnavailableFeature(const Decl *D) const;
+
const TargetInfo &getTargetInfo() const { return *Target; }
const TargetInfo *getAuxTargetInfo() const { return AuxTarget; }
@@ -1556,9 +1614,12 @@ class ASTContext : public RefCountedBase {
/// Return the uniqued reference to the type for a pointer to
/// the specified type.
- QualType getPointerType(QualType T) const;
- CanQualType getPointerType(CanQualType T) const {
- return CanQualType::CreateUnsafe(getPointerType((QualType) T));
+ QualType getPointerType(QualType T, BoundsSafetyPointerAttributes A =
+ BoundsSafetyPointerAttributes()) const;
+ CanQualType getPointerType(
+ CanQualType T,
+ BoundsSafetyPointerAttributes A = BoundsSafetyPointerAttributes()) const {
+ return CanQualType::CreateUnsafe(getPointerType((QualType)T, A));
}
QualType
@@ -1566,6 +1627,42 @@ class ASTContext : public RefCountedBase {
bool OrNull,
ArrayRef DependentDecls) const;
+ /* TO_UPSTREAM(BoundsSafety) ON */
+ QualType getDynamicRangePointerType(
+ QualType T, Expr *StartPtr, Expr *EndPtr,
+ ArrayRef StartPtrDecls,
+ ArrayRef EndPtrDecls) const;
+
+ QualType getValueTerminatedType(QualType T, Expr *TerminatorExpr) const;
+
+ /// Return a new pointer type with the -fbounds-safety pointer attribute with
+ /// preserving existing AttributedTypes and qualifiers.
+ QualType getBoundsSafetyPointerType(QualType PointerTy,
+ BoundsSafetyPointerAttributes);
+
+ /// Return a result type of merging -fbounds-safety pointer attributes of \p SrcTy
+ /// to \p DstTy, while preserving existing AttributedTypes and qualifiers of
+ /// \p DstTy. The type merging is performed recursively in nested pointers.
+ /// The caller should provide \p MergeFunctor to create a merged pointer type
+ /// using the recursively merged pointee type.
+ /// mergeBoundsSafetyPointerTypes removes any AttributedType(s) from \p
+ /// DstTy, calls \p MergeFunctor to merge the attributes at each level, and
+ /// then reapplies the AttributedType(s) to the merged type. \p OrigDstTy is
+ /// the same as \p DstTy but without dropping the AttributedType(s). This
+ /// allows us to check any AttributedType(s) in \p MergeFunctor in order to
+ /// make decision about the merged type.
+ QualType mergeBoundsSafetyPointerTypes(
+ QualType DstTy, QualType SrcTy,
+ std::function &MergeFunctor,
+ QualType OrigDstTy = QualType());
+
+ QualType getBoundsSafetyAutoPointerType(QualType T,
+ BoundsSafetyPointerAttributes AbiFAttr,
+ bool ShouldAutoBound);
+ /* TO_UPSTREAM(BoundsSafety) OFF */
+
/// Return the uniqued reference to a type adjusted from the original
/// type to a new type.
QualType getAdjustedType(QualType Orig, QualType New) const;
@@ -2651,6 +2748,14 @@ class ASTContext : public RefCountedBase {
uint64_t getTypeSize(QualType T) const { return getTypeInfo(T).Width; }
uint64_t getTypeSize(const Type *T) const { return getTypeInfo(T).Width; }
+ /*TO_UPSTREAM(BoundsSafety) ON*/
+ uint64_t getTypeSizeOrNull(QualType T) const {
+ if (T->isIncompleteOrSizelessType())
+ return 0;
+ return getTypeSize(T);
+ }
+ /*TO_UPSTREAM(BoundsSafety) OFF*/
+
/// Return the size of the character type, in bits.
uint64_t getCharWidth() const {
return getTypeSize(CharTy);
@@ -2897,6 +3002,37 @@ class ASTContext : public RefCountedBase {
return getCanonicalType(T1) == getCanonicalType(T2);
}
+ /* TO_UPSTREAM(BoundsSafety) ON*/
+ /// These enum values (other than CanMerge) are aligned with the options for
+ /// the third parameter in
+ /// diag::err_cond_expr_nested_bounds_safety_pointer_attribute_mismatch
+ enum BoundsSafePointerTypeMergeKind {
+ BSPTMK_NestedBoundsMismatch,
+ BSPTMK_FunctionTypeMismatch,
+ BSPTMK_TerminatedByMismatch,
+ BSPTMK_CanMerge,
+ };
+ /// Given two pointer types that can be unified without losing type safety,
+ /// check whether they can be merged without losing bounds safety.
+ /// In practice this means checking whether their inner pointer type bounds
+ /// sugar nodes match (if any exist). Non-nested pointer types can always be
+ /// unified, potentially requiring dynamic checks.
+ BoundsSafePointerTypeMergeKind canMergeTypeBounds(QualType LHSTy,
+ QualType RHSTy) const;
+
+ /// Given two pointer types, check whether either of them if is a
+ /// ValueTerminatedType, and if so, that the other is a ValueTerminatedType
+ /// with the same terminator. Does not check pointee type!
+ BoundsSafePointerTypeMergeKind
+ checkTerminatedByMismatch(QualType LHSTy, QualType RHSTy) const;
+ BoundsSafePointerTypeMergeKind canMergeInnerTypeBounds(QualType LHSTy,
+ QualType RHSTy) const;
+ BoundsSafePointerTypeMergeKind
+ canMergeFunctionTypeBounds(const FunctionProtoType *LHSTy,
+ const FunctionProtoType *RHSTy) const;
+
+ /* TO_UPSTREAM(BoundsSafety) OFF*/
+
/// Determine whether the given expressions \p X and \p Y are equivalent.
bool hasSameExpr(const Expr *X, const Expr *Y) const;
@@ -2974,6 +3110,16 @@ class ASTContext : public RefCountedBase {
/// Determine if two types are similar, ignoring only CVR qualifiers.
bool hasCvrSimilarType(QualType T1, QualType T2);
+ /* TO_UPSTREAM(BoundsSafety) ON */
+ /// Determine if two types have same -fbounds-safety pointer layouts, recursively.
+ bool hasSameBoundsSafetyPointerLayout(QualType T1, QualType T2);
+
+ /// Determine if two types have compatible -fbounds-safety pointer layouts,
+ /// recursively.
+ bool hasCompatibleBoundsSafetyPointerLayout(QualType T1, QualType T2,
+ bool ExactCheck = false);
+ /* TO_UPSTREAM(BoundsSafety) OFF */
+
/// Retrieves the default calling convention for the current context.
///
/// The context's default calling convention may differ from the current
diff --git a/clang/include/clang/AST/ASTMutationListener.h b/clang/include/clang/AST/ASTMutationListener.h
index 352af42391782..4151881333f23 100644
--- a/clang/include/clang/AST/ASTMutationListener.h
+++ b/clang/include/clang/AST/ASTMutationListener.h
@@ -159,6 +159,17 @@ class ASTMutationListener {
virtual void AddedAttributeToRecord(const Attr *Attr,
const RecordDecl *Record) {}
+ /* TO_UPSTREAM(BoundsSafety) ON*/
+ /// An attribute to a Decl to write in a separate record because the attribute
+ /// and the Decl create a cycle during deserialization.
+ ///
+ /// \param Attr The attribute to the Decl
+ ///
+ /// \param Record The Decl owns the attribute
+ virtual void LazyAttributeToDecl(const Attr *Attr,
+ const Decl *D) {}
+ /* TO_UPSTREAM(BoundsSafety) OFF*/
+
/// The parser find the named module declaration.
virtual void EnteringModulePurview() {}
diff --git a/clang/include/clang/AST/AbstractBasicReader.h b/clang/include/clang/AST/AbstractBasicReader.h
index 0d187eb49d6ca..0c19e98a36df8 100644
--- a/clang/include/clang/AST/AbstractBasicReader.h
+++ b/clang/include/clang/AST/AbstractBasicReader.h
@@ -218,6 +218,13 @@ class DataStreamBasicReader : public BasicReaderBase {
return Qualifiers::fromOpaqueValue(value);
}
+ /* TO_UPSTREAM(BoundsSafety) ON */
+ BoundsSafetyPointerAttributes readBoundsSafetyPointerAttributes() {
+ uint32_t value = asImpl().readUInt32();
+ return BoundsSafetyPointerAttributes::fromOpaqueValue(value);
+ }
+ /* TO_UPSTREAM(BoundsSafety) OFF */
+
FunctionProtoType::ExceptionSpecInfo
readExceptionSpecInfo(llvm::SmallVectorImpl &buffer) {
FunctionProtoType::ExceptionSpecInfo esi;
diff --git a/clang/include/clang/AST/AbstractBasicWriter.h b/clang/include/clang/AST/AbstractBasicWriter.h
index 8ea0c29cf5070..7b7f5f1af028d 100644
--- a/clang/include/clang/AST/AbstractBasicWriter.h
+++ b/clang/include/clang/AST/AbstractBasicWriter.h
@@ -200,6 +200,12 @@ class DataStreamBasicWriter : public BasicWriterBase {
asImpl().writeUInt64(value.getAsOpaqueValue());
}
+ /* TO_UPSTREAM(BoundsSafety) ON */
+ void writeBoundsSafetyPointerAttributes(BoundsSafetyPointerAttributes value) {
+ asImpl().writeUInt32(value.getAsOpaqueValue());
+ }
+ /* TO_UPSTREAM(BoundsSafety) OFF */
+
void writeExceptionSpecInfo(
const FunctionProtoType::ExceptionSpecInfo &esi) {
asImpl().writeUInt32(uint32_t(esi.Type));
diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h
index fe388b9fa045e..d5b6565b26bd0 100644
--- a/clang/include/clang/AST/Attr.h
+++ b/clang/include/clang/AST/Attr.h
@@ -24,6 +24,7 @@
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/PointerEmbeddedInt.h"
#include "clang/Support/Compiler.h"
#include "llvm/Frontend/HLSL/HLSLResource.h"
#include "llvm/Support/CodeGen.h"
@@ -442,6 +443,13 @@ inline ParameterABI ParameterABIAttr::getABI() const {
llvm_unreachable("bad parameter ABI attribute kind");
}
}
+
+/// Determine if type T is a valid subject for a nonnull and similar
+/// attributes. Dependent types are considered valid so they can be checked
+/// during instantiation time. By default, we look through references (the
+/// behavior used by nonnull), but if the second parameter is true, then we
+/// treat a reference type as valid.
+bool isValidPointerAttrType(QualType T, bool RefOkay = false);
} // end namespace clang
#endif
diff --git a/clang/include/clang/AST/AttrIterator.h b/clang/include/clang/AST/AttrIterator.h
index 2f39c144dc160..decf1a3ebe395 100644
--- a/clang/include/clang/AST/AttrIterator.h
+++ b/clang/include/clang/AST/AttrIterator.h
@@ -97,6 +97,8 @@ class specific_attr_iterator {
specific_attr_iterator Right) {
return !(Left == Right);
}
+
+ Iterator getCurrent() const { return Current; }
};
template
diff --git a/clang/include/clang/AST/Availability.h b/clang/include/clang/AST/Availability.h
index 60ca1383f0a44..520a734ec4c28 100644
--- a/clang/include/clang/AST/Availability.h
+++ b/clang/include/clang/AST/Availability.h
@@ -37,6 +37,8 @@ class AvailabilitySpec {
/// Name of the platform that Version corresponds to.
StringRef Platform;
+ StringRef DomainName;
+
SourceLocation BeginLoc, EndLoc;
public:
@@ -45,6 +47,9 @@ class AvailabilitySpec {
: Version(Version), Platform(Platform), BeginLoc(BeginLoc),
EndLoc(EndLoc) {}
+ AvailabilitySpec(StringRef DomainName, SourceLocation Loc)
+ : DomainName(DomainName), BeginLoc(Loc), EndLoc(Loc) {}
+
/// This constructor is used when representing the '*' case.
AvailabilitySpec(SourceLocation StarLoc)
: BeginLoc(StarLoc), EndLoc(StarLoc) {}
@@ -55,7 +60,12 @@ class AvailabilitySpec {
SourceLocation getEndLoc() const { return EndLoc; }
/// Returns true when this represents the '*' case.
- bool isOtherPlatformSpec() const { return Version.empty(); }
+ bool isOtherPlatformSpec() const {
+ return Version.empty() && DomainName.empty();
+ }
+
+ bool isDomainName() const { return !DomainName.empty(); }
+ StringRef getDomainName() const { return DomainName; }
};
class Decl;
diff --git a/clang/include/clang/AST/ComputeDependence.h b/clang/include/clang/AST/ComputeDependence.h
index c298f2620f211..076769a254da6 100644
--- a/clang/include/clang/AST/ComputeDependence.h
+++ b/clang/include/clang/AST/ComputeDependence.h
@@ -79,6 +79,15 @@ class LambdaExpr;
class CXXUnresolvedConstructExpr;
class CXXDependentScopeMemberExpr;
class MaterializeTemporaryExpr;
+/* TO_UPSTREAM(BoundsSafety) ON */
+class MaterializeSequenceExpr;
+class PredefinedBoundsCheckExpr;
+class BoundsCheckExpr;
+class AssumptionExpr;
+class BoundsSafetyPointerPromotionExpr;
+class GetBoundExpr;
+class ForgePtrExpr;
+/* TO_UPSTREAM(BoundsSafety) OFF */
class CXXFoldExpr;
class CXXParenListInitExpr;
class TypeTraitExpr;
@@ -178,6 +187,16 @@ ExprDependence computeDependence(TypeTraitExpr *E);
ExprDependence computeDependence(ConceptSpecializationExpr *E,
bool ValueDependent);
+/* TO_UPSTREAM(BoundsSafety) ON */
+ExprDependence computeDependence(MaterializeSequenceExpr *E);
+ExprDependence computeDependence(PredefinedBoundsCheckExpr *E);
+ExprDependence computeDependence(BoundsCheckExpr *E);
+ExprDependence computeDependence(AssumptionExpr *E);
+ExprDependence computeDependence(BoundsSafetyPointerPromotionExpr *E);
+ExprDependence computeDependence(GetBoundExpr *E);
+ExprDependence computeDependence(ForgePtrExpr *E);
+/* TO_UPSTREAM(BoundsSafety) OFF */
+
ExprDependence computeDependence(SYCLUniqueStableNameExpr *E);
ExprDependence computeDependence(PredefinedExpr *E);
ExprDependence computeDependence(CallExpr *E, ArrayRef PreArgs);
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 406d79ebd6641..c08555ad65b30 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -732,6 +732,46 @@ class ValueDecl : public NamedDecl {
/// can be captured.
bool isInitCapture() const;
+ /* TO_UPSTREAM(BoundsSafety) ON */
+ /// Whether this decl is a dependent count. This returns true for dependent
+ /// counts with and without dereference:
+ /// void foo(int *__counted_by(m) p, int m,
+ /// int *__counted_by(*n) *q, int *n);
+ /// True for both `m` and `n`.
+ bool isDependentCount() const;
+
+ /// Whether this decl is a dependent count without a dereference:
+ /// void foo(int *__counted_by(m) p, int m,
+ /// int *__counted_by(*n) *q, int *n);
+ /// True for `m`, but false for `n`.
+ bool isDependentCountWithoutDeref() const;
+
+ /// Whether this decl is a dependent count with a dereference:
+ /// void foo(int *__counted_by(m) p, int m,
+ /// int *__counted_by(*n) *q, int *n);
+ /// False for `m`, but true for `n`.
+ bool isDependentCountWithDeref() const;
+
+ /// Whether this decl is a dependent count that is used at least once in a
+ /// count expression of an inout count-attributed pointer.
+ /// void foo(int *__counted_by(a) p, int a,
+ /// int *__counted_by(*b) q, int *b,
+ /// int *__counted_by(c) *r, int c,
+ /// int *__counted_by(*d) *s, int *d);
+ /// True for `c` and `d`, but false for `a` and `b`.
+ /// void bar(int *__counted_by(count) in_p,
+ /// int *__counted_by(count) *out_p,
+ /// int count);
+ /// True for `count` (because of `out_p`).
+ bool isDependentCountThatIsUsedInInoutPointer() const;
+
+ /// Whether this decl is a dependent parameter referred to by the return type
+ /// that is a bounds-attributed type.
+ bool isDependentParamOfReturnType(
+ const BoundsAttributedType **RetType = nullptr,
+ const TypeCoupledDeclRefInfo **Info = nullptr) const;
+ /* TO_UPSTREAM(BoundsSafety) OFF */
+
// If this is a VarDecl, or a BindindDecl with an
// associated decomposed VarDecl, return that VarDecl.
VarDecl *getPotentiallyDecomposedVarDecl();
@@ -4506,6 +4546,9 @@ class RecordDecl : public TagDecl {
/// leaks.
bool isOrContainsUnion() const;
+ // TO_UPSTREAM(BoundsSafety)
+ bool isParentStructOf(const Decl *D) const;
+
// Iterator access to field members. The field iterator only visits
// the non-static data members of this class, ignoring any static
// data members, functions, constructors, destructors, etc.
@@ -5341,6 +5384,12 @@ void Redeclarable::setPreviousDecl(decl_type *PrevDecl) {
cast(static_cast(this))->isLinkageValid());
}
+/* TO_UPSTREAM(BoundsSafety) ON */
+// A BoundsSafety helper function.
+/// Return `true` if \p D is const qualified or attributed as immutable.
+bool IsConstOrLateConst(const Decl *D);
+/* TO_UPSTREAM(BoundsSafety) OFF */
+
// Inline function definitions.
/// Check if the given decl is complete.
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index c6326a8ba506d..3b0d2c994eb38 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -778,7 +778,7 @@ class alignas(8) Decl {
/// 'weak_import' attribute, but may also be marked with an
/// 'availability' attribute where we're targing a platform prior to
/// the introduction of this feature.
- bool isWeakImported() const;
+ bool isWeakImported(VersionTuple EnclosingVersion = VersionTuple()) const;
/// Determines whether this symbol can be weak-imported,
/// e.g., whether it would be well-formed to add the weak_import
diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h
index 2541edba83855..155acb11f3878 100644
--- a/clang/include/clang/AST/DeclObjC.h
+++ b/clang/include/clang/AST/DeclObjC.h
@@ -882,6 +882,11 @@ class ObjCPropertyDecl : public NamedDecl {
return Assign;
}
+ /// Return true if this property has an explicitly specified getter name.
+ bool hasExplicitGetterName() const {
+ return (PropertyAttributes & ObjCPropertyAttribute::kind_getter);
+ }
+
Selector getGetterName() const { return GetterName; }
SourceLocation getGetterNameLoc() const { return GetterNameLoc; }
@@ -890,6 +895,11 @@ class ObjCPropertyDecl : public NamedDecl {
GetterNameLoc = Loc;
}
+ /// Return true if this property has an explicitly specified setter name.
+ bool hasExplicitSetterName() const {
+ return (PropertyAttributes & ObjCPropertyAttribute::kind_setter);
+ }
+
Selector getSetterName() const { return SetterName; }
SourceLocation getSetterNameLoc() const { return SetterNameLoc; }
@@ -1240,7 +1250,8 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// which will be NULL if this class has not yet been defined.
///
/// The bit indicates when we don't need to check for out-of-date
- /// declarations. It will be set unless modules are enabled.
+ /// declarations. It will be set unless there is an ExternalASTSource that
+ /// could provide a definition.
llvm::PointerIntPair Data;
ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, SourceLocation AtLoc,
@@ -1529,7 +1540,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
// If the name of this class is out-of-date, bring it up-to-date, which
// might bring in a definition.
// Note: a null value indicates that we don't have a definition and that
- // modules are enabled.
+ // there is a ExternalASTSource that could provide a definition.
if (!Data.getOpaqueValue())
getMostRecentDecl();
@@ -2101,7 +2112,8 @@ class ObjCProtocolDecl : public ObjCContainerDecl,
/// which will be NULL if this class has not yet been defined.
///
/// The bit indicates when we don't need to check for out-of-date
- /// declarations. It will be set unless modules are enabled.
+ /// declarations. It will be set unless there is an ExternalASTSource that
+ /// could provide a definition.
llvm::PointerIntPair Data;
ObjCProtocolDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id,
@@ -2239,7 +2251,7 @@ class ObjCProtocolDecl : public ObjCContainerDecl,
// If the name of this protocol is out-of-date, bring it up-to-date, which
// might bring in a definition.
// Note: a null value indicates that we don't have a definition and that
- // modules are enabled.
+ // there is a ExternalASTSource that could provide a definition.
if (!Data.getOpaqueValue())
getMostRecentDecl();
@@ -2775,17 +2787,25 @@ raw_ostream &operator<<(raw_ostream &OS, const ObjCImplementationDecl &ID);
class ObjCCompatibleAliasDecl : public NamedDecl {
/// Class that this is an alias of.
ObjCInterfaceDecl *AliasedClass;
+ /// The location of the name of the referenced class.
+ SourceLocation AliasedClassLoc;
+ /// The location of the '@'.
+ SourceLocation AtLoc;
- ObjCCompatibleAliasDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
- ObjCInterfaceDecl* aliasedClass)
- : NamedDecl(ObjCCompatibleAlias, DC, L, Id), AliasedClass(aliasedClass) {}
+ ObjCCompatibleAliasDecl(DeclContext *DC, SourceLocation NameLoc,
+ IdentifierInfo *Id, ObjCInterfaceDecl *AliasedClass,
+ SourceLocation AliasedClassLoc, SourceLocation AtLoc)
+ : NamedDecl(ObjCCompatibleAlias, DC, NameLoc, Id),
+ AliasedClass(AliasedClass), AliasedClassLoc(AliasedClassLoc),
+ AtLoc(AtLoc) {}
void anchor() override;
public:
- static ObjCCompatibleAliasDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L, IdentifierInfo *Id,
- ObjCInterfaceDecl* aliasedClass);
+ static ObjCCompatibleAliasDecl *
+ Create(ASTContext &C, DeclContext *DC, SourceLocation NameLoc,
+ IdentifierInfo *Id, ObjCInterfaceDecl *AliasedClass,
+ SourceLocation AliasedClassLoc, SourceLocation AtLoc);
static ObjCCompatibleAliasDecl *CreateDeserialized(ASTContext &C,
GlobalDeclID ID);
@@ -2794,6 +2814,17 @@ class ObjCCompatibleAliasDecl : public NamedDecl {
ObjCInterfaceDecl *getClassInterface() { return AliasedClass; }
void setClassInterface(ObjCInterfaceDecl *D) { AliasedClass = D; }
+ SourceLocation getClassInterfaceLoc() const { return AliasedClassLoc; }
+
+ void setClassInterfaceLoc(SourceLocation Loc) { AliasedClassLoc = Loc; }
+
+ SourceLocation getAtLoc() const { return AtLoc; }
+ void setAtLoc(SourceLocation Loc) { AtLoc = Loc; }
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ return SourceRange(AtLoc, AtLoc);
+ }
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCCompatibleAlias; }
};
diff --git a/clang/include/clang/AST/DependentDiagnostic.h b/clang/include/clang/AST/DependentDiagnostic.h
index cadf970620041..4196f6a5db731 100644
--- a/clang/include/clang/AST/DependentDiagnostic.h
+++ b/clang/include/clang/AST/DependentDiagnostic.h
@@ -149,9 +149,11 @@ class DeclContext::ddiag_iterator {
return tmp;
}
+#ifndef __swift__
bool operator==(ddiag_iterator Other) const {
return Ptr == Other.Ptr;
}
+#endif
bool operator!=(ddiag_iterator Other) const {
return Ptr != Other.Ptr;
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 573cc72db35c6..81a0c9e674938 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -31,6 +31,7 @@
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
@@ -263,6 +264,12 @@ class Expr : public ValueStmt {
bool isUnusedResultAWarning(const Expr *&WarnExpr, SourceLocation &Loc,
SourceRange &R1, SourceRange &R2,
ASTContext &Ctx) const;
+ /* TO_UPSTREAM(BoundsSafety) ON */
+ bool isUnusedResultAWarning(const Expr *&WarnExpr, SourceLocation &Loc,
+ SourceRange &R1, SourceRange &R2,
+ ASTContext &Ctx,
+ llvm::SmallPtrSetImpl &B) const;
+ /* TO_UPSTREAM(BoundsSafety) OFF */
/// Returns the WarnUnusedResultAttr that is declared on the callee
/// or its return type declaration, together with a NamedDecl that
@@ -783,6 +790,18 @@ class Expr : public ValueStmt {
/// strlen, false otherwise.
bool tryEvaluateStrLen(uint64_t &Result, ASTContext &Ctx) const;
+ /* TO_UPSTREAM(BoundsSafety) ON*/
+ /// If the current Expr is an array or a pointer to an array element, this
+ /// will try to statically determine the value of the last element of that
+ /// array.
+ bool tryEvaluateTerminatorElement(EvalResult &Result,
+ const ASTContext &Ctx) const;
+
+ bool EvaluateAsTerminatorValue(
+ llvm::APSInt &Result, const ASTContext &Ctx,
+ SideEffectsKind AllowSideEffects = SE_NoSideEffects) const;
+ /* TO_UPSTREAM(BoundsSafety) OFF*/
+
bool EvaluateCharRangeAsString(std::string &Result,
const Expr *SizeExpression,
const Expr *PtrExpression, ASTContext &Ctx,
@@ -842,6 +861,11 @@ class Expr : public ValueStmt {
ASTContext &Ctx,
NullPointerConstantValueDependence NPC) const;
+ /* TO_UPSTREAM(BoundsSafety) ON*/
+ NullPointerConstantKind isNullPointerConstantIgnoreCastsAndOVEs(
+ ASTContext &Ctx, NullPointerConstantValueDependence NPC) const;
+ /* TO_UPSTREAM(BoundsSafety) OFF*/
+
/// isOBJCGCCandidate - Return true if this expression may be used in a read/
/// write barrier.
bool isOBJCGCCandidate(ASTContext &Ctx) const;
@@ -924,6 +948,8 @@ class Expr : public ValueStmt {
/// * What IgnoreImpCasts() skips
/// * MaterializeTemporaryExpr
/// * SubstNonTypeTemplateParmExpr
+ // TO_UPSTREAM(BoundsSafety)
+ Expr *IgnoreParenImpCasts(llvm::SmallPtrSetImpl &BoundValues) LLVM_READONLY;
Expr *IgnoreParenImpCasts() LLVM_READONLY;
const Expr *IgnoreParenImpCasts() const {
return const_cast(this)->IgnoreParenImpCasts();
@@ -1180,6 +1206,13 @@ class OpaqueValueExpr : public Expr {
Expr *SourceExpr;
public:
+ /*TO_UPSTREAM(BoundsSafety) ON*/
+ static OpaqueValueExpr *Wrap(const ASTContext &Context, Expr *E);
+ static OpaqueValueExpr *EnsureWrapped(
+ const ASTContext &Context, Expr *E,
+ SmallVectorImpl &OVEs);
+ /*TO_UPSTREAM(BoundsSafety) OFF*/
+
OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK,
ExprObjectKind OK = OK_Ordinary, Expr *SourceExpr = nullptr)
: Expr(OpaqueValueExprClass, T, VK, OK), SourceExpr(SourceExpr) {
@@ -3951,6 +3984,832 @@ class CStyleCastExpr final
friend class CastExpr;
};
+/* TO_UPSTREAM(BoundsSafety) ON */
+// Attaches one or more assumptions to an expression. The assumptions are each
+// codegen'd like they were the parameter of `__builtin_assume`.
+class AssumptionExpr final
+ : public Expr,
+ private llvm::TrailingObjects {
+ friend TrailingObjects;
+ friend class ASTStmtWriter;
+
+ Expr **getTrailingExprs() {
+ return const_cast(getTrailingObjects());
+ }
+
+ Expr *const *getTrailingExprs() const {
+ return getTrailingObjects();
+ }
+
+ AssumptionExpr(EmptyShell Empty, unsigned NumExprs)
+ : Expr(AssumptionExprClass, Empty) {
+ AssumptionExprBits.NumExprs = NumExprs;
+ }
+
+ AssumptionExpr(Expr *ResultExpr, llvm::ArrayRef Assumptions);
+
+public:
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == AssumptionExprClass;
+ }
+
+ static AssumptionExpr *Create(const ASTContext &Ctx, Expr *Result,
+ llvm::ArrayRef Assumptions);
+
+ static AssumptionExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumExprs);
+
+ Expr *getWrappedExpr() { return getTrailingExprs()[0]; }
+ const Expr *getWrappedExpr() const { return getTrailingExprs()[0]; }
+
+ void setWrappedExpr(Expr *E) {
+ if (E) {
+ getTrailingExprs()[0] = E;
+ setType(E->getType());
+ setValueKind(E->getValueKind());
+ setObjectKind(E->getObjectKind());
+ } else {
+ setType(QualType());
+ }
+ }
+
+ unsigned getNumSubExprs() const { return AssumptionExprBits.NumExprs; }
+ Expr *getSubExpr(unsigned I) { return getTrailingExprs()[I]; }
+ const Expr *getSubExpr(unsigned I) const { return getTrailingExprs()[I]; }
+ void setSubExpr(unsigned I, Expr *E) {
+ if (I == 0)
+ setWrappedExpr(E);
+ else
+ getTrailingExprs()[I] = E;
+ }
+
+ unsigned getNumAssumptions() const { return getNumSubExprs() - 1; }
+ Expr *getAssumption(unsigned I) { return getSubExpr(I + 1); }
+ const Expr *getAssumption(unsigned I) const { return getSubExpr(I + 1); }
+ void setAssumption(unsigned I, Expr *E) { setSubExpr(I + 1, E); }
+
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getWrappedExpr()->getBeginLoc();
+ }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getWrappedExpr()->getEndLoc();
+ }
+
+ typedef Expr * const * assumption_iterator;
+ typedef const Expr * const * const_assumption_iterator;
+
+ assumption_iterator assumptions_begin() {
+ return reinterpret_cast (getTrailingExprs()) + 1;
+ }
+ const_assumption_iterator assumptions_begin() const {
+ return reinterpret_cast (getTrailingExprs()) + 1;
+ }
+ assumption_iterator assumptions_end() {
+ return assumptions_begin() + getNumAssumptions();
+ }
+ const_assumption_iterator assumptions_end() const {
+ return assumptions_begin() + getNumAssumptions();
+ }
+
+ llvm::iterator_range assumptions() {
+ return llvm::make_range(assumptions_begin(), assumptions_end());
+ }
+ llvm::iterator_range assumptions() const {
+ return llvm::make_range(assumptions_begin(), assumptions_end());
+ }
+
+ child_range children() {
+ Stmt **begin = reinterpret_cast(getTrailingExprs());
+ return child_range(begin, begin + getNumSubExprs());
+ }
+
+ const_child_range children() const {
+ Stmt *const *begin = reinterpret_cast(getTrailingExprs());
+ return const_child_range(begin, begin + getNumSubExprs());
+ }
+};
+
+// Implicitly promote a pointer with external bounds to a wide pointer. Although
+// this expression doesn't belong to the CastExpr family, it should usually be
+// treated as such.
+class BoundsSafetyPointerPromotionExpr final
+ : public Expr,
+ private llvm::TrailingObjects {
+ friend TrailingObjects;
+ friend class ASTStmtWriter;
+
+ BoundsSafetyPointerPromotionExpr(EmptyShell Empty)
+ : Expr(BoundsSafetyPointerPromotionExprClass, Empty) {
+ setPointer(nullptr);
+ setNullCheck(false);
+ }
+
+ BoundsSafetyPointerPromotionExpr(QualType QT, Expr *Ptr, Expr *UpperBound,
+ Expr *LowerBound, bool NullCheck = false)
+ : Expr(BoundsSafetyPointerPromotionExprClass, QT, VK_PRValue, OK_Ordinary) {
+ setPointer(Ptr);
+ setNullCheck(NullCheck);
+ if (Stmt **lowerPtr = getLowerBoundPtr())
+ *lowerPtr = LowerBound;
+ if (Stmt **upperPtr = getUpperBoundPtr())
+ *upperPtr = UpperBound;
+ setDependence(computeDependence(this));
+ }
+
+ BoundsSafetyPointerPromotionExpr *unconst() const {
+ return const_cast(this);
+ }
+
+ Stmt **getPointerPtr();
+ Stmt **getLowerBoundPtr();
+ Stmt **getUpperBoundPtr();
+
+public:
+ static BoundsSafetyPointerPromotionExpr *
+ Create(const ASTContext &Context, QualType QT, Expr *Ptr, Expr *UpperBound,
+ Expr *LowerBound = nullptr, bool NullCheck = false);
+
+ static BoundsSafetyPointerPromotionExpr *CreateEmpty(const ASTContext &Context,
+ unsigned SubExprCount);
+
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getPointer()->getBeginLoc();
+ }
+
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getPointer()->getEndLoc();
+ }
+
+ Expr *getSubExprAsWritten();
+ Expr *getPointer() { return cast_or_null(*getPointerPtr()); }
+ Expr *getLowerBound() { return cast_or_null(*getLowerBoundPtr()); }
+ Expr *getUpperBound() { return cast_or_null(*getUpperBoundPtr()); }
+ const Expr *getSubExpr() const { return getPointer(); }
+ const Expr *getPointer() const { return unconst()->getPointer(); }
+ const Expr *getLowerBound() const { return unconst()->getLowerBound(); }
+ const Expr *getUpperBound() const { return unconst()->getUpperBound(); }
+ bool getNullCheck() const {
+ return BoundsSafetyPointerPromotionExprBits.NullCheck;
+ }
+
+ Expr *getSubExpr() { return getPointer(); }
+ const Expr *getSubExprAsWritten() const {
+ return unconst()->getSubExprAsWritten();
+ }
+
+ void setPointer(Expr *newValue) { *getPointerPtr() = newValue; }
+ void setLowerBound(Expr *newValue) { *getLowerBoundPtr() = newValue; }
+ void setUpperBound(Expr *newValue) { *getUpperBoundPtr() = newValue; }
+ void setNullCheck(bool NullCheck) {
+ BoundsSafetyPointerPromotionExprBits.NullCheck = NullCheck;
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BoundsSafetyPointerPromotionExprClass;
+ }
+
+ unsigned getNumChildren() const {
+ return unconst()->getLowerBoundPtr() ? 3 : 2;
+ }
+
+ child_range children() {
+ return child_range(getPointerPtr(), getPointerPtr() + getNumChildren());
+ }
+
+ const_child_range children() const {
+ auto Range = unconst()->children();
+ return const_child_range(Range.begin(), Range.end());
+ }
+};
+
+/// __unsafe_forge_bidi_indexable(addr, size)
+/// __unsafe_forge_single(addr)
+/// __unsafe_forge_terminated_by(addr, terminator)
+class ForgePtrExpr final : public Expr {
+ enum { ADDR, SIZE, TERMINATOR, NUM_SUBEXPRS };
+
+ Stmt *SubExprs[NUM_SUBEXPRS];
+
+ SourceLocation KWLoc;
+ SourceLocation RParenLoc;
+
+public:
+ ForgePtrExpr(QualType T, ExprValueKind VK, Expr *AddrExpr, Expr *SizeExpr,
+ Expr *TermExpr, SourceLocation KWLoc, SourceLocation RParenLoc)
+ : Expr(ForgePtrExprClass, T, VK, OK_Ordinary), KWLoc(KWLoc),
+ RParenLoc(RParenLoc) {
+ SubExprs[ADDR] = AddrExpr;
+ SubExprs[SIZE] = SizeExpr;
+ SubExprs[TERMINATOR] = TermExpr;
+ setDependence(computeDependence(this));
+ }
+
+ explicit ForgePtrExpr(EmptyShell Empty)
+ : Expr(ForgePtrExprClass, Empty) {
+ SubExprs[ADDR] = nullptr;
+ SubExprs[SIZE] = nullptr;
+ SubExprs[TERMINATOR] = nullptr;
+ }
+
+ bool ForgesBidiIndexablePointer() const {
+ return !ForgesSinglePointer() && !ForgesTerminatedByPointer();
+ }
+ bool ForgesSinglePointer() const {
+ auto BaseFA = getType()->getAs()->getPointerAttributes();
+ return !BaseFA.hasUpperBound() && !ForgesTerminatedByPointer();
+ }
+ bool ForgesTerminatedByPointer() const {
+ return getType()->isValueTerminatedType();
+ }
+
+ Expr *getAddr() const { return cast(SubExprs[ADDR]); }
+ void setAddr(Expr *E) { SubExprs[ADDR] = E; }
+ Expr *getSize() const { return cast_or_null(SubExprs[SIZE]); }
+ void setSize(Expr *E) { SubExprs[SIZE] = E; }
+ Expr *getTerminator() const {
+ return cast_or_null(SubExprs[TERMINATOR]);
+ }
+ void setTerminator(Expr *E) { SubExprs[TERMINATOR] = E; }
+
+ SourceLocation getBeginLoc() const LLVM_READONLY { return KWLoc; }
+ void setBeginLoc(SourceLocation Loc) { KWLoc = Loc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
+ void setEndLoc(SourceLocation Loc) { RParenLoc = Loc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ForgePtrExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0] + NUM_SUBEXPRS);
+ }
+ const_child_range children() const {
+ return const_child_range(&SubExprs[0], &SubExprs[0] + NUM_SUBEXPRS);
+ }
+};
+
+/// GetBoundExpr - get the lower or upper bound of a pointer expression.
+/// This would be a builtin if it wasn't easier to create an entirely new
+/// expression subclass than to instantiate a call to a builtin from Sema.
+/// Most GetBoundExpr are synthetic, and their source locations default to
+class GetBoundExpr final : public Expr {
+public:
+ enum BoundKind { BK_Lower, BK_Upper };
+
+private:
+ Stmt *SubExpr;
+ BoundKind Kind;
+ SourceLocation BuiltinLoc, RParenLoc;
+
+public:
+ GetBoundExpr(SourceLocation BuiltinLoc, SourceLocation RParenLoc,
+ Expr *SubExpr, BoundKind Kind, QualType ResultType)
+ : Expr(GetBoundExprClass, ResultType, VK_PRValue, OK_Ordinary),
+ SubExpr(SubExpr), Kind(Kind), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc)
+ {
+ setDependence(computeDependence(this));
+ }
+
+ GetBoundExpr(Expr *SubExpr, BoundKind Kind, QualType ResultType)
+ : GetBoundExpr(SourceLocation(), SourceLocation(), SubExpr, Kind,
+ ResultType)
+ { }
+
+ explicit GetBoundExpr(EmptyShell Empty)
+ : Expr(GetBoundExprClass, Empty), SubExpr(nullptr), Kind(BK_Lower) {
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == GetBoundExprClass;
+ }
+
+ SourceLocation getBuiltinLoc() const LLVM_READONLY { return BuiltinLoc; }
+ void setBuiltinLoc(SourceLocation Loc) { BuiltinLoc = Loc; }
+
+ SourceLocation getRParenLoc() const LLVM_READONLY { return RParenLoc; }
+ void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
+
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return BuiltinLoc.isInvalid() ? getSubExpr()->getBeginLoc() : BuiltinLoc;
+ }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return RParenLoc.isInvalid() ? getSubExpr()->getEndLoc() : RParenLoc;
+ }
+
+ child_range children() {
+ return child_range(&SubExpr, &SubExpr + 1);
+ }
+
+ const_child_range children() const {
+ return const_child_range(&SubExpr, &SubExpr + 1);
+ }
+
+ Expr *getSubExpr() { return cast(SubExpr); }
+ const Expr *getSubExpr() const { return cast(SubExpr); }
+ void setSubExpr(Expr *NewValue) { SubExpr = NewValue; }
+
+ BoundKind getBoundKind() const { return Kind; }
+ void setBoundKind(BoundKind K) { Kind = K; }
+};
+
+enum class BoundsCheckKind : unsigned {
+ FlexibleArrayCountAssign,
+ FlexibleArrayCountCast,
+ FlexibleArrayCountDeref
+};
+
+/// PredefinedBoundsCheckExpr - AST representation of bounds checks that
+/// BoundsSafety added. This is a wrapper expression to wrap the expression
+/// (GuardedExpr) that will be executed if the bounds check succeeds. The
+/// subexpressions except the first one (GuardedExpr) are used for bounds check
+/// whose semantics is determined by the kind of bounds check (BoundsCheckKind).
+/// Most subexpressions are likely to be OpaqueValueExpr to avoid re-evaluating
+/// expressions. As bounds checks are necessarily implicit, the expression uses
+/// the source location of the wrapped expression.
+class PredefinedBoundsCheckExpr final
+ : public Expr,
+ public llvm::TrailingObjects {
+ static constexpr unsigned CheckArgsOffset = 1;
+
+ PredefinedBoundsCheckExpr(Expr *GuardedExpr, BoundsCheckKind Kind,
+ ArrayRef CheckArgs);
+ PredefinedBoundsCheckExpr(EmptyShell Empty, unsigned NumChildren)
+ : Expr(PredefinedBoundsCheckExprClass, Empty) {
+ PredefinedBoundsCheckExprBits.NumChildren = NumChildren;
+ }
+
+ Stmt **getTrailingStmts() {
+ return const_cast(getTrailingObjects());
+ }
+
+ Stmt *const *getTrailingStmts() const { return getTrailingObjects(); }
+
+ Expr **getSubExprs() { return reinterpret_cast(getTrailingStmts()); }
+
+ Expr *const *getSubExprs() const {
+ return reinterpret_cast(getTrailingStmts());
+ }
+
+public:
+ static PredefinedBoundsCheckExpr *Create(ASTContext &Ctx, Expr *GuardedExpr,
+ BoundsCheckKind Kind,
+ ArrayRef CheckArgs);
+
+ static PredefinedBoundsCheckExpr *CreateEmpty(ASTContext &Ctx,
+ unsigned NumChildren);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == PredefinedBoundsCheckExprClass;
+ }
+
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getGuardedExpr()->getBeginLoc();
+ }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getGuardedExpr()->getEndLoc();
+ }
+
+ unsigned getNumSubExprs() const {
+ return PredefinedBoundsCheckExprBits.NumChildren;
+ }
+
+ unsigned getNumCheckArgs() const {
+ assert(getNumSubExprs() >= CheckArgsOffset);
+ return getNumSubExprs() - CheckArgsOffset;
+ }
+
+ static constexpr unsigned getCheckArgsOffset() { return CheckArgsOffset; }
+
+ typedef Expr *const *checkargs_iterator;
+ typedef const Expr *const *const_checkargs_iterator;
+
+ checkargs_iterator checkargs_begin() {
+ return reinterpret_cast(getSubExprs() +
+ getCheckArgsOffset());
+ }
+ const_checkargs_iterator checkargs_begin() const {
+ return reinterpret_cast(getSubExprs() +
+ getCheckArgsOffset());
+ }
+ checkargs_iterator checkargs_end() {
+ return checkargs_begin() + getNumCheckArgs();
+ }
+ const_checkargs_iterator checkargs_end() const {
+ return checkargs_begin() + getNumCheckArgs();
+ }
+
+ llvm::iterator_range checkargs() {
+ return llvm::make_range(checkargs_begin(), checkargs_end());
+ }
+ llvm::iterator_range checkargs() const {
+ return llvm::make_range(checkargs_begin(), checkargs_end());
+ }
+
+ child_range children() {
+ Stmt **begin = getTrailingStmts();
+ return child_range(begin, begin + getNumSubExprs());
+ }
+
+ const_child_range children() const {
+ Stmt *const *begin = getTrailingStmts();
+ return const_child_range(begin, begin + getNumSubExprs());
+ }
+
+ BoundsCheckKind getKind() const {
+ return static_cast(PredefinedBoundsCheckExprBits.Kind);
+ }
+
+ StringRef getKindName() const;
+
+ Expr *getGuardedExpr() { return getSubExpr(0); }
+ const Expr *getGuardedExpr() const { return getSubExpr(0); }
+ void setGuardedExpr(Expr *NewValue) { setSubExpr(0, NewValue); }
+
+ Expr *getSubExpr(unsigned i) {
+ assert(i < getNumSubExprs());
+ return cast(getTrailingStmts()[i]);
+ }
+
+ const Expr *getSubExpr(unsigned i) const {
+ assert(i < getNumSubExprs());
+ return cast(getTrailingStmts()[i]);
+ }
+
+ // This returns the pointer to the base struct with flexible array member.
+ const Expr *getFamBasePtr() const {
+ switch (getKind()) {
+ case BoundsCheckKind::FlexibleArrayCountAssign:
+ case BoundsCheckKind::FlexibleArrayCountCast:
+ case BoundsCheckKind::FlexibleArrayCountDeref:
+ return getSubExpr(CheckArgsOffset);
+ }
+ llvm_unreachable("Unsupported BoundsCheckKind");
+ }
+
+ const Expr *getFamPtr() const {
+ switch (getKind()) {
+ case BoundsCheckKind::FlexibleArrayCountAssign:
+ case BoundsCheckKind::FlexibleArrayCountCast:
+ case BoundsCheckKind::FlexibleArrayCountDeref:
+ return getSubExpr(CheckArgsOffset + 1);
+ }
+ llvm_unreachable("Unsupported BoundsCheckKind");
+ }
+
+ const Expr *getFamCount() const {
+ switch (getKind()) {
+ case BoundsCheckKind::FlexibleArrayCountAssign:
+ case BoundsCheckKind::FlexibleArrayCountCast:
+ case BoundsCheckKind::FlexibleArrayCountDeref:
+ return getSubExpr(CheckArgsOffset + 2);
+ }
+ llvm_unreachable("Unsupported BoundsCheckKind");
+ }
+
+ void setSubExpr(unsigned i, Expr *E) {
+ assert(i < getNumSubExprs());
+ getTrailingStmts()[i] = E;
+ }
+};
+
+/// BoundsCheckExpr - AST representation of a bounds check that BoundsSafety added.
+/// This wraps the expression that will be evaluated if the bounds check
+/// succeeds or evaluated before the bounds checks if PostGuard is true. The object
+/// also holds all the bounds to check. Many operands are
+/// likely to be OpaqueValueExpr to avoid re-evaluating expressions. As bounds
+/// checks are necessarily implicit, they never have a source location.
+class BoundsCheckExpr final :
+ public Expr, public llvm::TrailingObjects {
+ BoundsCheckExpr(Expr *GuardedExpr, Expr *Cond,
+ ArrayRef CommonExprs);
+ BoundsCheckExpr(EmptyShell Empty, unsigned NumChildren)
+ : Expr(BoundsCheckExprClass, Empty) {
+ BoundsCheckExprBits.NumChildren = NumChildren;
+ }
+
+ Stmt **getTrailingStmts() {
+ return const_cast(getTrailingObjects());
+ }
+
+ Stmt *const *getTrailingStmts() const {
+ return getTrailingObjects();
+ }
+
+ Expr **getSubExprs() {
+ return reinterpret_cast(getTrailingStmts());
+ }
+
+ Expr *const *getSubExprs() const {
+ return reinterpret_cast(getTrailingStmts());
+ }
+
+public:
+ static BoundsCheckExpr *Create(ASTContext &Ctx, Expr *GuardedExpr,
+ Expr *Cond, ArrayRef CommonExprs);
+
+ static BoundsCheckExpr *CreateEmpty(ASTContext &Ctx, unsigned NumChildren);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BoundsCheckExprClass;
+ }
+
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getGuardedExpr()->getBeginLoc();
+ }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getGuardedExpr()->getEndLoc();
+ }
+
+ unsigned getNumSubExprs() const { return BoundsCheckExprBits.NumChildren; }
+ unsigned getNumCommonExprs() const {
+ assert(getNumSubExprs() >= 2);
+ return getNumSubExprs() - 2;
+ }
+
+ typedef OpaqueValueExpr * const * opaquevalues_iterator;
+ typedef const OpaqueValueExpr * const * const_opaquevalues_iterator;
+
+ opaquevalues_iterator opaquevalues_begin() {
+ return reinterpret_cast (getSubExprs() + 2);
+ }
+ const_opaquevalues_iterator opaquevalues_begin() const {
+ return reinterpret_cast (getSubExprs() + 2);
+ }
+ opaquevalues_iterator opaquevalues_end() {
+ return opaquevalues_begin() + getNumCommonExprs();
+ }
+ const_opaquevalues_iterator opaquevalues_end() const {
+ return opaquevalues_begin() + getNumCommonExprs();
+ }
+
+ llvm::iterator_range opaquevalues() {
+ return llvm::make_range(opaquevalues_begin(), opaquevalues_end());
+ }
+ llvm::iterator_range opaquevalues() const {
+ return llvm::make_range(opaquevalues_begin(), opaquevalues_end());
+ }
+
+ child_range children() {
+ Stmt **begin = getTrailingStmts();
+ return child_range(begin, begin + getNumSubExprs());
+ }
+
+ const_child_range children() const {
+ Stmt *const *begin = getTrailingStmts();
+ return const_child_range(begin, begin + getNumSubExprs());
+ }
+
+ Expr *getGuardedExpr() { return getSubExpr(0); }
+ const Expr *getGuardedExpr() const { return getSubExpr(0); }
+ void setGuardedExpr(Expr *NewValue) { setSubExpr(0, NewValue); }
+
+ Expr *getCond() { return getSubExpr(1); }
+ const Expr *getCond() const { return getSubExpr(1); }
+ void setCond(Expr *Cond) { setSubExpr(1, Cond); }
+
+ Expr *getSubExpr(unsigned i) {
+ assert(i < getNumSubExprs());
+ return cast(getTrailingStmts()[i]);
+ }
+
+ const Expr *getSubExpr(unsigned i) const {
+ assert(i < getNumSubExprs());
+ return cast(getTrailingStmts()[i]);
+ }
+
+ void setSubExpr(unsigned i, Expr *E) {
+ assert(i < getNumSubExprs());
+ getTrailingStmts()[i] = E;
+ }
+};
+
+class MaterializeSequenceExpr final :
+ public Expr, public llvm::TrailingObjects {
+
+ MaterializeSequenceExpr(Expr *WrappedExpr, ArrayRef Values, bool Unbind)
+ : Expr(MaterializeSequenceExprClass, WrappedExpr->getType(),
+ WrappedExpr->getValueKind(),
+ WrappedExpr->getObjectKind()) {
+ MaterializeSequenceExprBits.NumExprs = Values.size() + 1;
+ MaterializeSequenceExprBits.Unbind = Unbind;
+ getSubExprs()[0] = WrappedExpr;
+ std::copy(Values.begin(), Values.end(), getSubExprs() + 1);
+ setDependence(computeDependence(this));
+ }
+
+ MaterializeSequenceExpr(EmptyShell Empty, unsigned NumExprs)
+ : Expr(MaterializeSequenceExprClass, Empty) {
+ MaterializeSequenceExprBits.NumExprs = NumExprs;
+ }
+
+ Expr **getSubExprs() {
+ return getTrailingObjects();
+ }
+
+ Expr *const *getSubExprs() const {
+ return getTrailingObjects();
+ }
+
+ friend class ASTStmtReader;
+public:
+ static MaterializeSequenceExpr *Create(const ASTContext &Ctx, Expr *WrappedExpr,
+ ArrayRef Values,
+ bool Unbind = false);
+
+ static MaterializeSequenceExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumExprs);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == MaterializeSequenceExprClass;
+ }
+
+ unsigned getNumSubExprs() const {
+ return MaterializeSequenceExprBits.NumExprs;
+ }
+
+ bool isBinding() const {
+ return !isUnbinding();
+ }
+
+ bool isUnbinding() const {
+ return MaterializeSequenceExprBits.Unbind;
+ }
+
+ unsigned getNumOpaqueValueExprs() const {
+ assert(getNumSubExprs() > 1);
+ return getNumSubExprs() - 1;
+ }
+
+ Expr *getWrappedExpr() const {
+ assert(getNumSubExprs() > 0);
+ return getSubExprs()[0];
+ }
+
+ typedef OpaqueValueExpr * const * opaquevalues_iterator;
+ typedef const OpaqueValueExpr * const * const_opaquevalues_iterator;
+
+ opaquevalues_iterator opaquevalues_begin() {
+ return reinterpret_cast (getSubExprs() + 1);
+ }
+ const_opaquevalues_iterator opaquevalues_begin() const {
+ return reinterpret_cast (getSubExprs() + 1);
+ }
+ opaquevalues_iterator opaquevalues_end() {
+ return opaquevalues_begin() + getNumOpaqueValueExprs();
+ }
+ const_opaquevalues_iterator opaquevalues_end() const {
+ return opaquevalues_begin() + getNumOpaqueValueExprs();
+ }
+
+ llvm::iterator_range opaquevalues() {
+ return llvm::make_range(opaquevalues_begin(), opaquevalues_end());
+ }
+ llvm::iterator_range opaquevalues() const {
+ return llvm::make_range(opaquevalues_begin(), opaquevalues_end());
+ }
+
+ SourceLocation getBeginLoc() const {
+ return getWrappedExpr()->getBeginLoc();
+ }
+
+ SourceLocation getEndLoc() const {
+ return getWrappedExpr()->getEndLoc();
+ }
+
+ child_range children() {
+ Stmt **begin = reinterpret_cast(getSubExprs());
+ return child_range(begin,
+ begin + getNumSubExprs());
+ }
+
+ const_child_range children() const {
+ Stmt *const *begin = reinterpret_cast(getSubExprs());
+ return const_child_range(begin,
+ begin + getNumSubExprs());
+ }
+};
+
+/// TerminatedByToIndexableExpr - The AST representation of
+/// __builtin_terminated_by_to_indexable() and
+/// __builtin_unsafe_terminated_by_to_indexable().
+class TerminatedByToIndexableExpr final : public Expr {
+private:
+ enum { POINTER, TERMINATOR, END_EXPR };
+ Stmt *SubExprs[END_EXPR];
+ bool IncludeTerminator;
+ SourceLocation BuiltinLoc, RParenLoc;
+
+public:
+ TerminatedByToIndexableExpr(SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc, Expr *Pointer,
+ Expr *Terminator, bool IncludeTerminator,
+ QualType ResultType)
+ : Expr(TerminatedByToIndexableExprClass, ResultType, VK_PRValue,
+ OK_Ordinary),
+ SubExprs{Pointer, Terminator}, IncludeTerminator(IncludeTerminator),
+ BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {}
+
+ TerminatedByToIndexableExpr(Expr *Pointer, Expr *Terminator,
+ QualType ResultType)
+ : TerminatedByToIndexableExpr(SourceLocation(), SourceLocation(), Pointer,
+ Terminator, false, ResultType) {}
+
+ explicit TerminatedByToIndexableExpr(EmptyShell Empty)
+ : Expr(TerminatedByToIndexableExprClass, Empty), SubExprs{},
+ IncludeTerminator(false) {}
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == TerminatedByToIndexableExprClass;
+ }
+
+ SourceLocation getBuiltinLoc() const LLVM_READONLY { return BuiltinLoc; }
+ void setBuiltinLoc(SourceLocation Loc) { BuiltinLoc = Loc; }
+
+ SourceLocation getRParenLoc() const LLVM_READONLY { return RParenLoc; }
+ void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
+
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return BuiltinLoc.isInvalid() ? getPointer()->getBeginLoc() : BuiltinLoc;
+ }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return RParenLoc.isInvalid() ? getPointer()->getEndLoc() : RParenLoc;
+ }
+
+ child_range children() { return child_range(SubExprs, SubExprs + END_EXPR); }
+
+ const_child_range children() const {
+ return const_child_range(SubExprs, SubExprs + END_EXPR);
+ }
+
+ Expr *getPointer() const { return cast(SubExprs[POINTER]); }
+ void setPointer(Expr *E) { SubExprs[POINTER] = E; }
+ Expr *getTerminator() const { return cast(SubExprs[TERMINATOR]); }
+ void setTerminator(Expr *E) { SubExprs[TERMINATOR] = E; }
+
+ bool includesTerminator() const { return IncludeTerminator; }
+ void setIncludeTerminator(bool Include) { IncludeTerminator = Include; }
+};
+
+/// TerminatedByFromIndexableExpr - The AST representation of
+/// __builtin_unsafe_terminated_by_from_indexable().
+class TerminatedByFromIndexableExpr final : public Expr {
+private:
+ enum { POINTER, POINTER_TO_TERMINATOR, END_EXPR };
+ Stmt *SubExprs[END_EXPR];
+ SourceLocation BuiltinLoc, RParenLoc;
+
+public:
+ TerminatedByFromIndexableExpr(SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc, Expr *Pointer,
+ Expr *PointerToTerminator, QualType ResultType)
+ : Expr(TerminatedByFromIndexableExprClass, ResultType, VK_PRValue,
+ OK_Ordinary),
+ SubExprs{Pointer, PointerToTerminator}, BuiltinLoc(BuiltinLoc),
+ RParenLoc(RParenLoc) {}
+
+ TerminatedByFromIndexableExpr(Expr *Pointer, Expr *PointerToTerminator,
+ QualType ResultType)
+ : TerminatedByFromIndexableExpr(SourceLocation(), SourceLocation(),
+ Pointer, PointerToTerminator,
+ ResultType) {}
+
+ explicit TerminatedByFromIndexableExpr(EmptyShell Empty)
+ : Expr(TerminatedByFromIndexableExprClass, Empty), SubExprs{} {}
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == TerminatedByFromIndexableExprClass;
+ }
+
+ SourceLocation getBuiltinLoc() const LLVM_READONLY { return BuiltinLoc; }
+ void setBuiltinLoc(SourceLocation Loc) { BuiltinLoc = Loc; }
+
+ SourceLocation getRParenLoc() const LLVM_READONLY { return RParenLoc; }
+ void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
+
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return BuiltinLoc.isInvalid() ? getPointer()->getBeginLoc() : BuiltinLoc;
+ }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ if (RParenLoc.isValid())
+ return RParenLoc;
+ return getPointerToTerminator() ? getPointerToTerminator()->getEndLoc()
+ : SourceLocation();
+ }
+
+ child_range children() { return child_range(SubExprs, SubExprs + END_EXPR); }
+
+ const_child_range children() const {
+ return const_child_range(SubExprs, SubExprs + END_EXPR);
+ }
+
+ Expr *getPointer() const { return cast(SubExprs[POINTER]); }
+ void setPointer(Expr *E) { SubExprs[POINTER] = E; }
+ Expr *getPointerToTerminator() const {
+ return cast_or_null(SubExprs[POINTER_TO_TERMINATOR]);
+ }
+ void setPointerToTerminator(Expr *E) { SubExprs[POINTER_TO_TERMINATOR] = E; }
+};
+/* TO_UPSTREAM(BoundsSafety) OFF */
+
/// A builtin binary operation expression such as "x + y" or "x <= y".
///
/// This expression node kind describes a builtin binary operation,
@@ -5294,6 +6153,28 @@ class InitListExpr : public Expr {
return cast_or_null(InitExprs[Init]);
}
+ /* TO_UPSTREAM(BoundsSafety) ON*/
+ Expr *getInitForField(const ValueDecl *VD) {
+ assert(isSemanticForm());
+ if (auto FD = dyn_cast(VD)) {
+ unsigned FieldIdx = 0;
+ for (FieldDecl *Sibling : FD->getParent()->fields()) {
+ if (Sibling->isUnnamedBitField())
+ continue;
+ if (Sibling == FD)
+ break;
+ ++FieldIdx;
+ }
+ if (FieldIdx >= getNumInits())
+ return nullptr;
+ return getInit(FieldIdx);
+ }
+
+ auto IFD = cast(VD);
+ return getInitForField(IFD->getAnonField());
+ }
+ /* TO_UPSTREAM(BoundsSafety) OFF*/
+
void setInit(unsigned Init, Expr *expr) {
assert(Init < getNumInits() && "Initializer access out of range!");
InitExprs[Init] = expr;
diff --git a/clang/include/clang/AST/ExprObjC.h b/clang/include/clang/AST/ExprObjC.h
index b9232305f036a..f1b6bc2c6938d 100644
--- a/clang/include/clang/AST/ExprObjC.h
+++ b/clang/include/clang/AST/ExprObjC.h
@@ -1700,30 +1700,78 @@ class ObjCBridgedCastExpr final
/// be used in the condition of an \c if, but it is also usable as top level
/// expressions.
///
-class ObjCAvailabilityCheckExpr : public Expr {
+class ObjCAvailabilityCheckExpr final
+ : public Expr,
+ private llvm::TrailingObjects {
+public:
+ struct VersionAsWritten {
+ /// Platform version canonicalized for use with availability checks.
+ VersionTuple Version;
+ /// Platform version as written in the source.
+ VersionTuple SourceVersion;
+ };
+
+private:
friend class ASTStmtReader;
+ friend llvm::TrailingObjects;
- VersionTuple VersionToCheck;
+ VersionAsWritten VersionToCheck;
SourceLocation AtLoc, RParen;
+ void setHasDomainName(bool V) {
+ ObjCAvailabilityCheckExprBits.HasDomainName = V;
+ }
+
+ ObjCAvailabilityCheckExpr(SourceLocation AtLoc, SourceLocation RParen,
+ QualType Ty, StringRef DomainName)
+ : Expr(ObjCAvailabilityCheckExprClass, Ty, VK_PRValue, OK_Ordinary),
+ VersionToCheck(), AtLoc(AtLoc), RParen(RParen) {
+ setDependence(ExprDependence::None);
+ setHasDomainName(true);
+ strcpy(getTrailingObjects(), DomainName.data());
+ }
+
public:
- ObjCAvailabilityCheckExpr(VersionTuple VersionToCheck, SourceLocation AtLoc,
+ ObjCAvailabilityCheckExpr(VersionAsWritten VersionToCheck,
+ SourceLocation AtLoc,
SourceLocation RParen, QualType Ty)
: Expr(ObjCAvailabilityCheckExprClass, Ty, VK_PRValue, OK_Ordinary),
VersionToCheck(VersionToCheck), AtLoc(AtLoc), RParen(RParen) {
setDependence(ExprDependence::None);
+ setHasDomainName(false);
}
+ static ObjCAvailabilityCheckExpr *
+ CreateAvailabilityFeatureCheck(SourceLocation AtLoc, SourceLocation RParen,
+ QualType Ty, StringRef DomainName,
+ const ASTContext &C);
+
explicit ObjCAvailabilityCheckExpr(EmptyShell Shell)
- : Expr(ObjCAvailabilityCheckExprClass, Shell) {}
+ : Expr(ObjCAvailabilityCheckExprClass, Shell) {
+ setHasDomainName(false);
+ }
+
+ static ObjCAvailabilityCheckExpr *
+ CreateEmpty(const ASTContext &C, Stmt::EmptyShell Empty, size_t FeaturesLen);
SourceLocation getBeginLoc() const { return AtLoc; }
SourceLocation getEndLoc() const { return RParen; }
SourceRange getSourceRange() const { return {AtLoc, RParen}; }
/// This may be '*', in which case this should fold to true.
- bool hasVersion() const { return !VersionToCheck.empty(); }
- VersionTuple getVersion() const { return VersionToCheck; }
+ bool hasVersion() const { return !VersionToCheck.Version.empty(); }
+ VersionTuple getVersion() const { return VersionToCheck.Version; }
+ VersionTuple getVersionAsWritten() const {
+ return VersionToCheck.SourceVersion;
+ }
+
+ bool hasDomainName() const {
+ return ObjCAvailabilityCheckExprBits.HasDomainName;
+ }
+ StringRef getDomainName() const {
+ assert(hasDomainName());
+ return getTrailingObjects();
+ }
child_range children() {
return child_range(child_iterator(), child_iterator());
diff --git a/clang/include/clang/AST/ExternalASTSource.h b/clang/include/clang/AST/ExternalASTSource.h
index 8fc490b1d8471..adfc2c9e6fb55 100644
--- a/clang/include/clang/AST/ExternalASTSource.h
+++ b/clang/include/clang/AST/ExternalASTSource.h
@@ -143,6 +143,11 @@ class ExternalASTSource : public RefCountedBase {
/// Update an out-of-date identifier.
virtual void updateOutOfDateIdentifier(const IdentifierInfo &II) {}
+ // Retrieve the variable declaration that has the information for the domain.
+ virtual Decl *getAvailabilityDomainDecl(StringRef DomainName) {
+ return nullptr;
+ }
+
/// Find all declarations with the given name in the given context,
/// and add them to the context by calling SetExternalVisibleDeclsForName
/// or SetNoExternalVisibleDeclsForName.
diff --git a/clang/include/clang/AST/IgnoreExpr.h b/clang/include/clang/AST/IgnoreExpr.h
index 917bada61fa6f..e7a2c49fde863 100644
--- a/clang/include/clang/AST/IgnoreExpr.h
+++ b/clang/include/clang/AST/IgnoreExpr.h
@@ -45,6 +45,35 @@ const Expr *IgnoreExprNodes(const Expr *E, FnTys &&...Fns) {
return IgnoreExprNodes(const_cast(E), std::forward(Fns)...);
}
+/* TO_UPSTREAM(BoundsSafety) ON */
+inline Expr *IgnoreBoundsSafetyImplicitImpl(
+ Expr *E, llvm::SmallPtrSetImpl &BoundValues) {
+
+ if (auto *FPPE = dyn_cast(E))
+ return FPPE->getSubExpr();
+
+ if (auto *AE = dyn_cast(E))
+ return AE->getWrappedExpr();
+
+ if (auto *MSE = dyn_cast(E)) {
+ if (!MSE->isUnbinding())
+ BoundValues.insert(MSE->opaquevalues_begin(), MSE->opaquevalues_end());
+ return MSE->getWrappedExpr();
+ }
+
+ if (auto *BCE = dyn_cast(E)) {
+ BoundValues.insert(BCE->opaquevalues_begin(), BCE->opaquevalues_end());
+ return BCE->getGuardedExpr();
+ }
+
+ if (auto *Opaque = dyn_cast(E))
+ if (BoundValues.count(Opaque))
+ return Opaque->getSourceExpr();
+
+ return E;
+}
+/* TO_UPSTREAM(BoundsSafety) OFF */
+
inline Expr *IgnoreImplicitCastsSingleStep(Expr *E) {
if (auto *ICE = dyn_cast(E))
return ICE->getSubExpr();
diff --git a/clang/include/clang/AST/NestedNameSpecifierBase.h b/clang/include/clang/AST/NestedNameSpecifierBase.h
index 8f4bbe97f6e9a..8b4d44ca8c63e 100644
--- a/clang/include/clang/AST/NestedNameSpecifierBase.h
+++ b/clang/include/clang/AST/NestedNameSpecifierBase.h
@@ -256,6 +256,23 @@ class NestedNameSpecifier {
void dump(llvm::raw_ostream &OS) const;
void dump(llvm::raw_ostream &OS, const LangOptions &LO) const;
+ /// \brief Compute the qualification required to get from the current context
+ /// (\p CurContext) to the target context (\p TargetContext).
+ ///
+ /// \param Context the AST context in which the qualification will be used.
+ ///
+ /// \param CurContext the context where an entity is being named, which is
+ /// typically based on the current scope.
+ ///
+ /// \param TargetContext the context in which the named entity actually
+ /// resides.
+ ///
+ /// \returns a nested name specifier that refers into the target context, or
+ /// NULL if no qualification is needed.
+ static NestedNameSpecifier
+ getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
+ const DeclContext *TargetContext);
+
static constexpr auto NumLowBitsAvailable = FlagOffset;
};
diff --git a/clang/include/clang/AST/ObjCMethodReferenceInfo.h b/clang/include/clang/AST/ObjCMethodReferenceInfo.h
new file mode 100644
index 0000000000000..0a3046f2a6593
--- /dev/null
+++ b/clang/include/clang/AST/ObjCMethodReferenceInfo.h
@@ -0,0 +1,43 @@
+//===- ObjcMethodReferenceInfo.h - API for ObjC method tracing --*- 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 APIs for ObjC method tracing.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_OBJC_METHOD_REFERENCE_INFO_H
+#define LLVM_CLANG_OBJC_METHOD_REFERENCE_INFO_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/raw_ostream.h"
+#include