diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 25ac0596d78b5..a2dbf8ab256ae 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -35,6 +35,9 @@
/clang/lib/CIR @lanza @bcardosolopes
/clang/tools/cir-* @lanza @bcardosolopes
+# BEGIN SWIFT
+/lldb/**/*Swift* @adrian-prantl
+# END SWIFT
/lldb/ @JDevlieghere
# MLIR Interfaces.
diff --git a/.gitignore b/.gitignore
index a84268a7f6863..6662481fd5227 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..ba542cb9cd6d8
--- /dev/null
+++ b/apple-ci/amtool
@@ -0,0 +1,359 @@
+#!/usr/bin/env python3
+"""
+Tool to reproduce and resolve the issues reported by the automerger.
+"""
+
+import argparse
+import json
+import logging
+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='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='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}`.')
+
+
+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..736f5008def9f
--- /dev/null
+++ b/apple-ci/clang/am/build.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+set -eu
+
+SRC_DIR=$PWD/llvm-project
+BUILD_DIR=$PWD/build
+
+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=${WORKSPACE}/.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 03a3e8404e069..21cad46ee11b2 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 a263681b3c633..076738dd7c1aa 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 1e981825c7c15..367b60b0239a2 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -893,30 +893,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(
@@ -1679,6 +1702,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 f43734ec1ede3..244cae9e42ca7 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.h
+++ b/clang-tools-extra/clangd/ClangdLSPServer.h
@@ -142,6 +142,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 52844129834c3..d5a04a28ea4c9 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -640,6 +640,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 1e612e2ba618e..83ddb24263709 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 0eb196fbad46a..6b167778ee612 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -98,6 +98,7 @@ toCompletionItemKind(index::SymbolKind Kind,
using SK = index::SymbolKind;
switch (Kind) {
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 05c8041df7de7..2d01ae7aafa19 100644
--- a/clang-tools-extra/clangd/Protocol.cpp
+++ b/clang-tools-extra/clangd/Protocol.cpp
@@ -298,6 +298,7 @@ SymbolKind adjustKindToCapability(SymbolKind Kind,
SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind) {
switch (Kind) {
case index::SymbolKind::Unknown:
+ case index::SymbolKind::CommentTag:
return SymbolKind::Variable;
case index::SymbolKind::Module:
return SymbolKind::Module;
@@ -1243,6 +1244,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 c7ef1a13e6e39..8a104fae317fa 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;
@@ -1448,6 +1465,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 c1ab63fb22f61..c5ab63e78073b 100644
--- a/clang-tools-extra/clangd/Quality.cpp
+++ b/clang-tools-extra/clangd/Quality.cpp
@@ -146,6 +146,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 e561513fe687f..93cabfa7eb0d3 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 e464f1ad45c52..ce357362094f6 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)
@@ -1074,6 +1076,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 2cb0722f7f285..c73ca3aa68b7a 100644
--- a/clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ b/clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -1542,6 +1542,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());
@@ -1573,6 +1574,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");
@@ -2091,8 +2124,9 @@ TEST(CrossFileRenameTests, ObjC) {
}
@end
)cpp",
- }};
-
+ }
+ };
+
trace::TestTracer Tracer;
for (const auto &T : Cases) {
SCOPED_TRACE(T.FooH);
@@ -2468,6 +2502,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 d48622eba5378..fe92958780b30 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 cf3de4f742e84..7a48ad06f511a 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/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 41818d43ac687..1c587fbc2ff35 100644
--- a/clang/docs/PointerAuthentication.rst
+++ b/clang/docs/PointerAuthentication.rst
@@ -47,14 +47,13 @@ This document serves four purposes:
- It documents several language extensions that are useful on targets using
pointer authentication.
-- It will eventually present a theory of operation for the security mitigation,
- describing the basic requirements for correctness, various weaknesses in the
- mechanism, and ways in which programmers can strengthen its protections
- (including recommendations for language implementors).
+- It presents a theory of operation for the security mitigation, describing the
+ basic requirements for correctness, various weaknesses in the mechanism, and
+ ways in which programmers can strengthen its protections (including
+ recommendations for language implementors).
-- It will eventually document the language ABIs currently used for C, C++,
- Objective-C, and Swift on arm64e, although these are not yet stable on any
- target.
+- It documents the language ABIs currently used for C, C++, Objective-C, and
+ Swift on arm64e, although these are not yet stable on any target.
Basic Concepts
--------------
@@ -125,7 +124,7 @@ independently for I and D keys.)
interfaces or as primitives in a compiler IR because they expose raw
pointers. Raw pointers require special attention in the language
implementation to avoid the accidental creation of exploitable code
- sequences.
+ sequences; see the section on `Attackable code sequences`_.
The following details are all implementation-defined:
@@ -255,19 +254,133 @@ signing schema breaks down even more simply:
It is important that the signing schema be independently derived at all signing
and authentication sites. Preferably, the schema should be hard-coded
everywhere it is needed, but at the very least, it must not be derived by
-inspecting information stored along with the pointer.
+inspecting information stored along with the pointer. See the section on
+`Attacks on pointer authentication`_ for more information.
+
+
+
+
Language Features
-----------------
-There is currently one main pointer authentication language feature:
+There are three levels of the pointer authentication language feature:
+
+- The language implementation automatically signs and authenticates function
+ pointers (and certain data pointers) across a variety of standard situations,
+ including return addresses, function pointers, and C++ virtual functions. The
+ intent is for all pointers to code in program memory to be signed in some way
+ and for all branches to code in program text to authenticate those
+ signatures.
-- The language provides the ```` intrinsic interface for manually
- signing and authenticating pointers in code. These can be used in
+- The language also provides extensions to override the default rules used by
+ the language implementation. For example, the ``__ptrauth`` type qualifier
+ can be used to change how pointers are signed when they are stored in
+ a particular variable or field; this provides much stronger protection than
+ is guaranteed by the default rules for C function and data pointers.
+
+- Finally, the language provides the ```` intrinsic interface for
+ manually signing and authenticating pointers in code. These can be used in
circumstances where very specific behavior is required.
+Language implementation
+~~~~~~~~~~~~~~~~~~~~~~~
+
+For the most part, pointer authentication is an unobserved detail of the
+implementation of the programming language. Any element of the language
+implementation that would perform an indirect branch to a pointer is implicitly
+altered so that the pointer is signed when first constructed and authenticated
+when the branch is performed. This includes:
+
+- indirect-call features in the programming language, such as C function
+ pointers, C++ virtual functions, C++ member function pointers, the "blocks"
+ C extension, and so on;
+
+- returning from a function, no matter how it is called; and
-Language Extensions
+- indirect calls introduced by the implementation, such as branches through the
+ global offset table (GOT) used to implement direct calls to functions defined
+ outside of the current shared object.
+
+For more information about this, see the `Language ABI`_ section.
+
+However, some aspects of the implementation are observable by the programmer or
+otherwise require special notice.
+
+C data pointers
+^^^^^^^^^^^^^^^
+
+The current implementation in Clang does not sign pointers to ordinary data by
+default. For a partial explanation of the reasoning behind this, see the
+`Theory of Operation`_ section.
+
+A specific data pointer which is more security-sensitive than most can be
+signed using the `__ptrauth qualifier`_ or using the ````
+intrinsics.
+
+C function pointers
+^^^^^^^^^^^^^^^^^^^
+
+The C standard imposes restrictions on the representation and semantics of
+function pointer types which make it difficult to achieve satisfactory
+signature diversity in the default language rules. See `Attacks on pointer
+authentication`_ for more information about signature diversity. Programmers
+should strongly consider using the ``__ptrauth`` qualifier to improve the
+protections for important function pointers, such as the components of of
+a hand-rolled "v-table"; see the section on the `__ptrauth qualifier`_ for
+details.
+
+The value of a pointer to a C function includes a signature, even when the
+value is cast to a non-function-pointer type like ``void*`` or ``intptr_t``. On
+implementations that use high bits to store the signature, this means that
+relational comparisons and hashes will vary according to the exact signature
+value, which is likely to change between executions of a program. In some
+implementations, it may also vary based on the exact function pointer type.
+
+Null pointers
+^^^^^^^^^^^^^
+
+In principle, an implementation could derive the signed null pointer value
+simply by applying the standard signing algorithm to the raw null pointer
+value. However, for likely signing algorithms, this would mean that the signed
+null pointer value would no longer be statically known, which would have many
+negative consequences. For one, it would become substantially more expensive
+to emit null pointer values or to perform null-pointer checks. For another,
+the pervasive (even if technically unportable) assumption that null pointers
+are bitwise zero would be invalidated, making it substantially more difficult
+to adopt pointer authentication, as well as weakening common optimizations for
+zero-initialized memory such as the use of ``.bzz`` sections. Therefore it is
+beneficial to treat null pointers specially by giving them their usual
+representation. On AArch64, this requires additional code when working with
+possibly-null pointers, such as when copying a pointer field that has been
+signed with address diversity.
+
+Return addresses and frame pointers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The current implementation in Clang implicitly signs both return addresses and
+frame pointers. While these values are technically implementation details of
+a function, there are some important libraries and development tools which rely
+on manually walking the chain of stack frames. These tools must be updated to
+correctly account for pointer authentication, either by stripping signatures
+(if security is not important for the tool, e.g. if it is capturing a stack
+trace during a crash) or properly authenticating them. More information about
+how these values are signed is available in the `Language ABI`_ section.
+
+C++ virtual functions
+^^^^^^^^^^^^^^^^^^^^^
+
+The current implementation in Clang signs virtual function pointers with
+a discriminator derived from the full signature of the overridden method,
+including the method name and parameter types. It is possible to write C++
+code that relies on v-table layout remaining constant despite changes to
+a method signature; for example, a parameter might be a ``typedef`` that
+resolves to a different type based on a build setting. Such code violates
+C++'s One Definition Rule (ODR), but that violation is not normally detected;
+however, pointer authentication will detect it.
+
+
+Language extensions
~~~~~~~~~~~~~~~~~~~
Feature Testing
@@ -280,6 +393,16 @@ a number of different tests.
normal interface. This may be true even on targets where pointer
authentication is not enabled by default.
+- ``__has_feature(ptrauth_returns)`` is true if the target uses pointer
+ authentication to protect return addresses.
+
+- ``__has_feature(ptrauth_calls)`` is true if the target uses pointer
+ authentication to protect indirect branches. This implies
+ ``__has_feature(ptrauth_returns)`` and ``__has_feature(ptrauth_intrinsics)``.
+
+Clang provides several other tests only for historical purposes; for current
+purposes they are all equivalent to ``ptrauth_calls``.
+
__ptrauth Qualifier
^^^^^^^^^^^^^^^^^^^
@@ -292,6 +415,11 @@ type, either to a function or to an object. It currently cannot be an
Objective-C pointer type, a C++ reference type, or a block pointer type; these
restrictions may be lifted in the future.
+The current implementation in Clang is known to not provide adequate safety
+guarantees against the creation of `signing oracles`_ when assigning data
+pointers to ``__ptrauth``-qualified gl-values. See the section on `safe
+derivation`_ for more information.
+
The qualifier's operands are as follows:
- ``key`` - an expression evaluating to a key value from ````; must
@@ -326,6 +454,54 @@ a discriminator determined as follows:
is ``ptrauth_blend_discriminator(&x, discriminator)``; see
`ptrauth_blend_discriminator`_.
+Non-triviality from address diversity
++++++++++++++++++++++++++++++++++++++
+
+Address diversity must impose additional restrictions in order to allow the
+implementation to correctly copy values. In C++, a type qualified with address
+diversity is treated like a class type with non-trivial copy/move constructors
+and assignment operators, with the usual effect on containing classes and
+unions. C does not have a standard concept of non-triviality, and so we must
+describe the basic rules here, with the intention of imitating the emergent
+rules of C++:
+
+- A type may be **non-trivial to copy**.
+
+- A type may also be **illegal to copy**. Types that are illegal to copy are
+ always non-trivial to copy.
+
+- A type may also be **address-sensitive**.
+
+- A type qualified with a ``ptrauth`` qualifier that requires address diversity
+ is non-trivial to copy and address-sensitive.
+
+- An array type is illegal to copy, non-trivial to copy, or address-sensitive
+ if its element type is illegal to copy, non-trivial to copy, or
+ address-sensitive, respectively.
+
+- A struct type is illegal to copy, non-trivial to copy, or address-sensitive
+ if it has a field whose type is illegal to copy, non-trivial to copy, or
+ address-sensitive, respectively.
+
+- A union type is both illegal and non-trivial to copy if it has a field whose
+ type is non-trivial or illegal to copy.
+
+- A union type is address-sensitive if it has a field whose type is
+ address-sensitive.
+
+- A program is ill-formed if it uses a type that is illegal to copy as
+ a function parameter, argument, or return type.
+
+- A program is ill-formed if an expression requires a type to be copied that is
+ illegal to copy.
+
+- Otherwise, copying a type that is non-trivial to copy correctly copies its
+ subobjects.
+
+- Types that are address-sensitive must always be passed and returned
+ indirectly. Thus, changing the address-sensitivity of a type may be
+ ABI-breaking even if its size and alignment do not change.
+
````
~~~~~~~~~~~~~~~
@@ -432,7 +608,7 @@ Produce a signed pointer for the given raw pointer without applying any
authentication or extra treatment. This operation is not required to have the
same behavior on a null pointer that the language implementation would.
-This is a treacherous operation that can easily result in signing oracles.
+This is a treacherous operation that can easily result in `signing oracles`_.
Programs should use it seldom and carefully.
``ptrauth_auth_and_resign``
@@ -453,7 +629,29 @@ a null pointer that the language implementation would.
The code sequence produced for this operation must not be directly attackable.
However, if the discriminator values are not constant integers, their
computations may still be attackable. In the future, Clang should be enhanced
-to guaranteed non-attackability if these expressions are safely-derived.
+to guaranteed non-attackability if these expressions are
+:ref:`safely-derived`.
+
+``ptrauth_auth_function``
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: c
+
+ ptrauth_auth_function(pointer, key, discriminator)
+
+Authenticate that ``pointer`` is signed with ``key`` and ``discriminator`` and
+re-sign it to the standard schema for a function pointer of its type.
+
+``pointer`` must have function pointer type. The result will have the same
+type as ``pointer``. This operation is not required to have the same behavior
+on a null pointer that the language implementation would.
+
+This operation makes the same attackability guarantees as
+``ptrauth_auth_and_resign``.
+
+If this operation appears syntactically as the function operand of a call,
+Clang guarantees that the call will directly authenticate the function value
+using the given schema rather than re-signing to the standard schema.
``ptrauth_auth_data``
^^^^^^^^^^^^^^^^^^^^^
@@ -469,7 +667,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``
@@ -499,6 +697,466 @@ type. Implementations are not required to make all bits of the result equally
significant; in particular, some implementations are known to not leave
meaningful data in the low bits.
+Standard ``__ptrauth`` qualifiers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+```` additionally provides several macros which expand to
+``__ptrauth`` qualifiers for common ABI situations.
+
+For convenience, these macros expand to nothing when pointer authentication is
+disabled.
+
+These macros can be found in the header; some details of these macros may be
+unstable or implementation-specific.
+
+
+
+
+
+Theory of Operation
+-------------------
+
+The threat model of pointer authentication is as follows:
+
+- The attacker has the ability to read and write to a certain range of addresses, possibly the entire address space. However, they are constrained by the normal rules of the process: for example, they cannot write to memory that is mapped read-only, and if they access unmapped memory it will trigger a trap.
+
+- The attacker has no ability to add arbitrary executable code to the program. For example, the program does not include malicious code to begin with, and the attacker cannot alter existing instructions, load a malicious shared library, or remap writable pages as executable. If the attacker wants to get the process to perform a specific sequence of actions, they must somehow subvert the normal control flow of the process.
+
+In both of the above paragraphs, it is merely assumed that the attacker's *current* capabilities are restricted; that is, their current exploit does not directly give them the power to do these things. The attacker's immediate goal may well be to leverage their exploit to gain these capabilities, e.g. to load a malicious dynamic library into the process, even though the process does not directly contain code to do so.
+
+Note that any bug that fits the above threat model can be immediately exploited as a denial-of-service attack by simply performing an illegal access and crashing the program. Pointer authentication cannot protect against this. While denial-of-service attacks are unfortunate, they are also unquestionably the best possible result of a bug this severe. Therefore, pointer authentication enthusiastically embraces the idea of halting the program on a pointer authentication failure rather than continuing in a possibly-compromised state.
+
+Pointer authentication is a form of control-flow integrity (CFI) enforcement. The basic security hypothesis behind CFI enforcement is that many bugs can only be usefully exploited (other than as a denial-of-service) by leveraging them to subvert the control flow of the program. If this is true, then by inhibiting or limiting that subversion, it may be possible to largely mitigate the security consequences of those bugs by rendering them impractical (or, ideally, impossible) to exploit.
+
+Every indirect branch in a program has a purpose. Using human intelligence, a programmer can describe where a particular branch *should* go according to this purpose: a ``return`` in ``printf`` should return to the call site, a particular call in ``qsort`` should call the comparator that was passed in as an argument, and so on. But for CFI to enforce that every branch in a program goes where it *should* in this sense would require CFI to perfectly enforce every semantic rule of the program's abstract machine; that is, it would require making the programming environment perfectly sound. That is out of scope. Instead, the goal of CFI is merely to catch attempts to make a branch go somewhere that its obviously *shouldn't* for its purpose: for example, to stop a call from branching into the middle of a function rather than its beginning. As the information available to CFI gets better about the purpose of the branch, CFI can enforce tighter and tighter restrictions on where the branch is permitted to go. Still, ultimately CFI cannot make the program sound. This may help explain why pointer authentication makes some of the choices it does: for example, to sign and authenticate mostly code pointers rather than every pointer in the program. Preventing attackers from redirecting branches is both particularly important and particularly approachable as a goal. Detecting corruption more broadly is infeasible with these techniques, and the attempt would have far higher cost.
+
+Attacks on pointer authentication
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Pointer authentication works as follows. Every indirect branch in a program has a purpose. For every purpose, the implementation chooses a :ref:`signing schema`. At some place where a pointer is known to be correct for its purpose, it is signed according to the purpose's schema. At every place where the pointer is needed for its purpose, it is authenticated according to the purpose's schema. If that authentication fails, the program is halted.
+
+There are a variety of ways to attack this.
+
+Attacks of interest to programmers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+These attacks arise from weaknesses in the default protections offered by pointer authentication. They can be addressed by using attributes or intrinsics to opt in to stronger protection.
+
+Substitution attacks
+++++++++++++++++++++
+
+An attacker can simply overwrite a pointer intended for one purpose with a pointer intended for another purpose if both purposes use the same signing schema and that schema does not use address diversity.
+
+The most common source of this weakness is when code relies on using the default language rules for C function pointers. The current implementation uses the exact same signing schema for all C function pointers, even for functions of substantially different type. While efforts are ongoing to improve constant diversity for C function pointers of different type, there are necessary limits to this. The C standard requires function pointers to be copyable with ``memcpy``, which means that function pointers can never use address diversity. Furthermore, even if a function pointer can only be replaced with another function of the exact same type, that can still be useful to an attacker, as in the following example of a hand-rolled "v-table":
+
+.. code-block:: c
+
+ struct ObjectOperations {
+ void (*retain)(Object *);
+ void (*release)(Object *);
+ void (*deallocate)(Object *);
+ void (*logStatus)(Object *);
+ };
+
+This weakness can be mitigated by using a more specific signing schema for each purpose. For example, in this example, the ``__ptrauth`` qualifier can be used with a different constant discriminator for each field. Since there's no particular reason it's important for this v-table to be copyable with ``memcpy``, the functions can also be signed with address diversity:
+
+.. code-block:: c
+
+ #if __has_feature(ptrauth_calls)
+ #define objectOperation(discriminator) \
+ __ptrauth(ptrauth_key_function_pointer, 1, discriminator)
+ #else
+ #define objectOperation(discriminator)
+ #endif
+
+ struct ObjectOperations {
+ void (*objectOperation(0xf017) retain)(Object *);
+ void (*objectOperation(0x2639) release)(Object *);
+ void (*objectOperation(0x8bb0) deallocate)(Object *);
+ void (*objectOperation(0xc5d4) logStatus)(Object *);
+ };
+
+This weakness can also sometimes be mitigated by simply keeping the signed pointer in constant memory, but this is less effective than using better signing diversity.
+
+.. _Access path attacks:
+
+Access path attacks
++++++++++++++++++++
+
+If a signed pointer is often accessed indirectly (that is, by first loading the address of the object where the signed pointer is stored), an attacker can affect uses of it by overwriting the intermediate pointer in the access path.
+
+The most common scenario exhibiting this weakness is an object with a pointer to a "v-table" (a structure holding many function pointers). An attacker does not need to replace a signed function pointer in the v-table if they can instead simply replace the v-table pointer in the object with their own pointer --- perhaps to memory where they've constructed their own v-table, or to existing memory that coincidentally happens to contain a signed pointer at the right offset that's been signed with the right signing schema.
+
+This attack arises because data pointers are not signed by default. It works even if the signed pointer uses address diversity: address diversity merely means that each pointer is signed with its own storage address, which (by design) is invariant to changes in the accessing pointer.
+
+Using sufficiently diverse signing schemas within the v-table can provide reasonably strong mitigation against this weakness. Always use address diversity in v-tables to prevent attackers from assembling their own v-table. Avoid re-using constant discriminators to prevent attackers from replacing a v-table pointer with a pointer to totally unrelated memory that just happens to contain an similarly-signed pointer.
+
+Further mitigation can be attained by signing pointers to v-tables. Any signature at all should prevent attackers from forging v-table pointers; they will need to somehow harvest an existing signed pointer from elsewhere in memory. Using a meaningful constant discriminator will force this to be harvested from an object with similar structure (e.g. a different implementation of the same interface). Using address diversity will prevent such harvesting entirely. However, care must be taken when sourcing the v-table pointer originally; do not blindly sign a pointer that is not :ref:`safely derived`.
+
+.. _Signing oracles:
+
+Signing oracles
++++++++++++++++
+
+A signing oracle is a bit of code which can be exploited by an attacker to sign an arbitrary pointer in a way that can later be recovered. Such oracles can be used by attackers to forge signatures matching the oracle's signing schema, which is likely to cause a total compromise of pointer authentication's effectiveness.
+
+This attack only affects ordinary programmers if they are using certain treacherous patterns of code. Currently this includes:
+
+- all uses of the ``__ptrauth_sign_unauthenticated`` intrinsic and
+- assigning data pointers to ``__ptrauth``-qualified l-values.
+
+Care must be taken in these situations to ensure that the pointer being signed has been :ref:`safely derived` or is otherwise not possible to attack. (In some cases, this may be challenging without compiler support.)
+
+A diagnostic will be added in the future for implicitly dangerous patterns of code, such as assigning a non-safely-derived data pointer to a ``__ptrauth``-qualified l-value.
+
+.. _Authentication oracles:
+
+Authentication oracles
+++++++++++++++++++++++
+
+An authentication oracle is a bit of code which can be exploited by an attacker to leak whether a signed pointer is validly signed without halting the program if it isn't. Such oracles can be used to forge signatures matching the oracle's signing schema if the attacker can repeatedly invoke the oracle for different candidate signed pointers. This is likely to cause a total compromise of pointer authentication's effectiveness.
+
+There should be no way for an ordinary programmer to create an authentication oracle using the current set of operations. However, implementation flaws in the past have occasionally given rise to authentication oracles due to a failure to immediately trap on authentication failure.
+
+The likelihood of creating an authentication oracle is why there is currently no intrinsic which queries whether a signed pointer is validly signed.
+
+
+Attacks of interest to implementors
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+These attacks are not inherent to the model; they arise from mistakes in either implementing or using the `sign` and `auth` operations. Avoiding these mistakes requires careful work throughout the system.
+
+Failure to trap on authentication failure
++++++++++++++++++++++++++++++++++++++++++
+
+Any failure to halt the program on an authentication failure is likely to be exploitable by attackers to create an :ref:`authentication oracle`.
+
+There are several different ways to introduce this problem:
+
+- The implementation might try to halt the program in some way that can be intercepted.
+
+ For example, the ``auth`` instruction in ARMv8.3 does not directly trap; instead it corrupts its result so that it is always an invalid pointer. If the program subsequently attempts to use that pointer, that will be a bad memory access, and it will trap into the kernel. However, kernels do not usually immediately halt programs that trigger traps due to bad memory accesses; instead they notify the process to give it an opportunity to recover. If this happens with an ``auth`` failure, the attacker may be able to exploit the recovery path in a way that creates an oracle. Kernels should ensure that these sorts of traps are not recoverable.
+
+- A compiler might use an intermediate representation (IR) for ``sign`` and ``auth`` operations that cannot make adequate correctness guarantees.
+
+ For example, suppose that an IR uses ARMv8.3-like semantics for ``auth``: the operation merely corrupts its result on failure instead of promising the trap. A frontend might emit patterns of IR that always follow an ``auth`` with a memory access, thinking that this ensures correctness. But if the IR can be transformed to insert code between the ``auth`` and the access, or if the ``auth`` can be speculated, then this potentially creates an oracle. It is better for ``auth`` to semantically guarantee to trap, potentially requiring an explicit check in the generated code. An ARMv8.3-like target can avoid this explicit check in the common case by recognizing the pattern of an ``auth`` followed immediately by an access.
+
+Attackable code sequences
++++++++++++++++++++++++++
+
+If code that is part of a pointer authentication operation is interleaved with code that may itself be vulnerable to attacks, an attacker may be able to use this to create a :ref:`signing` or :ref:`authentication` oracle.
+
+For example, suppose that the compiler is generating a call to a function and passing two arguments: a signed constant pointer and a value derived from a call. In ARMv8.3, this code might look like so:
+
+.. code-block:: asm
+
+ adr x19, _callback. ; compute &_callback
+ paciza x19 ; sign it with a constant discriminator of 0
+ blr _argGenerator ; call _argGenerator() (returns in x0)
+ mov x1, x0 ; move call result to second arg register
+ mov x0, x19 ; move signed &_callback to first arg register
+ blr _function ; call _function
+
+This code is correct, as would be a sequencing that does *both* the ``adr`` and the ``paciza`` after the call to ``_argGenerator``. But a sequence that computes the address of ``_callback`` but leaves it as a raw pointer in a register during the call to ``_argGenerator`` would be vulnerable:
+
+.. code-block:: asm
+
+ adr x19, _callback. ; compute &_callback
+ blr _argGenerator ; call _argGenerator() (returns in x0)
+ mov x1, x0 ; move call result to second arg register
+ paciza x19 ; sign &_callback
+ mov x0, x19 ; move signed &_callback to first arg register
+ blr _function ; call _function
+
+If ``_argGenerator`` spills ``x19`` (a callee-save register), and if the attacker can perform a write during this call, then the attacker can overwrite the spill slot with an arbitrary pointer that will eventually be unconditionally signed after the function returns. This would be a signing oracle.
+
+The implementation can avoid this by obeying two basic rules:
+
+- The compiler's intermediate representations (IR) should not provide operations that expose intermediate raw pointers. This may require providing extra operations that perform useful combinations of operations.
+
+ For example, there should be an "atomic" auth-and-resign operation that should be used instead of emitting an ``auth`` operation whose result is fed into a ``sign``.
+
+ Similarly, if a pointer should be authenticated as part of doing a memory access or a call, then the access or call should be decorated with enough information to perform the authentication; there should not be a separate ``auth`` whose result is used as the pointer operand for the access or call. (In LLVM IR, we do this for calls, but not yet for loads or stores.)
+
+ "Operations" includes things like materializing a signed pointer to a known function or global variable. The compiler must be able to recognize and emit this as a unified operation, rather than potentially splitting it up as in the example above.
+
+- The compiler backend should not be too aggressive about scheduling instructions that are part of a pointer authentication operation. This may require custom code-generation of these operations in some cases.
+
+Register clobbering
++++++++++++++++++++
+
+As a refinement of the section on `Attackable code sequences`_, if the attacker has the ability to modify arbitrary *register* state at arbitrary points in the program, then special care must be taken.
+
+For example, ARMv8.3 might materialize a signed function pointer like so:
+
+.. code-block:: asm
+
+ adr x0, _callback. ; compute &_callback
+ paciza x0 ; sign it with a constant discriminator of 0
+
+If an attacker has the ability to overwrite ``x0`` between these two instructions, this code sequence is vulnerable to becoming a signing oracle.
+
+For the most part, this sort of attack is not possible: it is a basic element of the design of modern computation that register state is private and inviolable. However, in systems that support asynchronous interrupts, this property requires the cooperation of the interrupt-handling code. If that code saves register state to memory, and that memory can be overwritten by an attacker, then essentially the attack can overwrite arbitrary register state at an arbitrary point. This could be a concern if the threat model includes attacks on the kernel or if the program uses user-space preemptive multitasking.
+
+(Readers might object that an attacker cannot rely on asynchronous interrupts triggering at an exact instruction boundary. In fact, researchers have had some success in doing exactly that. Even ignoring that, though, we should aim to protect against lucky attackers just as much as good ones.)
+
+To protect against this, saved register state must be at least partially signed (using something like `ptrauth_sign_generic_data`_). This is required for correctness anyway because saved thread states include security-critical registers such as SP, FP, PC, and LR (where applicable). Ideally, this signature would cover all the registers, but since saving and restoring registers can be very performance-sensitive, that may not be acceptable. It is sufficient to set aside a small number of scratch registers that will be guaranteed to be preserved correctly; the compiler can then be careful to only store critical values like intermediate raw pointers in those registers.
+
+``setjmp`` and ``longjmp`` should sign and authenticate the core registers (SP, FP, PC, and LR), but they do not need to worry about intermediate values because ``setjmp`` can only be called synchronously, and the compiler should never schedule pointer-authentication operations interleaved with arbitrary calls.
+
+.. _Relative addresses:
+
+Attacks on relative addressing
+++++++++++++++++++++++++++++++
+
+Relative addressing is a technique used to compress and reduce the load-time cost of infrequently-used global data. The pointer authentication system is unlikely to support signing or authenticating a relative address, and in most cases it would defeat the point to do so: it would take additional storage space, and applying the signature would take extra work at load time.
+
+Relative addressing is not precluded by the use of pointer authentication, but it does take extra considerations to make it secure:
+
+- Relative addresses must only be stored in read-only memory. A writable relative address can be overwritten to point nearly anywhere, making it inherently insecure; this danger can only be compensated for with techniques for protecting arbitrary data like `ptrauth_sign_generic_data`_.
+
+- Relative addresses must only be accessed through signed pointers with adequate diversity. If an attacker can perform an `access path attack` to replace the pointer through which the relative address is accessed, they can easily cause the relative address to point wherever they want.
+
+Signature forging
++++++++++++++++++
+
+If an attacker can exactly reproduce the behavior of the signing algorithm, and they know all the correct inputs to it, then they can perfectly forge a signature on an arbitrary pointer.
+
+There are three components to avoiding this mistake:
+
+- The abstract signing algorithm should be good: it should not have glaring flaws which would allow attackers to predict its result with better than random accuracy without knowing all the inputs (like the key values).
+
+- The key values should be kept secret. If at all possible, they should never be stored in accessible memory, or perhaps only stored encrypted.
+
+- Contexts that are meant to be independently protected should use different key values. For example, the kernel should not use the same keys as user processes. Different user processes should also use different keys from each other as much as possible, although this may pose its own technical challenges.
+
+Remapping
++++++++++
+
+If an attacker can change the memory protections on certain pages of the program's memory, that can substantially weaken the protections afforded by pointer authentication.
+
+- If an attacker can inject their own executable code, they can also certainly inject code that can be used as a :ref:`signing oracle`. The same is true if they can write to the instruction stream.
+
+- If an attacker can remap read-only program sections to be writable, then any use of :ref:`relative addresses` in global data becomes insecure.
+
+- If an attacker can remap read-only program sections to be writable, then it is unsafe to use unsigned pointers in `global offset tables`_.
+
+Remapping memory in this way often requires the attacker to have already substantively subverted the control flow of the process. Nonetheless, if the operating system has a mechanism for mapping pages in a way that cannot be remapped, this should be used wherever possible.
+
+
+
+.. _Safe Derivation:
+
+Safe derivation
+~~~~~~~~~~~~~~~
+
+Whether a data pointer is stored, even briefly, as a raw pointer can affect the security-correctness of a program. (Function pointers are never implicitly stored as raw pointers; raw pointers to functions can only be produced with the ```` intrinsics.) Repeated re-signing can also impact performance. Clang makes a modest set of guarantees in this area:
+
+- An expression of pointer type is said to be **safely derived** if:
+
+ - it takes the address of a global variable or function, or
+
+ - it is a load from a gl-value of ``__ptrauth``-qualified type.
+
+- If a value that is safely derived is assigned to a ``__ptrauth``-qualified object, including by initialization, then the value will be directly signed as appropriate for the target qualifier and will not be stored as a raw pointer.
+
+- If the function expression of a call is a gl-value of ``__ptrauth``-qualified type, then the call will be authenticated directly according to the source qualifier and will not be resigned to the default rule for a function pointer of its type.
+
+These guarantees are known to be inadequate for data pointer security. In particular, Clang should be enhanced to make the following guarantees:
+
+- A pointer should additionally be considered safely derived if it is:
+
+ - the address of a gl-value that is safely derived,
+
+ - the result of pointer arithmetic on a pointer that is safely derived (with some restrictions on the integer operand),
+
+ - the result of a comma operator where the second operand is safely derived,
+
+ - the result of a conditional operator where the selected operand is safely derived, or
+
+ - the result of loading from a safely derived gl-value.
+
+- A gl-value should be considered safely derived if it is:
+
+ - a dereference of a safely derived pointer,
+
+ - a member access into a safely derived gl-value, or
+
+ - a reference to a variable.
+
+- An access to a safely derived gl-value should be guaranteed to not allow replacement of any of the safely-derived component values at any point in the access. "Access" should include loading a function pointer.
+
+- Assignments should include pointer-arithmetic operators like ``+=``.
+
+Making these guarantees will require further work, including significant new support in LLVM IR.
+
+Furthermore, Clang should implement a warning when assigning a data pointer that is not safely derived to a ``__ptrauth``-qualified gl-value.
+
+
+
+Language ABI
+------------
+
+This section describes the pointer-authentication ABI currently implemented in Clang for the Apple arm64e target. As other targets adopt pointer authentication, this section should be generalized to express their ABIs as well.
+
+Key assignments
+~~~~~~~~~~~~~~~
+
+ARMv8.3 provides four abstract signing keys: ``IA``, ``IB``, ``DA``, and ``DB``. The architecture designates ``IA`` and ``IB`` for signing code pointers and ``DA`` and ``DB`` for signing data pointers; this is reinforced by two properties:
+
+- The ISA provides instructions that perform combined auth+call and auth+load operations; these instructions can only use the ``I`` keys and ``D`` keys, respectively.
+
+- AArch64's TBI feature can be separately enabled for code pointers (controlling whether indirect-branch instructions ignore those bits) and data pointers (controlling whether memory-access instructions) ignore those bits. If TBI is enabled for a kind of pointer, the sign and auth operations preserve the TBI bits when signing with an associated keys (at the cost of shrinking the number of available signing bits by 8).
+
+arm64e then further subdivides the keys as follows:
+
+- The ``A`` keys are used for primarily "global" purposes like signing v-tables and function pointers. These keys are sometimes called *process-independent* or *cross-process* because on existing OSes they are not changed when changing processes, although this is not a platform guarantee.
+
+- The ``B`` keys are used for primarily "local" purposes like signing return addresses and frame pointers. These keys are sometimes called *process-specific* because they are typically different between processes. However, they are in fact shared across processes in one situation: systems which provide ``fork`` cannot change these keys in the child process; they can only be changed during ``exec``.
+
+Implementation-defined algorithms and quantities
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The cryptographic hash algorithm used to compute signatures in ARMv8.3 is a private detail of the hardware implementation.
+
+arm64e restricts constant discriminators (used in ``__ptrauth`` and ``ptrauth_blend_discriminator``) to the range from 0 to 65535, inclusive. A 0 discriminator generally signifies that no blending is required; see the documentation for ``ptrauth_blend_discriminator``. This range is somewhat narrow but has two advantages:
+
+- The AArch64 ISA allows an arbitrary 16-bit immediate to be written over the top 16 bits of a register in a single instruction:
+
+ .. code-block:: asm
+
+ movk xN, #0x4849, LSL 48
+
+ This is ideal for the discriminator blending operation because it adds minimal code-size overhead and avoids overwriting any interesting bits from the pointer. Blending in a wider constant discriminator would either clobber interesting bits (e.g. if it was loaded with ``movk xN, #0x4c4f, LSL 32``) or require significantly more code (e.g. if the discriminator was loaded with a ``mov+bfi`` sequence).
+
+- It is possible to pack a 16-bit discriminator into loader metadata with minimal compromises, whereas a wider discriminator would require extra metadata storage and therefore significantly impact load times.
+
+The string hash used by ``ptrauth_string_discriminator`` is a 64-bit SipHash-2-4 using the constant seed ``b5d4c9eb79104a796fec8b1b428781d4`` (big-endian), with the result reduced by modulo to the range of non-zero discriminators (i.e. ``(rawHash % 65535) + 1``).
+
+Return addresses
+~~~~~~~~~~~~~~~~
+
+The kernel must ensure that attackers cannot replace LR due to an asynchronous exception; see `Register clobbering`_. If this is done by generally protecting LR, then functions which don't spill LR to the stack can avoid signing it entirely. Otherwise, the return address must be signed; on arm64e it is signed with the ``IB`` key using the stack pointer on entry as the discriminator.
+
+Protecting return addresses is of such particular importance that the ``IB`` key is almost entirely reserved for this purpose.
+
+Global offset tables
+~~~~~~~~~~~~~~~~~~~~
+
+The global offset table (GOT) is not ABI, but it is a common implementation technique for dynamic linking which deserves special discussion here.
+
+Whenever possible, signed pointers should be materialized directly in code rather than via the GOT, e.g. using an ``adrp+add+pac`` sequence on ARMv8.3. This decreases the amount of work necessary at load time to initialize the GOT, but more importantly, it defines away the potential for several attacks:
+
+- Attackers cannot change instructions, so there is no way to cause this code sequence to materialize a different pointer, whereas an access via the GOT always has *at minimum* a probabilistic chance to be the target of successful `substitution attacks`_.
+
+- The GOT is a dense pool of fixed pointers at a fixed offset relative to code; attackers can search this pool for useful pointers that can be used in `substitution attacks`_, whereas pointers that are only materialized directly are not so easily available.
+
+- Similarly, attackers can use `access path attacks`_ to replace a pointer to a signed pointer with a pointer to the GOT if the signing schema used within the GOT happens to be the same as the original pointer. This kind of collision becomes much less likely to be useful the fewer pointers are in the GOT in the first place.
+
+If this can be done for a symbol, then the compiler need only ensure that it materializes the signed pointer using registers that are safe against `register clobbering`_.
+
+However, many symbols can only be accessed via the GOT, e.g. because they resolve to definitions outside of the current image. In this case, care must be taken to ensure that using the GOT does not introduce weaknesses.
+
+- If the entire GOT can be mapped read-only after loading, then no signing is required within the GOT. In fact, not signing pointers in the GOT is preferable in this case because it makes the GOT useless for the harvesting and access-path attacks above. Storing raw pointers in this way is usually extremely unsafe, but for the special case of an immutable GOT entry it's fine because the GOT is always accessed via an address that is directly materialized in code and thus provably unattackable. (But see `Remapping`_.)
+
+- Otherwise, GOT entries which are used for producing a signed pointer constant must be signed. The signing schema used in the GOT need not match the target signing schema for the signed constant. To counteract the threats of substitution attacks, it's best if GOT entries can be signed with address diversity. Using a good constant discriminator as well (perhaps derived from the symbol name) can make it less useful to use a pointer to the GOT as the replacement in an :ref:`access path attack`.
+
+In either case, the compiler must ensure that materializing the address of a GOT entry as part of producing a signed pointer constant is not vulnerable to `register clobbering`_. If the linker also generates code for this, e.g. for call stubs, this generated code must take the same precautions.
+
+C function pointers
+~~~~~~~~~~~~~~~~~~~
+
+On arm64e, C function pointers are currently signed with the ``IA`` key without address diversity and with a constant discriminator of 0.
+
+The C and C++ standards do not permit C function pointers to be signed with address diversity by default: in C++ terms, function pointer types are required to be trivially copyable, which means they must be copyable with ``memcpy``.
+
+The use of a uniform constant discriminator is seen as a serious defect which should be remedied, and improving this is under investigation.
+
+C++ virtual tables
+~~~~~~~~~~~~~~~~~~
+
+The pointer to a C++ virtual table is currently signed with the ``DA`` key, no address diversity, and a constant discriminator of 0. The use of no address diversity, as well as the uniform constant discriminator, are seen as weaknesses. Not using address diversity allows attackers to simply copy valid v-table pointers from one object to another. However, using a uniform discriminator of 0 does have positive performance and code-size implications on ARMv8.3, and diversity for the most important v-table access pattern (virtual dispatch) is already better assured by the signing schemas used on the virtual functions. It is also known that some code in practice copies objects containing v-tables with ``memcpy``, and while this is not permitted formally, it is something that may be invasive to eliminate.
+
+Virtual functions in a C++ virtual table are signed with the ``IA`` key, address diversity, and a constant discriminator equal to the string hash (see `ptrauth_string_discriminator`_) of the mangled name of the function which originally gave rise to the v-table slot.
+
+C++ member function pointers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A member function pointer is signed with the ``IA`` key, no address diversity, and a constant discriminator equal to the string hash (see `ptrauth_string_discriminator`_) of the member pointer type. Address diversity is not permitted by C++ for member function pointers because they must be trivially-copyable types.
+
+The Itanium C++ ABI specifies that member function pointers to virtual functions simply store an offset to the correct v-table slot. This ABI cannot be used securely with pointer authentication because there is no safe place to store the constant discriminator for the target v-table slot: if it's stored with the offset, an attacker can simply overwrite it with the right discriminator for the offset. Even if the programmer never uses pointers to virtual functions, the existence of this code path makes all member function pointer dereferences insecure.
+
+arm64e changes this ABI so that virtual function pointers are stored using dispatch thunks with vague linkage. Because arm64e supports interoperation with ``arm64`` code when pointer authentication is disabled, an arm64e member function pointer dereference still recognizes the virtual-function representation but uses an bogus discriminator on that path that should always trap if pointer authentication is enabled dynamically.
+
+The use of dispatch thunks means that ``==`` on member function pointers is no longer reliable for virtual functions, but this is acceptable because the standard makes no guarantees about it in the first place.
+
+The use of dispatch thunks also potentially enables v-tables to be signed using a declaration-specific constant discriminator in the future; otherwise this discriminator would also need to be stored in the member pointer.
+
+Blocks
+~~~~~~
+
+Block pointers are data pointers which must interoperate with the ObjC `id` type and therefore cannot be signed themselves.
+
+The invocation pointer in a block is signed with the ``IA`` key using address diversity and a constant dicriminator of 0. Using a uniform discriminator is seen as a weakness to be potentially improved, but this is tricky due to the subtype polymorphism directly permitted for blocks.
+
+Block descriptors and ``__block`` variables can contain pointers to functions that can be used to copy or destroy the object. These functions are signed with the ``IA`` key, address diversity, and a constant discriminator of 0. The structure of block descriptors is under consideration for improvement.
+
+Objective-C methods
+~~~~~~~~~~~~~~~~~~~
+
+Objective-C method lists sign methods with the ``IA`` key using address diversity and a constant discriminator of 0. Using a uniform constant discriminator is believed to be acceptable because these tables are only accessed internally to the Objective-C runtime.
+
+The Objective-C runtime provides additional protection to methods that have been loaded into the Objective-C method cache; this protection is private to the runtime.
+
+Pointer authentication cannot protect against access-path atacks against the Objective-C ``isa`` pointer, through which all dispatch occurs, because of compatibility requirements and existing and important usage of high bits in the pointer.
+
+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 cannot be a signed pointer.
+
+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..fd041344c6fdc
--- /dev/null
+++ b/clang/include/clang-c/Dependencies.h
@@ -0,0 +1,596 @@
+/*==-- 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);
+
+/**
+ * @}
+ */
+
+#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 25700a48c928c..7973212d58c49 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 9c01978fd49ef..b66d0d1da2192 100644
--- a/clang/include/clang/APINotes/Types.h
+++ b/clang/include/clang/APINotes/Types.h
@@ -662,6 +662,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) {
@@ -890,6 +893,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 9999a30c51ade..eece37ccd02da 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 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 3c78833a3f069..31a1c4c0fc05d 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -26,6 +26,7 @@
#include "clang/AST/SYCLKernelInfo.h"
#include "clang/AST/TemplateName.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"
@@ -262,6 +263,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
@@ -500,6 +509,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 =
@@ -795,6 +822,36 @@ class ASTContext : public RefCountedBase {
return DiagAllocator;
}
+ struct AvailabilityDomainInfo {
+ FeatureAvailKind Kind = FeatureAvailKind::None;
+ clang::Decl *Decl = nullptr;
+ ImplicitCastExpr *Call = nullptr;
+ 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; }
@@ -1454,9 +1511,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
@@ -1464,6 +1524,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;
@@ -2516,6 +2612,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);
@@ -2762,6 +2866,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;
@@ -2839,6 +2974,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 "canonical" nested name specifier for a
/// given nested name specifier.
///
diff --git a/clang/include/clang/AST/ASTMutationListener.h b/clang/include/clang/AST/ASTMutationListener.h
index 2c4ec2ce67f36..b8bd5403df477 100644
--- a/clang/include/clang/AST/ASTMutationListener.h
+++ b/clang/include/clang/AST/ASTMutationListener.h
@@ -149,6 +149,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 5ab438715ecf7..273cd9c4f7498 100644
--- a/clang/include/clang/AST/AbstractBasicReader.h
+++ b/clang/include/clang/AST/AbstractBasicReader.h
@@ -219,6 +219,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 f65d94abc2ff1..4572c813621a9 100644
--- a/clang/include/clang/AST/AbstractBasicWriter.h
+++ b/clang/include/clang/AST/AbstractBasicWriter.h
@@ -201,6 +201,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 994f236337b99..693c7a2be7c7d 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"
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 e96275e5f2e07..92f96d01999bc 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, llvm::ArrayRef PreArgs);
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 3faf63e395a08..b34e60c995110 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -709,6 +709,14 @@ class ValueDecl : public NamedDecl {
/// can be captured.
bool isInitCapture() const;
+ /* TO_UPSTREAM(BoundsSafety) ON */
+ /// 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();
@@ -4436,6 +4444,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.
@@ -5220,6 +5231,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/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h
index 4663603f79754..5d5d6e147dda0 100644
--- a/clang/include/clang/AST/DeclObjC.h
+++ b/clang/include/clang/AST/DeclObjC.h
@@ -881,6 +881,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; }
@@ -889,6 +894,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; }
@@ -1239,7 +1249,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,
@@ -1528,7 +1539,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();
@@ -2100,7 +2111,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,
@@ -2238,7 +2250,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();
@@ -2774,17 +2786,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);
@@ -2793,6 +2813,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 a83320a7ddec2..864c0dc708131 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"
@@ -262,6 +263,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 */
/// isLValue - True if this expression is an "l-value" according to
/// the rules of the current language. C and C++ give somewhat
@@ -782,6 +789,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,
@@ -841,6 +860,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;
@@ -923,6 +947,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();
@@ -1179,6 +1205,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) {
@@ -3892,6 +3925,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,
@@ -5231,6 +6090,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 f87fa85569c44..cea2eb198fb6d 100644
--- a/clang/include/clang/AST/ExprObjC.h
+++ b/clang/include/clang/AST/ExprObjC.h
@@ -1689,30 +1689,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 f45e3af7602c1..3d9d152e29f05 100644
--- a/clang/include/clang/AST/ExternalASTSource.h
+++ b/clang/include/clang/AST/ExternalASTSource.h
@@ -142,6 +142,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/NestedNameSpecifier.h b/clang/include/clang/AST/NestedNameSpecifier.h
index d7da3272d0943..11e6f601715d1 100644
--- a/clang/include/clang/AST/NestedNameSpecifier.h
+++ b/clang/include/clang/AST/NestedNameSpecifier.h
@@ -235,6 +235,23 @@ class NestedNameSpecifier : public llvm::FoldingSetNode {
void dump() const;
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);
};
/// A C++ nested-name-specifier augmented with source location
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