diff --git a/.ci/compute_projects.py b/.ci/compute_projects.py
index e61b8dc5021f3..40dd0507a9eaf 100644
--- a/.ci/compute_projects.py
+++ b/.ci/compute_projects.py
@@ -49,7 +49,8 @@
},
"lld": {"bolt", "cross-project-tests"},
# TODO(issues/132795): LLDB should be enabled on clang changes.
- "clang": {"clang-tools-extra", "cross-project-tests"},
+ "clang": {"clang-tools-extra", "compiler-rt", "cross-project-tests"},
+ "clang-tools-extra": {"libc"},
"mlir": {"flang"},
# Test everything if ci scripts are changed.
# FIXME: Figure out what is missing and add here.
@@ -63,15 +64,7 @@
# This mapping describes runtimes that should be tested when the key project is
# touched.
-DEPENDENT_RUNTIMES_TO_TEST = {
- "clang": {"compiler-rt"},
- "clang-tools-extra": {"libc"},
-}
-DEPENDENT_RUNTIMES_TO_TEST_NEEDS_RECONFIG = {
- "llvm": {"libcxx", "libcxxabi", "libunwind"},
- "clang": {"libcxx", "libcxxabi", "libunwind"},
- ".ci": {"libcxx", "libcxxabi", "libunwind"},
-}
+DEPENDENT_RUNTIMES_TO_TEST = {"clang": {"libcxx", "libcxxabi", "libunwind"}}
EXCLUDE_LINUX = {
"cross-project-tests", # TODO(issues/132796): Tests are failing.
@@ -100,6 +93,9 @@
"cross-project-tests",
"flang",
"libc",
+ "libcxx",
+ "libcxxabi",
+ "libunwind",
"lldb",
"openmp",
"polly",
@@ -126,10 +122,10 @@
"polly": "check-polly",
}
-RUNTIMES = {"libcxx", "libcxxabi", "libunwind", "compiler-rt", "libc"}
+RUNTIMES = {"libcxx", "libcxxabi", "libunwind"}
-def _add_dependencies(projects: Set[str], runtimes: Set[str]) -> Set[str]:
+def _add_dependencies(projects: Set[str]) -> Set[str]:
projects_with_dependents = set(projects)
current_projects_count = 0
while current_projects_count != len(projects_with_dependents):
@@ -138,25 +134,9 @@ def _add_dependencies(projects: Set[str], runtimes: Set[str]) -> Set[str]:
if project not in PROJECT_DEPENDENCIES:
continue
projects_with_dependents.update(PROJECT_DEPENDENCIES[project])
- for runtime in runtimes:
- if runtime not in PROJECT_DEPENDENCIES:
- continue
- projects_with_dependents.update(PROJECT_DEPENDENCIES[runtime])
return projects_with_dependents
-def _exclude_projects(current_projects: Set[str], platform: str) -> Set[str]:
- if platform == "Linux":
- to_exclude = EXCLUDE_LINUX
- elif platform == "Windows":
- to_exclude = EXCLUDE_WINDOWS
- elif platform == "Darwin":
- to_exclude = EXCLUDE_MAC
- else:
- raise ValueError(f"Unexpected platform: {platform}")
- return current_projects.difference(to_exclude)
-
-
def _compute_projects_to_test(modified_projects: Set[str], platform: str) -> Set[str]:
projects_to_test = set()
for modified_project in modified_projects:
@@ -174,14 +154,25 @@ def _compute_projects_to_test(modified_projects: Set[str], platform: str) -> Set
):
continue
projects_to_test.add(dependent_project)
- projects_to_test = _exclude_projects(projects_to_test, platform)
+ if platform == "Linux":
+ for to_exclude in EXCLUDE_LINUX:
+ if to_exclude in projects_to_test:
+ projects_to_test.remove(to_exclude)
+ elif platform == "Windows":
+ for to_exclude in EXCLUDE_WINDOWS:
+ if to_exclude in projects_to_test:
+ projects_to_test.remove(to_exclude)
+ elif platform == "Darwin":
+ for to_exclude in EXCLUDE_MAC:
+ if to_exclude in projects_to_test:
+ projects_to_test.remove(to_exclude)
+ else:
+ raise ValueError("Unexpected platform.")
return projects_to_test
-def _compute_projects_to_build(
- projects_to_test: Set[str], runtimes: Set[str]
-) -> Set[str]:
- return _add_dependencies(projects_to_test, runtimes)
+def _compute_projects_to_build(projects_to_test: Set[str]) -> Set[str]:
+ return _add_dependencies(projects_to_test)
def _compute_project_check_targets(projects_to_test: Set[str]) -> Set[str]:
@@ -193,36 +184,24 @@ def _compute_project_check_targets(projects_to_test: Set[str]) -> Set[str]:
return check_targets
-def _compute_runtimes_to_test(modified_projects: Set[str], platform: str) -> Set[str]:
+def _compute_runtimes_to_test(projects_to_test: Set[str]) -> Set[str]:
runtimes_to_test = set()
- for modified_project in modified_projects:
- if modified_project not in DEPENDENT_RUNTIMES_TO_TEST:
- continue
- runtimes_to_test.update(DEPENDENT_RUNTIMES_TO_TEST[modified_project])
- return _exclude_projects(runtimes_to_test, platform)
+ for project_to_test in projects_to_test:
+ if project_to_test in DEPENDENT_RUNTIMES_TO_TEST:
+ runtimes_to_test.update(DEPENDENT_RUNTIMES_TO_TEST[project_to_test])
+ if project_to_test in DEPENDENT_RUNTIMES_TO_BUILD:
+ runtimes_to_test.update(DEPENDENT_RUNTIMES_TO_BUILD[project_to_test])
+ return runtimes_to_test
-def _compute_runtimes_to_test_needs_reconfig(
- modified_projects: Set[str], platform: str
-) -> Set[str]:
- runtimes_to_test = set()
- for modified_project in modified_projects:
- if modified_project not in DEPENDENT_RUNTIMES_TO_TEST_NEEDS_RECONFIG:
+def _compute_runtime_check_targets(projects_to_test: Set[str]) -> Set[str]:
+ check_targets = set()
+ for project_to_test in projects_to_test:
+ if project_to_test not in DEPENDENT_RUNTIMES_TO_TEST:
continue
- runtimes_to_test.update(
- DEPENDENT_RUNTIMES_TO_TEST_NEEDS_RECONFIG[modified_project]
- )
- return _exclude_projects(runtimes_to_test, platform)
-
-
-def _compute_runtimes_to_build(
- runtimes_to_test: Set[str], modified_projects: Set[str], platform: str
-) -> Set[str]:
- runtimes_to_build = set(runtimes_to_test)
- for modified_project in modified_projects:
- if modified_project in DEPENDENT_RUNTIMES_TO_BUILD:
- runtimes_to_build.update(DEPENDENT_RUNTIMES_TO_BUILD[modified_project])
- return _exclude_projects(runtimes_to_build, platform)
+ for runtime_to_test in DEPENDENT_RUNTIMES_TO_TEST[project_to_test]:
+ check_targets.add(PROJECT_CHECK_TARGETS[runtime_to_test])
+ return check_targets
def _get_modified_projects(modified_files: list[str]) -> Set[str]:
@@ -246,19 +225,10 @@ def _get_modified_projects(modified_files: list[str]) -> Set[str]:
def get_env_variables(modified_files: list[str], platform: str) -> Set[str]:
modified_projects = _get_modified_projects(modified_files)
projects_to_test = _compute_projects_to_test(modified_projects, platform)
- runtimes_to_test = _compute_runtimes_to_test(modified_projects, platform)
- runtimes_to_test_needs_reconfig = _compute_runtimes_to_test_needs_reconfig(
- modified_projects, platform
- )
- runtimes_to_build = _compute_runtimes_to_build(
- runtimes_to_test | runtimes_to_test_needs_reconfig, modified_projects, platform
- )
- projects_to_build = _compute_projects_to_build(projects_to_test, runtimes_to_build)
+ projects_to_build = _compute_projects_to_build(projects_to_test)
projects_check_targets = _compute_project_check_targets(projects_to_test)
- runtimes_check_targets = _compute_project_check_targets(runtimes_to_test)
- runtimes_check_targets_needs_reconfig = _compute_project_check_targets(
- runtimes_to_test_needs_reconfig
- )
+ runtimes_to_build = _compute_runtimes_to_test(projects_to_test)
+ runtimes_check_targets = _compute_runtime_check_targets(projects_to_test)
# We use a semicolon to separate the projects/runtimes as they get passed
# to the CMake invocation and thus we need to use the CMake list separator
# (;). We use spaces to separate the check targets as they end up getting
@@ -268,9 +238,6 @@ def get_env_variables(modified_files: list[str], platform: str) -> Set[str]:
"project_check_targets": " ".join(sorted(projects_check_targets)),
"runtimes_to_build": ";".join(sorted(runtimes_to_build)),
"runtimes_check_targets": " ".join(sorted(runtimes_check_targets)),
- "runtimes_check_targets_needs_reconfig": " ".join(
- sorted(runtimes_check_targets_needs_reconfig)
- ),
}
diff --git a/.ci/compute_projects_test.py b/.ci/compute_projects_test.py
index 6bc2e34a1cbe1..ae376ea6a43cd 100644
--- a/.ci/compute_projects_test.py
+++ b/.ci/compute_projects_test.py
@@ -26,10 +26,6 @@ def test_llvm(self):
)
self.assertEqual(
env_variables["runtimes_check_targets"],
- "",
- )
- self.assertEqual(
- env_variables["runtimes_check_targets_needs_reconfig"],
"check-cxx check-cxxabi check-unwind",
)
@@ -50,10 +46,6 @@ def test_llvm_windows(self):
)
self.assertEqual(
env_variables["runtimes_check_targets"],
- "",
- )
- self.assertEqual(
- env_variables["runtimes_check_targets_needs_reconfig"],
"check-cxx check-cxxabi check-unwind",
)
@@ -74,10 +66,6 @@ def test_llvm_mac(self):
)
self.assertEqual(
env_variables["runtimes_check_targets"],
- "",
- )
- self.assertEqual(
- env_variables["runtimes_check_targets_needs_reconfig"],
"check-cxx check-cxxabi check-unwind",
)
@@ -87,21 +75,17 @@ def test_clang(self):
)
self.assertEqual(
env_variables["projects_to_build"],
- "clang;clang-tools-extra;lld;llvm",
+ "clang;clang-tools-extra;compiler-rt;lld;llvm",
)
self.assertEqual(
env_variables["project_check_targets"],
- "check-clang check-clang-tools",
+ "check-clang check-clang-tools check-compiler-rt",
)
self.assertEqual(
- env_variables["runtimes_to_build"], "compiler-rt;libcxx;libcxxabi;libunwind"
+ env_variables["runtimes_to_build"], "libcxx;libcxxabi;libunwind"
)
self.assertEqual(
env_variables["runtimes_check_targets"],
- "check-compiler-rt",
- )
- self.assertEqual(
- env_variables["runtimes_check_targets_needs_reconfig"],
"check-cxx check-cxxabi check-unwind",
)
@@ -120,10 +104,6 @@ def test_clang_windows(self):
)
self.assertEqual(
env_variables["runtimes_check_targets"],
- "",
- )
- self.assertEqual(
- env_variables["runtimes_check_targets_needs_reconfig"],
"check-cxx check-cxxabi check-unwind",
)
@@ -135,7 +115,6 @@ def test_bolt(self):
self.assertEqual(env_variables["project_check_targets"], "check-bolt")
self.assertEqual(env_variables["runtimes_to_build"], "")
self.assertEqual(env_variables["runtimes_check_targets"], "")
- self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "")
def test_lldb(self):
env_variables = compute_projects.get_env_variables(
@@ -145,7 +124,6 @@ def test_lldb(self):
self.assertEqual(env_variables["project_check_targets"], "check-lldb")
self.assertEqual(env_variables["runtimes_to_build"], "")
self.assertEqual(env_variables["runtimes_check_targets"], "")
- self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "")
def test_mlir(self):
env_variables = compute_projects.get_env_variables(
@@ -157,7 +135,6 @@ def test_mlir(self):
)
self.assertEqual(env_variables["runtimes_to_build"], "")
self.assertEqual(env_variables["runtimes_check_targets"], "")
- self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "")
def test_flang(self):
env_variables = compute_projects.get_env_variables(
@@ -167,7 +144,6 @@ def test_flang(self):
self.assertEqual(env_variables["project_check_targets"], "check-flang")
self.assertEqual(env_variables["runtimes_to_build"], "")
self.assertEqual(env_variables["runtimes_check_targets"], "")
- self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "")
def test_invalid_subproject(self):
env_variables = compute_projects.get_env_variables(
@@ -177,7 +153,6 @@ def test_invalid_subproject(self):
self.assertEqual(env_variables["project_check_targets"], "")
self.assertEqual(env_variables["runtimes_to_build"], "")
self.assertEqual(env_variables["runtimes_check_targets"], "")
- self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "")
def test_top_level_file(self):
env_variables = compute_projects.get_env_variables(["README.md"], "Linux")
@@ -185,7 +160,6 @@ def test_top_level_file(self):
self.assertEqual(env_variables["project_check_targets"], "")
self.assertEqual(env_variables["runtimes_to_build"], "")
self.assertEqual(env_variables["runtimes_check_targets"], "")
- self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "")
def test_exclude_runtiems_in_projects(self):
env_variables = compute_projects.get_env_variables(
@@ -195,7 +169,6 @@ def test_exclude_runtiems_in_projects(self):
self.assertEqual(env_variables["project_check_targets"], "")
self.assertEqual(env_variables["runtimes_to_build"], "")
self.assertEqual(env_variables["runtimes_check_targets"], "")
- self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "")
def test_exclude_docs(self):
env_variables = compute_projects.get_env_variables(
@@ -205,7 +178,6 @@ def test_exclude_docs(self):
self.assertEqual(env_variables["project_check_targets"], "")
self.assertEqual(env_variables["runtimes_to_build"], "")
self.assertEqual(env_variables["runtimes_check_targets"], "")
- self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "")
def test_exclude_gn(self):
env_variables = compute_projects.get_env_variables(
@@ -215,7 +187,6 @@ def test_exclude_gn(self):
self.assertEqual(env_variables["project_check_targets"], "")
self.assertEqual(env_variables["runtimes_to_build"], "")
self.assertEqual(env_variables["runtimes_check_targets"], "")
- self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "")
def test_ci(self):
env_variables = compute_projects.get_env_variables(
@@ -227,15 +198,10 @@ def test_ci(self):
"check-clang check-lld check-lldb check-llvm",
)
self.assertEqual(
- env_variables["runtimes_to_build"],
- "libcxx;libcxxabi;libunwind",
+ env_variables["runtimes_to_build"], "libcxx;libcxxabi;libunwind"
)
self.assertEqual(
env_variables["runtimes_check_targets"],
- "",
- )
- self.assertEqual(
- env_variables["runtimes_check_targets_needs_reconfig"],
"check-cxx check-cxxabi check-unwind",
)
@@ -249,19 +215,6 @@ def test_lldb(self):
env_variables["runtimes_to_build"], "libcxx;libcxxabi;libunwind"
)
self.assertEqual(env_variables["runtimes_check_targets"], "")
- self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "")
-
- def test_clang_tools_extra(self):
- env_variables = compute_projects.get_env_variables(
- ["clang-tools-extra/CMakeLists.txt"], "Linux"
- )
- self.assertEqual(
- env_variables["projects_to_build"], "clang;clang-tools-extra;lld;llvm"
- )
- self.assertEqual(env_variables["project_check_targets"], "check-clang-tools")
- self.assertEqual(env_variables["runtimes_to_build"], "libc")
- self.assertEqual(env_variables["runtimes_check_targets"], "check-libc")
- self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "")
if __name__ == "__main__":
diff --git a/.ci/monolithic-linux.sh b/.ci/monolithic-linux.sh
index c350a58679140..7503ea4e6a992 100755
--- a/.ci/monolithic-linux.sh
+++ b/.ci/monolithic-linux.sh
@@ -57,7 +57,6 @@ projects="${1}"
targets="${2}"
runtimes="${3}"
runtime_targets="${4}"
-runtime_targets_needs_reconfig="${5}"
lit_args="-v --xunit-xml-output ${BUILD_DIR}/test-results.xml --use-unique-output-file-name --timeout=1200 --time-tests"
@@ -94,15 +93,9 @@ echo "--- ninja"
# Targets are not escaped as they are passed as separate arguments.
ninja -C "${BUILD_DIR}" -k 0 ${targets}
-if [[ "${runtime_targets}" != "" ]]; then
- echo "--- ninja runtimes"
-
- ninja -C "${BUILD_DIR}" ${runtime_targets}
-fi
-
# Compiling runtimes with just-built Clang and running their tests
# as an additional testing for Clang.
-if [[ "${runtime_targets_needs_reconfig}" != "" ]]; then
+if [[ "${runtimes_targets}" != "" ]]; then
echo "--- cmake runtimes C++26"
cmake \
@@ -112,7 +105,7 @@ if [[ "${runtime_targets_needs_reconfig}" != "" ]]; then
echo "--- ninja runtimes C++26"
- ninja -C "${BUILD_DIR}" ${runtime_targets_needs_reconfig}
+ ninja -C "${BUILD_DIR}" ${runtime_targets}
echo "--- cmake runtimes clang modules"
@@ -123,5 +116,5 @@ if [[ "${runtime_targets_needs_reconfig}" != "" ]]; then
echo "--- ninja runtimes clang modules"
- ninja -C "${BUILD_DIR}" ${runtime_targets_needs_reconfig}
+ ninja -C "${BUILD_DIR}" ${runtime_targets}
fi
diff --git a/.github/new-prs-labeler.yml b/.github/new-prs-labeler.yml
index 162161ff13fb0..2f8d5745668d9 100644
--- a/.github/new-prs-labeler.yml
+++ b/.github/new-prs-labeler.yml
@@ -777,6 +777,10 @@ backend:NVPTX:
- 'llvm/**/*nvptx*/**'
- 'llvm/**/*NVPTX*/**'
+backend:MIPS:
+ - '**/*mips*'
+ - '**/*Mips*'
+
backend:RISC-V:
- clang/**/*riscv*
- clang/**/*RISCV*
diff --git a/.github/workflows/email-check.yaml b/.github/workflows/email-check.yaml
index f4481d5cf5583..904ad718f97dd 100644
--- a/.github/workflows/email-check.yaml
+++ b/.github/workflows/email-check.yaml
@@ -32,7 +32,8 @@ jobs:
COMMENT: >-
⚠️ We detected that you are using a GitHub private e-mail address to contribute to the repo.
Please turn off [Keep my email addresses private](https://github.com/settings/emails) setting in your account.
- See [LLVM Discourse](https://discourse.llvm.org/t/hidden-emails-on-github-should-we-do-something-about-it) for more information.
+ See [LLVM Developer Policy](https://llvm.org/docs/DeveloperPolicy.html#email-addresses) and
+ [LLVM Discourse](https://discourse.llvm.org/t/hidden-emails-on-github-should-we-do-something-about-it) for more information.
run: |
cat << EOF > comments
[{"body" : "$COMMENT"}]
diff --git a/.github/workflows/libcxx-build-and-test.yaml b/.github/workflows/libcxx-build-and-test.yaml
index 80f2432b78dea..f0bdf6c0b5899 100644
--- a/.github/workflows/libcxx-build-and-test.yaml
+++ b/.github/workflows/libcxx-build-and-test.yaml
@@ -52,8 +52,8 @@ jobs:
cxx: [ 'clang++-21' ]
include:
- config: 'generic-gcc'
- cc: 'gcc-14'
- cxx: 'g++-14'
+ cc: 'gcc-15'
+ cxx: 'g++-15'
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ${{ matrix.config }}.${{ matrix.cxx }}
@@ -92,8 +92,8 @@ jobs:
cxx: [ 'clang++-21' ]
include:
- config: 'generic-gcc-cxx11'
- cc: 'gcc-14'
- cxx: 'g++-14'
+ cc: 'gcc-15'
+ cxx: 'g++-15'
- config: 'generic-cxx26'
cc: 'clang-20'
cxx: 'clang++-20'
diff --git a/.github/workflows/premerge.yaml b/.github/workflows/premerge.yaml
index 4435a3e905768..709b6d03d94c3 100644
--- a/.github/workflows/premerge.yaml
+++ b/.github/workflows/premerge.yaml
@@ -56,12 +56,11 @@ jobs:
echo "Running project checks targets: ${project_check_targets}"
echo "Building runtimes: ${runtimes_to_build}"
echo "Running runtimes checks targets: ${runtimes_check_targets}"
- echo "Running runtimes checks requiring reconfiguring targets: ${runtimes_check_targets_needs_reconfig}"
export CC=/opt/llvm/bin/clang
export CXX=/opt/llvm/bin/clang++
- ./.ci/monolithic-linux.sh "${projects_to_build}" "${project_check_targets}" "${runtimes_to_build}" "${runtimes_check_targets}" "${runtimes_check_targets_needs_reconfig}"
+ ./.ci/monolithic-linux.sh "${projects_to_build}" "${project_check_targets}" "${runtimes_to_build}" "${runtimes_check_targets}"
- name: Upload Artifacts
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h
index 14957cba50174..ca8b786f4ab69 100644
--- a/bolt/include/bolt/Core/BinaryFunction.h
+++ b/bolt/include/bolt/Core/BinaryFunction.h
@@ -388,6 +388,10 @@ class BinaryFunction {
/// The profile data for the number of times the function was executed.
uint64_t ExecutionCount{COUNT_NO_PROFILE};
+ /// Profile data for the number of times this function was entered from
+ /// external code (DSO, JIT, etc).
+ uint64_t ExternEntryCount{0};
+
/// Profile match ratio.
float ProfileMatchRatio{0.0f};
@@ -1877,6 +1881,10 @@ class BinaryFunction {
return *this;
}
+ /// Set the profile data for the number of times the function was entered from
+ /// external code (DSO/JIT).
+ void setExternEntryCount(uint64_t Count) { ExternEntryCount = Count; }
+
/// Adjust execution count for the function by a given \p Count. The value
/// \p Count will be subtracted from the current function count.
///
@@ -1904,6 +1912,10 @@ class BinaryFunction {
/// Return COUNT_NO_PROFILE if there's no profile info.
uint64_t getExecutionCount() const { return ExecutionCount; }
+ /// Return the profile information about the number of times the function was
+ /// entered from external code (DSO/JIT).
+ uint64_t getExternEntryCount() const { return ExternEntryCount; }
+
/// Return the raw profile information about the number of branch
/// executions corresponding to this function.
uint64_t getRawSampleCount() const { return RawSampleCount; }
diff --git a/bolt/include/bolt/Profile/DataAggregator.h b/bolt/include/bolt/Profile/DataAggregator.h
index 3f07a6dc03a4f..96969cf53baca 100644
--- a/bolt/include/bolt/Profile/DataAggregator.h
+++ b/bolt/include/bolt/Profile/DataAggregator.h
@@ -99,24 +99,28 @@ class DataAggregator : public DataReader {
uint64_t Addr;
};
+ /// Container for the unit of branch data.
+ /// Backwards compatible with legacy use for branches and fall-throughs:
+ /// - if \p Branch is FT_ONLY or FT_EXTERNAL_ORIGIN, the trace only
+ /// contains fall-through data,
+ /// - if \p To is BR_ONLY, the trace only contains branch data.
struct Trace {
+ static constexpr const uint64_t EXTERNAL = 0ULL;
+ static constexpr const uint64_t BR_ONLY = -1ULL;
+ static constexpr const uint64_t FT_ONLY = -1ULL;
+ static constexpr const uint64_t FT_EXTERNAL_ORIGIN = -2ULL;
+
+ uint64_t Branch;
uint64_t From;
uint64_t To;
- Trace(uint64_t From, uint64_t To) : From(From), To(To) {}
- bool operator==(const Trace &Other) const {
- return From == Other.From && To == Other.To;
- }
+ auto tie() const { return std::tie(Branch, From, To); }
+ bool operator==(const Trace &Other) const { return tie() == Other.tie(); }
+ bool operator<(const Trace &Other) const { return tie() < Other.tie(); }
};
+ friend raw_ostream &operator<<(raw_ostream &OS, const Trace &);
struct TraceHash {
- size_t operator()(const Trace &L) const {
- return std::hash()(L.From << 32 | L.To);
- }
- };
-
- struct FTInfo {
- uint64_t InternCount{0};
- uint64_t ExternCount{0};
+ size_t operator()(const Trace &L) const { return hash_combine(L.tie()); }
};
struct TakenBranchInfo {
@@ -126,8 +130,11 @@ class DataAggregator : public DataReader {
/// Intermediate storage for profile data. We save the results of parsing
/// and use them later for processing and assigning profile.
- std::unordered_map BranchLBRs;
- std::unordered_map FallthroughLBRs;
+ std::unordered_map TraceMap;
+ std::vector> Traces;
+ /// Pre-populated addresses of returns, coming from pre-aggregated data or
+ /// disassembly. Used to disambiguate call-continuation fall-throughs.
+ std::unordered_set Returns;
std::unordered_map BasicSamples;
std::vector MemSamples;
@@ -200,8 +207,8 @@ class DataAggregator : public DataReader {
/// Return a vector of offsets corresponding to a trace in a function
/// if the trace is valid, std::nullopt otherwise.
std::optional, 16>>
- getFallthroughsInTrace(BinaryFunction &BF, const LBREntry &First,
- const LBREntry &Second, uint64_t Count = 1) const;
+ getFallthroughsInTrace(BinaryFunction &BF, const Trace &Trace, uint64_t Count,
+ bool IsReturn) const;
/// Record external entry into the function \p BF.
///
@@ -261,12 +268,14 @@ class DataAggregator : public DataReader {
uint64_t From, uint64_t To, uint64_t Count,
uint64_t Mispreds);
+ /// Checks if \p Addr corresponds to a return instruction.
+ bool checkReturn(uint64_t Addr);
+
/// Register a \p Branch.
bool doBranch(uint64_t From, uint64_t To, uint64_t Count, uint64_t Mispreds);
/// Register a trace between two LBR entries supplied in execution order.
- bool doTrace(const LBREntry &First, const LBREntry &Second,
- uint64_t Count = 1);
+ bool doTrace(const Trace &Trace, uint64_t Count, bool IsReturn);
/// Parser helpers
/// Return false if we exhausted our parser buffer and finished parsing
@@ -516,6 +525,21 @@ inline raw_ostream &operator<<(raw_ostream &OS,
OS << formatv("{0:x} -> {1:x}/{2}", L.From, L.To, L.Mispred ? 'M' : 'P');
return OS;
}
+
+inline raw_ostream &operator<<(raw_ostream &OS,
+ const DataAggregator::Trace &T) {
+ switch (T.Branch) {
+ case DataAggregator::Trace::FT_ONLY:
+ case DataAggregator::Trace::FT_EXTERNAL_ORIGIN:
+ break;
+ default:
+ OS << Twine::utohexstr(T.Branch) << " -> ";
+ }
+ OS << Twine::utohexstr(T.From);
+ if (T.To != DataAggregator::Trace::BR_ONLY)
+ OS << " ... " << Twine::utohexstr(T.To);
+ return OS;
+}
} // namespace bolt
} // namespace llvm
diff --git a/bolt/include/bolt/Profile/DataReader.h b/bolt/include/bolt/Profile/DataReader.h
index 3c770fed2598f..6f527ba3931d4 100644
--- a/bolt/include/bolt/Profile/DataReader.h
+++ b/bolt/include/bolt/Profile/DataReader.h
@@ -97,6 +97,9 @@ struct FuncBranchData {
/// Total execution count for the function.
int64_t ExecutionCount{0};
+ /// Total entry count from external code for the function.
+ uint64_t ExternEntryCount{0};
+
/// Indicate if the data was used.
bool Used{false};
diff --git a/bolt/include/bolt/Profile/ProfileYAMLMapping.h b/bolt/include/bolt/Profile/ProfileYAMLMapping.h
index a8d9a15311d94..41e2bd1651efd 100644
--- a/bolt/include/bolt/Profile/ProfileYAMLMapping.h
+++ b/bolt/include/bolt/Profile/ProfileYAMLMapping.h
@@ -206,6 +206,7 @@ struct BinaryFunctionProfile {
uint32_t Id{0};
llvm::yaml::Hex64 Hash{0};
uint64_t ExecCount{0};
+ uint64_t ExternEntryCount{0};
std::vector Blocks;
std::vector InlineTree;
bool Used{false};
@@ -218,6 +219,7 @@ template <> struct MappingTraits {
YamlIO.mapRequired("fid", BFP.Id);
YamlIO.mapRequired("hash", BFP.Hash);
YamlIO.mapRequired("exec", BFP.ExecCount);
+ YamlIO.mapOptional("extern", BFP.ExternEntryCount, 0);
YamlIO.mapRequired("nblocks", BFP.NumBasicBlocks);
YamlIO.mapOptional("blocks", BFP.Blocks,
std::vector());
diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp
index 6d1969f5c6c30..b998d7160aae7 100644
--- a/bolt/lib/Core/BinaryFunction.cpp
+++ b/bolt/lib/Core/BinaryFunction.cpp
@@ -471,6 +471,8 @@ void BinaryFunction::print(raw_ostream &OS, std::string Annotation) {
OS << "\n Sample Count: " << RawSampleCount;
OS << "\n Profile Acc : " << format("%.1f%%", ProfileMatchRatio * 100.0f);
}
+ if (ExternEntryCount)
+ OS << "\n Extern Entry Count: " << ExternEntryCount;
if (opts::PrintDynoStats && !getLayout().block_empty()) {
OS << '\n';
diff --git a/bolt/lib/Passes/ProfileQualityStats.cpp b/bolt/lib/Passes/ProfileQualityStats.cpp
index dfd74d3dd5719..64cc662c3ab29 100644
--- a/bolt/lib/Passes/ProfileQualityStats.cpp
+++ b/bolt/lib/Passes/ProfileQualityStats.cpp
@@ -532,6 +532,9 @@ void computeFlowMappings(const BinaryContext &BC, FlowInfo &TotalFlowMap) {
std::vector &MaxCountMap = TotalMaxCountMaps[FunctionNum];
std::vector &MinCountMap = TotalMinCountMaps[FunctionNum];
+ // Record external entry count into CallGraphIncomingFlows
+ CallGraphIncomingFlows[FunctionNum] += Function->getExternEntryCount();
+
// Update MaxCountMap, MinCountMap, and CallGraphIncomingFlows
auto recordCall = [&](const BinaryBasicBlock *SourceBB,
const MCSymbol *DestSymbol, uint64_t Count,
diff --git a/bolt/lib/Passes/RetpolineInsertion.cpp b/bolt/lib/Passes/RetpolineInsertion.cpp
index 98e5a8fba6454..bda26206e16c3 100644
--- a/bolt/lib/Passes/RetpolineInsertion.cpp
+++ b/bolt/lib/Passes/RetpolineInsertion.cpp
@@ -195,7 +195,7 @@ std::string createRetpolineFunctionTag(BinaryContext &BC,
TagOS << "+";
if (MemRef.DispExpr)
- MemRef.DispExpr->print(TagOS, BC.AsmInfo.get());
+ BC.AsmInfo->printExpr(TagOS, *MemRef.DispExpr);
else
TagOS << MemRef.DispImm;
diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp
index 4022212bcf1b6..178c9d3a63730 100644
--- a/bolt/lib/Profile/DataAggregator.cpp
+++ b/bolt/lib/Profile/DataAggregator.cpp
@@ -61,6 +61,12 @@ FilterMemProfile("filter-mem-profile",
cl::init(true),
cl::cat(AggregatorCategory));
+static cl::opt ParseMemProfile(
+ "parse-mem-profile",
+ cl::desc("enable memory profile parsing if it's present in the input data, "
+ "on by default unless `--itrace` is set."),
+ cl::init(true), cl::cat(AggregatorCategory));
+
static cl::opt
FilterPID("pid",
cl::desc("only use samples from process with specified PID"),
@@ -181,6 +187,10 @@ void DataAggregator::start() {
"script -F pid,event,ip",
/*Wait = */false);
} else if (!opts::ITraceAggregation.empty()) {
+ // Disable parsing memory profile from trace data, unless requested by user.
+ if (!opts::ParseMemProfile.getNumOccurrences())
+ opts::ParseMemProfile = false;
+
std::string ItracePerfScriptArgs = llvm::formatv(
"script -F pid,brstack --itrace={0}", opts::ITraceAggregation);
launchPerfProcess("branch events with itrace", MainEventsPPI,
@@ -191,12 +201,9 @@ void DataAggregator::start() {
/*Wait = */ false);
}
- // Note: we launch script for mem events regardless of the option, as the
- // command fails fairly fast if mem events were not collected.
- launchPerfProcess("mem events",
- MemEventsPPI,
- "script -F pid,event,addr,ip",
- /*Wait = */false);
+ if (opts::ParseMemProfile)
+ launchPerfProcess("mem events", MemEventsPPI, "script -F pid,event,addr,ip",
+ /*Wait = */ false);
launchPerfProcess("process events", MMapEventsPPI,
"script --show-mmap-events --no-itrace",
@@ -217,7 +224,8 @@ void DataAggregator::abort() {
sys::Wait(TaskEventsPPI.PI, 1, &Error);
sys::Wait(MMapEventsPPI.PI, 1, &Error);
sys::Wait(MainEventsPPI.PI, 1, &Error);
- sys::Wait(MemEventsPPI.PI, 1, &Error);
+ if (opts::ParseMemProfile)
+ sys::Wait(MemEventsPPI.PI, 1, &Error);
deleteTempFiles();
@@ -506,7 +514,8 @@ Error DataAggregator::preprocessProfile(BinaryContext &BC) {
errs() << "PERF2BOLT: failed to parse samples\n";
// Special handling for memory events
- if (!prepareToParse("mem events", MemEventsPPI, MemEventsErrorCallback))
+ if (opts::ParseMemProfile &&
+ !prepareToParse("mem events", MemEventsPPI, MemEventsErrorCallback))
if (const std::error_code EC = parseMemEvents())
errs() << "PERF2BOLT: failed to parse memory events: " << EC.message()
<< '\n';
@@ -514,6 +523,10 @@ Error DataAggregator::preprocessProfile(BinaryContext &BC) {
deleteTempFiles();
heatmap:
+ // Sort parsed traces for faster processing.
+ if (!opts::BasicAggregation)
+ llvm::sort(Traces, llvm::less_first());
+
if (!opts::HeatmapMode)
return Error::success();
@@ -589,8 +602,7 @@ void DataAggregator::processProfile(BinaryContext &BC) {
llvm::stable_sort(MemEvents.second.Data);
// Release intermediate storage.
- clear(BranchLBRs);
- clear(FallthroughLBRs);
+ clear(Traces);
clear(BasicSamples);
clear(MemSamples);
}
@@ -718,50 +730,54 @@ bool DataAggregator::doInterBranch(BinaryFunction *FromFunc,
return true;
}
+bool DataAggregator::checkReturn(uint64_t Addr) {
+ auto isReturn = [&](auto MI) { return MI && BC->MIB->isReturn(*MI); };
+ if (llvm::is_contained(Returns, Addr))
+ return true;
+
+ BinaryFunction *Func = getBinaryFunctionContainingAddress(Addr);
+ if (!Func)
+ return false;
+
+ const uint64_t Offset = Addr - Func->getAddress();
+ if (Func->hasInstructions()
+ ? isReturn(Func->getInstructionAtOffset(Offset))
+ : isReturn(Func->disassembleInstructionAtOffset(Offset))) {
+ Returns.emplace(Addr);
+ return true;
+ }
+ return false;
+}
+
bool DataAggregator::doBranch(uint64_t From, uint64_t To, uint64_t Count,
uint64_t Mispreds) {
- // Returns whether \p Offset in \p Func contains a return instruction.
- auto checkReturn = [&](const BinaryFunction &Func, const uint64_t Offset) {
- auto isReturn = [&](auto MI) { return MI && BC->MIB->isReturn(*MI); };
- return Func.hasInstructions()
- ? isReturn(Func.getInstructionAtOffset(Offset))
- : isReturn(Func.disassembleInstructionAtOffset(Offset));
- };
-
// Mutates \p Addr to an offset into the containing function, performing BAT
// offset translation and parent lookup.
//
- // Returns the containing function (or BAT parent) and whether the address
- // corresponds to a return (if \p IsFrom) or a call continuation (otherwise).
+ // Returns the containing function (or BAT parent).
auto handleAddress = [&](uint64_t &Addr, bool IsFrom) {
BinaryFunction *Func = getBinaryFunctionContainingAddress(Addr);
if (!Func) {
Addr = 0;
- return std::pair{Func, false};
+ return Func;
}
Addr -= Func->getAddress();
- bool IsRet = IsFrom && checkReturn(*Func, Addr);
-
if (BAT)
Addr = BAT->translate(Func->getAddress(), Addr, IsFrom);
if (BinaryFunction *ParentFunc = getBATParentFunction(*Func))
- Func = ParentFunc;
+ return ParentFunc;
- return std::pair{Func, IsRet};
+ return Func;
};
- auto [FromFunc, IsReturn] = handleAddress(From, /*IsFrom*/ true);
- auto [ToFunc, _] = handleAddress(To, /*IsFrom*/ false);
+ BinaryFunction *FromFunc = handleAddress(From, /*IsFrom*/ true);
+ BinaryFunction *ToFunc = handleAddress(To, /*IsFrom*/ false);
if (!FromFunc && !ToFunc)
return false;
- // Ignore returns.
- if (IsReturn)
- return true;
-
// Treat recursive control transfers as inter-branches.
if (FromFunc == ToFunc && To != 0) {
recordBranch(*FromFunc, From, To, Count, Mispreds);
@@ -771,37 +787,20 @@ bool DataAggregator::doBranch(uint64_t From, uint64_t To, uint64_t Count,
return doInterBranch(FromFunc, ToFunc, From, To, Count, Mispreds);
}
-bool DataAggregator::doTrace(const LBREntry &First, const LBREntry &Second,
- uint64_t Count) {
- BinaryFunction *FromFunc = getBinaryFunctionContainingAddress(First.To);
- BinaryFunction *ToFunc = getBinaryFunctionContainingAddress(Second.From);
+bool DataAggregator::doTrace(const Trace &Trace, uint64_t Count,
+ bool IsReturn) {
+ const uint64_t From = Trace.From, To = Trace.To;
+ BinaryFunction *FromFunc = getBinaryFunctionContainingAddress(From);
+ BinaryFunction *ToFunc = getBinaryFunctionContainingAddress(To);
+ NumTraces += Count;
if (!FromFunc || !ToFunc) {
- LLVM_DEBUG({
- dbgs() << "Out of range trace starting in ";
- if (FromFunc)
- dbgs() << formatv("{0} @ {1:x}", *FromFunc,
- First.To - FromFunc->getAddress());
- else
- dbgs() << Twine::utohexstr(First.To);
- dbgs() << " and ending in ";
- if (ToFunc)
- dbgs() << formatv("{0} @ {1:x}", *ToFunc,
- Second.From - ToFunc->getAddress());
- else
- dbgs() << Twine::utohexstr(Second.From);
- dbgs() << '\n';
- });
+ LLVM_DEBUG(dbgs() << "Out of range trace " << Trace << '\n');
NumLongRangeTraces += Count;
return false;
}
if (FromFunc != ToFunc) {
+ LLVM_DEBUG(dbgs() << "Invalid trace " << Trace << '\n');
NumInvalidTraces += Count;
- LLVM_DEBUG({
- dbgs() << "Invalid trace starting in " << FromFunc->getPrintName()
- << formatv(" @ {0:x}", First.To - FromFunc->getAddress())
- << " and ending in " << ToFunc->getPrintName()
- << formatv(" @ {0:x}\n", Second.From - ToFunc->getAddress());
- });
return false;
}
@@ -809,28 +808,21 @@ bool DataAggregator::doTrace(const LBREntry &First, const LBREntry &Second,
BinaryFunction *ParentFunc = getBATParentFunction(*FromFunc);
if (!ParentFunc)
ParentFunc = FromFunc;
- ParentFunc->SampleCountInBytes += Count * (Second.From - First.To);
+ ParentFunc->SampleCountInBytes += Count * (To - From);
const uint64_t FuncAddress = FromFunc->getAddress();
std::optional FTs =
BAT && BAT->isBATFunction(FuncAddress)
- ? BAT->getFallthroughsInTrace(FuncAddress, First.To, Second.From)
- : getFallthroughsInTrace(*FromFunc, First, Second, Count);
+ ? BAT->getFallthroughsInTrace(FuncAddress, From - IsReturn, To)
+ : getFallthroughsInTrace(*FromFunc, Trace, Count, IsReturn);
if (!FTs) {
- LLVM_DEBUG(
- dbgs() << "Invalid trace starting in " << FromFunc->getPrintName()
- << " @ " << Twine::utohexstr(First.To - FromFunc->getAddress())
- << " and ending in " << ToFunc->getPrintName() << " @ "
- << ToFunc->getPrintName() << " @ "
- << Twine::utohexstr(Second.From - ToFunc->getAddress()) << '\n');
+ LLVM_DEBUG(dbgs() << "Invalid trace " << Trace << '\n');
NumInvalidTraces += Count;
return false;
}
LLVM_DEBUG(dbgs() << "Processing " << FTs->size() << " fallthroughs for "
- << FromFunc->getPrintName() << ":"
- << Twine::utohexstr(First.To) << " to "
- << Twine::utohexstr(Second.From) << ".\n");
+ << FromFunc->getPrintName() << ":" << Trace << '\n');
for (auto [From, To] : *FTs) {
if (BAT) {
From = BAT->translate(FromFunc->getAddress(), From, /*IsBranchSrc=*/true);
@@ -843,17 +835,15 @@ bool DataAggregator::doTrace(const LBREntry &First, const LBREntry &Second,
}
std::optional, 16>>
-DataAggregator::getFallthroughsInTrace(BinaryFunction &BF,
- const LBREntry &FirstLBR,
- const LBREntry &SecondLBR,
- uint64_t Count) const {
+DataAggregator::getFallthroughsInTrace(BinaryFunction &BF, const Trace &Trace,
+ uint64_t Count, bool IsReturn) const {
SmallVector, 16> Branches;
BinaryContext &BC = BF.getBinaryContext();
// Offsets of the trace within this function.
- const uint64_t From = FirstLBR.To - BF.getAddress();
- const uint64_t To = SecondLBR.From - BF.getAddress();
+ const uint64_t From = Trace.From - BF.getAddress();
+ const uint64_t To = Trace.To - BF.getAddress();
if (From > To)
return std::nullopt;
@@ -880,8 +870,13 @@ DataAggregator::getFallthroughsInTrace(BinaryFunction &BF,
// Adjust FromBB if the first LBR is a return from the last instruction in
// the previous block (that instruction should be a call).
- if (From == FromBB->getOffset() && !BF.containsAddress(FirstLBR.From) &&
- !FromBB->isEntryPoint() && !FromBB->isLandingPad()) {
+ if (IsReturn) {
+ if (From)
+ FromBB = BF.getBasicBlockContainingOffset(From - 1);
+ else
+ LLVM_DEBUG(dbgs() << "return to the function start: " << Trace << '\n');
+ } else if (Trace.Branch == Trace::EXTERNAL && From == FromBB->getOffset() &&
+ !FromBB->isEntryPoint() && !FromBB->isLandingPad()) {
const BinaryBasicBlock *PrevBB =
BF.getLayout().getBlock(FromBB->getIndex() - 1);
if (PrevBB->getSuccessor(FromBB->getLabel())) {
@@ -889,10 +884,9 @@ DataAggregator::getFallthroughsInTrace(BinaryFunction &BF,
if (Instr && BC.MIB->isCall(*Instr))
FromBB = PrevBB;
else
- LLVM_DEBUG(dbgs() << "invalid incoming LBR (no call): " << FirstLBR
- << '\n');
+ LLVM_DEBUG(dbgs() << "invalid trace (no call): " << Trace << '\n');
} else {
- LLVM_DEBUG(dbgs() << "invalid incoming LBR: " << FirstLBR << '\n');
+ LLVM_DEBUG(dbgs() << "invalid trace: " << Trace << '\n');
}
}
@@ -911,9 +905,7 @@ DataAggregator::getFallthroughsInTrace(BinaryFunction &BF,
// Check for bad LBRs.
if (!BB->getSuccessor(NextBB->getLabel())) {
- LLVM_DEBUG(dbgs() << "no fall-through for the trace:\n"
- << " " << FirstLBR << '\n'
- << " " << SecondLBR << '\n');
+ LLVM_DEBUG(dbgs() << "no fall-through for the trace: " << Trace << '\n');
return std::nullopt;
}
@@ -1218,14 +1210,15 @@ std::error_code DataAggregator::parseAggregatedLBREntry() {
FT_EXTERNAL_ORIGIN // f
} Type = INVALID;
- // The number of fields to parse, set based on Type.
+ /// The number of fields to parse, set based on \p Type.
int AddrNum = 0;
int CounterNum = 0;
- // Storage for parsed fields.
+ /// Storage for parsed fields.
StringRef EventName;
std::optional Addr[3];
int64_t Counters[2] = {0};
+ /// Parse strings: record type and optionally an event name.
while (Type == INVALID || Type == EVENT_NAME) {
while (checkAndConsumeFS()) {
}
@@ -1259,6 +1252,7 @@ std::error_code DataAggregator::parseAggregatedLBREntry() {
CounterNum = SSI(Str).Case("B", 2).Case("E", 0).Default(1);
}
+ /// Parse locations depending on entry type, recording them in \p Addr array.
for (int I = 0; I < AddrNum; ++I) {
while (checkAndConsumeFS()) {
}
@@ -1268,6 +1262,7 @@ std::error_code DataAggregator::parseAggregatedLBREntry() {
Addr[I] = AddrOrErr.get();
}
+ /// Parse counters depending on entry type.
for (int I = 0; I < CounterNum; ++I) {
while (checkAndConsumeFS()) {
}
@@ -1278,11 +1273,13 @@ std::error_code DataAggregator::parseAggregatedLBREntry() {
Counters[I] = CountOrErr.get();
}
+ /// Expect end of line here.
if (!checkAndConsumeNewLine()) {
reportError("expected end of line");
return make_error_code(llvm::errc::io_error);
}
+ /// Record event name into \p EventNames and return.
if (Type == EVENT_NAME) {
EventNames.insert(EventName);
return std::error_code();
@@ -1296,6 +1293,7 @@ std::error_code DataAggregator::parseAggregatedLBREntry() {
int64_t Count = Counters[0];
int64_t Mispreds = Counters[1];
+ /// Record basic IP sample into \p BasicSamples and return.
if (Type == SAMPLE) {
BasicSamples[FromOffset] += Count;
NumTotalSamples += Count;
@@ -1307,30 +1305,26 @@ std::error_code DataAggregator::parseAggregatedLBREntry() {
if (ToFunc)
ToFunc->setHasProfileAvailable();
- Trace Trace(FromOffset, ToOffset);
- // Taken trace
- if (Type == TRACE || Type == BRANCH) {
- TakenBranchInfo &Info = BranchLBRs[Trace];
- Info.TakenCount += Count;
- Info.MispredCount += Mispreds;
-
- NumTotalSamples += Count;
- }
- // Construct fallthrough part of the trace
- if (Type == TRACE) {
- const uint64_t TraceFtEndOffset = Addr[2]->Offset;
- Trace.From = ToOffset;
- Trace.To = TraceFtEndOffset;
- Type = FromFunc == ToFunc ? FT : FT_EXTERNAL_ORIGIN;
+ /// For legacy fall-through types, adjust locations to match Trace container.
+ if (Type == FT || Type == FT_EXTERNAL_ORIGIN) {
+ Addr[2] = Location(Addr[1]->Offset); // Trace To
+ Addr[1] = Location(Addr[0]->Offset); // Trace From
+ // Put a magic value into Trace Branch to differentiate from a full trace.
+ Addr[0] = Location(Type == FT ? Trace::FT_ONLY : Trace::FT_EXTERNAL_ORIGIN);
}
- // Add fallthrough trace
- if (Type != BRANCH) {
- FTInfo &Info = FallthroughLBRs[Trace];
- (Type == FT ? Info.InternCount : Info.ExternCount) += Count;
- NumTraces += Count;
+ /// For legacy branch type, mark Trace To to differentite from a full trace.
+ if (Type == BRANCH) {
+ Addr[2] = Location(Trace::BR_ONLY);
}
+ /// Record a trace.
+ Trace T{Addr[0]->Offset, Addr[1]->Offset, Addr[2]->Offset};
+ TakenBranchInfo TI{(uint64_t)Count, (uint64_t)Mispreds};
+ Traces.emplace_back(T, TI);
+
+ NumTotalSamples += Count;
+
return std::error_code();
}
@@ -1341,7 +1335,7 @@ bool DataAggregator::ignoreKernelInterrupt(LBREntry &LBR) const {
std::error_code DataAggregator::printLBRHeatMap() {
outs() << "PERF2BOLT: parse branch events...\n";
- NamedRegionTimer T("parseBranch", "Parsing branch events", TimerGroupName,
+ NamedRegionTimer T("buildHeatmap", "Building heatmap", TimerGroupName,
TimerGroupDesc, opts::TimeAggregator);
if (BC->IsLinuxKernel) {
@@ -1377,12 +1371,9 @@ std::error_code DataAggregator::printLBRHeatMap() {
// Register basic samples and perf LBR addresses not covered by fallthroughs.
for (const auto &[PC, Hits] : BasicSamples)
HM.registerAddress(PC, Hits);
- for (const auto &LBR : FallthroughLBRs) {
- const Trace &Trace = LBR.first;
- const FTInfo &Info = LBR.second;
- HM.registerAddressRange(Trace.From, Trace.To,
- Info.InternCount + Info.ExternCount);
- }
+ for (const auto &[Trace, Info] : Traces)
+ if (Trace.To != Trace::BR_ONLY)
+ HM.registerAddressRange(Trace.From, Trace.To, Info.TakenCount);
if (HM.getNumInvalidRanges())
outs() << "HEATMAP: invalid traces: " << HM.getNumInvalidRanges() << '\n';
@@ -1428,22 +1419,10 @@ void DataAggregator::parseLBRSample(const PerfBranchSample &Sample,
// chronological order)
if (NeedsSkylakeFix && NumEntry <= 2)
continue;
- if (NextLBR) {
- // Record fall-through trace.
- const uint64_t TraceFrom = LBR.To;
- const uint64_t TraceTo = NextLBR->From;
- const BinaryFunction *TraceBF =
- getBinaryFunctionContainingAddress(TraceFrom);
- FTInfo &Info = FallthroughLBRs[Trace(TraceFrom, TraceTo)];
- if (TraceBF && TraceBF->containsAddress(LBR.From))
- ++Info.InternCount;
- else
- ++Info.ExternCount;
- ++NumTraces;
- }
+ uint64_t TraceTo = NextLBR ? NextLBR->From : Trace::BR_ONLY;
NextLBR = &LBR;
- TakenBranchInfo &Info = BranchLBRs[Trace(LBR.From, LBR.To)];
+ TakenBranchInfo &Info = TraceMap[Trace{LBR.From, LBR.To, TraceTo}];
++Info.TakenCount;
Info.MispredCount += LBR.Mispred;
}
@@ -1554,10 +1533,14 @@ std::error_code DataAggregator::parseBranchEvents() {
parseLBRSample(Sample, NeedsSkylakeFix);
}
- for (const Trace &Trace : llvm::make_first_range(BranchLBRs))
- for (const uint64_t Addr : {Trace.From, Trace.To})
+ Traces.reserve(TraceMap.size());
+ for (const auto &[Trace, Info] : TraceMap) {
+ Traces.emplace_back(Trace, Info);
+ for (const uint64_t Addr : {Trace.Branch, Trace.From})
if (BinaryFunction *BF = getBinaryFunctionContainingAddress(Addr))
BF->setHasProfileAvailable();
+ }
+ clear(TraceMap);
outs() << "PERF2BOLT: read " << NumSamples << " samples and " << NumEntries
<< " LBR entries\n";
@@ -1582,23 +1565,14 @@ void DataAggregator::processBranchEvents() {
NamedRegionTimer T("processBranch", "Processing branch events",
TimerGroupName, TimerGroupDesc, opts::TimeAggregator);
- for (const auto &AggrLBR : FallthroughLBRs) {
- const Trace &Loc = AggrLBR.first;
- const FTInfo &Info = AggrLBR.second;
- LBREntry First{Loc.From, Loc.From, false};
- LBREntry Second{Loc.To, Loc.To, false};
- if (Info.InternCount)
- doTrace(First, Second, Info.InternCount);
- if (Info.ExternCount) {
- First.From = 0;
- doTrace(First, Second, Info.ExternCount);
- }
- }
-
- for (const auto &AggrLBR : BranchLBRs) {
- const Trace &Loc = AggrLBR.first;
- const TakenBranchInfo &Info = AggrLBR.second;
- doBranch(Loc.From, Loc.To, Info.TakenCount, Info.MispredCount);
+ for (const auto &[Trace, Info] : Traces) {
+ bool IsReturn = checkReturn(Trace.Branch);
+ // Ignore returns.
+ if (!IsReturn && Trace.Branch != Trace::FT_ONLY &&
+ Trace.Branch != Trace::FT_EXTERNAL_ORIGIN)
+ doBranch(Trace.Branch, Trace.From, Info.TakenCount, Info.MispredCount);
+ if (Trace.To != Trace::BR_ONLY)
+ doTrace(Trace, Info.TakenCount, IsReturn);
}
printBranchSamplesDiagnostics();
}
@@ -2255,6 +2229,7 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC,
YamlBF.Id = BF->getFunctionNumber();
YamlBF.Hash = BAT->getBFHash(FuncAddress);
YamlBF.ExecCount = BF->getKnownExecutionCount();
+ YamlBF.ExternEntryCount = BF->getExternEntryCount();
YamlBF.NumBasicBlocks = BAT->getNumBasicBlocks(FuncAddress);
const BoltAddressTranslation::BBHashMapTy &BlockMap =
BAT->getBBHashMap(FuncAddress);
diff --git a/bolt/lib/Profile/DataReader.cpp b/bolt/lib/Profile/DataReader.cpp
index c512394f26a3b..afe24216d7f5d 100644
--- a/bolt/lib/Profile/DataReader.cpp
+++ b/bolt/lib/Profile/DataReader.cpp
@@ -85,6 +85,7 @@ void FuncBranchData::appendFrom(const FuncBranchData &FBD, uint64_t Offset) {
}
llvm::stable_sort(Data);
ExecutionCount += FBD.ExecutionCount;
+ ExternEntryCount += FBD.ExternEntryCount;
for (auto I = FBD.EntryData.begin(), E = FBD.EntryData.end(); I != E; ++I) {
assert(I->To.Name == FBD.Name);
auto NewElmt = EntryData.insert(EntryData.end(), *I);
@@ -269,6 +270,7 @@ Error DataReader::preprocessProfile(BinaryContext &BC) {
if (FuncBranchData *FuncData = getBranchDataForNames(Function.getNames())) {
setBranchData(Function, FuncData);
Function.ExecutionCount = FuncData->ExecutionCount;
+ Function.ExternEntryCount = FuncData->ExternEntryCount;
FuncData->Used = true;
}
}
@@ -419,6 +421,7 @@ void DataReader::matchProfileData(BinaryFunction &BF) {
if (fetchProfileForOtherEntryPoints(BF)) {
BF.ProfileMatchRatio = evaluateProfileData(BF, *FBD);
BF.ExecutionCount = FBD->ExecutionCount;
+ BF.ExternEntryCount = FBD->ExternEntryCount;
BF.RawSampleCount = FBD->getNumExecutedBranches();
}
return;
@@ -449,6 +452,7 @@ void DataReader::matchProfileData(BinaryFunction &BF) {
setBranchData(BF, NewBranchData);
NewBranchData->Used = true;
BF.ExecutionCount = NewBranchData->ExecutionCount;
+ BF.ExternEntryCount = NewBranchData->ExternEntryCount;
BF.ProfileMatchRatio = 1.0f;
break;
}
@@ -1190,6 +1194,8 @@ std::error_code DataReader::parse() {
if (BI.To.IsSymbol && BI.To.Offset == 0) {
I = GetOrCreateFuncEntry(BI.To.Name);
I->second.ExecutionCount += BI.Branches;
+ if (!BI.From.IsSymbol)
+ I->second.ExternEntryCount += BI.Branches;
}
}
diff --git a/bolt/lib/Profile/YAMLProfileReader.cpp b/bolt/lib/Profile/YAMLProfileReader.cpp
index 33ce40ac2eeec..086e47b661e10 100644
--- a/bolt/lib/Profile/YAMLProfileReader.cpp
+++ b/bolt/lib/Profile/YAMLProfileReader.cpp
@@ -176,6 +176,7 @@ bool YAMLProfileReader::parseFunctionProfile(
uint64_t FunctionExecutionCount = 0;
BF.setExecutionCount(YamlBF.ExecCount);
+ BF.setExternEntryCount(YamlBF.ExternEntryCount);
uint64_t FuncRawBranchCount = 0;
for (const yaml::bolt::BinaryBasicBlockProfile &YamlBB : YamlBF.Blocks)
diff --git a/bolt/lib/Profile/YAMLProfileWriter.cpp b/bolt/lib/Profile/YAMLProfileWriter.cpp
index 0ae67a4d35595..1632aa1c6bfe2 100644
--- a/bolt/lib/Profile/YAMLProfileWriter.cpp
+++ b/bolt/lib/Profile/YAMLProfileWriter.cpp
@@ -226,6 +226,7 @@ YAMLProfileWriter::convert(const BinaryFunction &BF, bool UseDFS,
YamlBF.Hash = BF.getHash();
YamlBF.NumBasicBlocks = BF.size();
YamlBF.ExecCount = BF.getKnownExecutionCount();
+ YamlBF.ExternEntryCount = BF.getExternEntryCount();
DenseMap InlineTreeNodeId;
if (PseudoProbeDecoder && BF.getGUID()) {
std::tie(YamlBF.InlineTree, InlineTreeNodeId) =
diff --git a/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp b/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp
index 18be125d53aeb..c7d664ab09d46 100644
--- a/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp
+++ b/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp
@@ -10,7 +10,7 @@
//
//===----------------------------------------------------------------------===//
-#include "MCTargetDesc/RISCVMCExpr.h"
+#include "MCTargetDesc/RISCVMCAsmInfo.h"
#include "MCTargetDesc/RISCVMCTargetDesc.h"
#include "bolt/Core/MCPlusBuilder.h"
#include "llvm/BinaryFormat/ELF.h"
@@ -33,8 +33,8 @@ class RISCVMCPlusBuilder : public MCPlusBuilder {
bool equals(const MCSpecifierExpr &A, const MCSpecifierExpr &B,
CompFuncTy Comp) const override {
- const auto &RISCVExprA = cast(A);
- const auto &RISCVExprB = cast(B);
+ const auto &RISCVExprA = cast(A);
+ const auto &RISCVExprB = cast(B);
if (RISCVExprA.getSpecifier() != RISCVExprB.getSpecifier())
return false;
@@ -245,7 +245,7 @@ class RISCVMCPlusBuilder : public MCPlusBuilder {
MCContext *Ctx) {
Inst.setOpcode(Opcode);
Inst.clear();
- Inst.addOperand(MCOperand::createExpr(RISCVMCExpr::create(
+ Inst.addOperand(MCOperand::createExpr(MCSpecifierExpr::create(
MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx),
ELF::R_RISCV_CALL_PLT, *Ctx)));
}
@@ -342,7 +342,7 @@ class RISCVMCPlusBuilder : public MCPlusBuilder {
}
const MCSymbol *getTargetSymbol(const MCExpr *Expr) const override {
- auto *RISCVExpr = dyn_cast(Expr);
+ auto *RISCVExpr = dyn_cast(Expr);
if (RISCVExpr && RISCVExpr->getSubExpr())
return getTargetSymbol(RISCVExpr->getSubExpr());
@@ -435,19 +435,19 @@ class RISCVMCPlusBuilder : public MCPlusBuilder {
case ELF::R_RISCV_TLS_GD_HI20:
// The GOT is reused so no need to create GOT relocations
case ELF::R_RISCV_PCREL_HI20:
- return RISCVMCExpr::create(Expr, ELF::R_RISCV_PCREL_HI20, Ctx);
+ return MCSpecifierExpr::create(Expr, ELF::R_RISCV_PCREL_HI20, Ctx);
case ELF::R_RISCV_PCREL_LO12_I:
case ELF::R_RISCV_PCREL_LO12_S:
- return RISCVMCExpr::create(Expr, RISCVMCExpr::VK_PCREL_LO, Ctx);
+ return MCSpecifierExpr::create(Expr, RISCV::S_PCREL_LO, Ctx);
case ELF::R_RISCV_HI20:
- return RISCVMCExpr::create(Expr, ELF::R_RISCV_HI20, Ctx);
+ return MCSpecifierExpr::create(Expr, ELF::R_RISCV_HI20, Ctx);
case ELF::R_RISCV_LO12_I:
case ELF::R_RISCV_LO12_S:
- return RISCVMCExpr::create(Expr, RISCVMCExpr::VK_LO, Ctx);
+ return MCSpecifierExpr::create(Expr, RISCV::S_LO, Ctx);
case ELF::R_RISCV_CALL:
- return RISCVMCExpr::create(Expr, ELF::R_RISCV_CALL_PLT, Ctx);
+ return MCSpecifierExpr::create(Expr, ELF::R_RISCV_CALL_PLT, Ctx);
case ELF::R_RISCV_CALL_PLT:
- return RISCVMCExpr::create(Expr, ELF::R_RISCV_CALL_PLT, Ctx);
+ return MCSpecifierExpr::create(Expr, ELF::R_RISCV_CALL_PLT, Ctx);
}
}
@@ -466,10 +466,10 @@ class RISCVMCPlusBuilder : public MCPlusBuilder {
return false;
const auto *ImmExpr = ImmOp.getExpr();
- if (!isa(ImmExpr))
+ if (!isa(ImmExpr))
return false;
- switch (cast(ImmExpr)->getSpecifier()) {
+ switch (cast(ImmExpr)->getSpecifier()) {
default:
return false;
case ELF::R_RISCV_CALL_PLT:
diff --git a/bolt/lib/Utils/CMakeLists.txt b/bolt/lib/Utils/CMakeLists.txt
index efba6d54449d3..94933644ef5ef 100644
--- a/bolt/lib/Utils/CMakeLists.txt
+++ b/bolt/lib/Utils/CMakeLists.txt
@@ -6,12 +6,25 @@ set(version_inc "${CMAKE_CURRENT_BINARY_DIR}/VCSVersion.inc")
set(generate_vcs_version_script "${LLVM_CMAKE_DIR}/GenerateVersionFromVCS.cmake")
+if(llvm_vc AND LLVM_APPEND_VC_REV)
+ set(llvm_source_dir ${LLVM_MAIN_SRC_DIR})
+endif()
+if(LLVM_VC_REPOSITORY AND LLVM_VC_REVISION)
+ set(llvm_source_dir ${LLVM_SOURCE_DIR})
+ set(llvm_vc_repository ${LLVM_VC_REPOSITORY})
+ set(llvm_vc_revision ${LLVM_VC_REVISION})
+endif()
+if(bolt_vc AND LLVM_APPEND_VC_REV)
+ set(bolt_source_dir ${BOLT_SOURCE_DIR})
+endif()
+
# Create custom target to generate the VC revision include.
add_custom_command(OUTPUT "${version_inc}"
DEPENDS "${llvm_vc}" "${bolt_vc}" "${generate_vcs_version_script}"
COMMAND ${CMAKE_COMMAND} "-DNAMES=BOLT"
+ "-DLLVM_SOURCE_DIR=${llvm_source_dir}"
+ "-DBOLT_SOURCE_DIR=${bolt_source_dir}"
"-DHEADER_FILE=${version_inc}"
- "-DBOLT_SOURCE_DIR=${BOLT_SOURCE_DIR}"
"-DLLVM_VC_REPOSITORY=${llvm_vc_repository}"
"-DLLVM_VC_REVISION=${llvm_vc_revision}"
"-DLLVM_FORCE_VC_REVISION=${LLVM_FORCE_VC_REVISION}"
diff --git a/bolt/test/AArch64/adr-relaxation.s b/bolt/test/AArch64/adr-relaxation.s
index a643a62339ba3..864650c3287d8 100644
--- a/bolt/test/AArch64/adr-relaxation.s
+++ b/bolt/test/AArch64/adr-relaxation.s
@@ -34,7 +34,6 @@ foo:
.cfi_startproc
cmp x1, x11
b.hi .L2
- mov x0, #0x0
.L2:
# CHECK-FOO: :
# CHECK-FOO-NEXT: adrp
diff --git a/bolt/test/X86/callcont-fallthru.s b/bolt/test/X86/callcont-fallthru.s
index 4994cfb541eef..c2ef024db9475 100644
--- a/bolt/test/X86/callcont-fallthru.s
+++ b/bolt/test/X86/callcont-fallthru.s
@@ -4,29 +4,43 @@
# RUN: %clang %cflags -fpic -shared -xc /dev/null -o %t.so
## Link against a DSO to ensure PLT entries.
# RUN: %clangxx %cxxflags %s %t.so -o %t -Wl,-q -nostdlib
-# RUN: link_fdata %s %t %t.pat PREAGGT1
-# RUN: link_fdata %s %t %t.pat2 PREAGGT2
-# RUN-DISABLED: link_fdata %s %t %t.patplt PREAGGPLT
+# Trace to a call continuation, not a landing pad/entry point
+# RUN: link_fdata %s %t %t.pa-base PREAGG-BASE
+# Trace from a return to a landing pad/entry point call continuation
+# RUN: link_fdata %s %t %t.pa-ret PREAGG-RET
+# Trace from an external location to a landing pad/entry point call continuation
+# RUN: link_fdata %s %t %t.pa-ext PREAGG-EXT
+# RUN-DISABLED: link_fdata %s %t %t.pa-plt PREAGG-PLT
# RUN: llvm-strip --strip-unneeded %t -o %t.strip
# RUN: llvm-objcopy --remove-section=.eh_frame %t.strip %t.noeh
## Check pre-aggregated traces attach call continuation fallthrough count
-# RUN: llvm-bolt %t.noeh --pa -p %t.pat -o %t.out \
-# RUN: --print-cfg --print-only=main | FileCheck %s
-
-## Check pre-aggregated traces don't attach call continuation fallthrough count
-## to secondary entry point (unstripped)
-# RUN: llvm-bolt %t --pa -p %t.pat2 -o %t.out \
-# RUN: --print-cfg --print-only=main | FileCheck %s --check-prefix=CHECK3
-## Check pre-aggregated traces don't attach call continuation fallthrough count
-## to landing pad (stripped, LP)
-# RUN: llvm-bolt %t.strip --pa -p %t.pat2 -o %t.out \
-# RUN: --print-cfg --print-only=main | FileCheck %s --check-prefix=CHECK3
+## in the basic case (not an entry point, not a landing pad).
+# RUN: llvm-bolt %t.noeh --pa -p %t.pa-base -o %t.out \
+# RUN: --print-cfg --print-only=main | FileCheck %s --check-prefix=CHECK-BASE
+
+## Check pre-aggregated traces from a return attach call continuation
+## fallthrough count to secondary entry point (unstripped)
+# RUN: llvm-bolt %t --pa -p %t.pa-ret -o %t.out \
+# RUN: --print-cfg --print-only=main | FileCheck %s --check-prefix=CHECK-ATTACH
+## Check pre-aggregated traces from a return attach call continuation
+## fallthrough count to landing pad (stripped, landing pad)
+# RUN: llvm-bolt %t.strip --pa -p %t.pa-ret -o %t.out \
+# RUN: --print-cfg --print-only=main | FileCheck %s --check-prefix=CHECK-ATTACH
+
+## Check pre-aggregated traces from external location don't attach call
+## continuation fallthrough count to secondary entry point (unstripped)
+# RUN: llvm-bolt %t --pa -p %t.pa-ext -o %t.out \
+# RUN: --print-cfg --print-only=main | FileCheck %s --check-prefix=CHECK-SKIP
+## Check pre-aggregated traces from external location don't attach call
+## continuation fallthrough count to landing pad (stripped, landing pad)
+# RUN: llvm-bolt %t.strip --pa -p %t.pa-ext -o %t.out \
+# RUN: --print-cfg --print-only=main | FileCheck %s --check-prefix=CHECK-SKIP
## Check pre-aggregated traces don't report zero-sized PLT fall-through as
## invalid trace
-# RUN-DISABLED: llvm-bolt %t.strip --pa -p %t.patplt -o %t.out | FileCheck %s \
+# RUN-DISABLED: llvm-bolt %t.strip --pa -p %t.pa-plt -o %t.out | FileCheck %s \
# RUN-DISABLED: --check-prefix=CHECK-PLT
# CHECK-PLT: traces mismatching disassembled function contents: 0
@@ -56,11 +70,11 @@ main:
Ltmp0_br:
callq puts@PLT
## Check PLT traces are accepted
-# PREAGGPLT: T #Ltmp0_br# #puts@plt# #puts@plt# 3
+# PREAGG-PLT: T #Ltmp0_br# #puts@plt# #puts@plt# 3
## Target is an external-origin call continuation
-# PREAGGT1: T X:0 #Ltmp1# #Ltmp4_br# 2
-# CHECK: callq puts@PLT
-# CHECK-NEXT: count: 2
+# PREAGG-BASE: T X:0 #Ltmp1# #Ltmp4_br# 2
+# CHECK-BASE: callq puts@PLT
+# CHECK-BASE-NEXT: count: 2
Ltmp1:
movq -0x10(%rbp), %rax
@@ -71,24 +85,18 @@ Ltmp4:
cmpl $0x0, -0x14(%rbp)
Ltmp4_br:
je Ltmp0
-# CHECK2: je .Ltmp0
-# CHECK2-NEXT: count: 3
movl $0xa, -0x18(%rbp)
callq foo
## Target is a binary-local call continuation
-# PREAGGT1: T #Lfoo_ret# #Ltmp3# #Ltmp3_br# 1
-# CHECK: callq foo
-# CHECK-NEXT: count: 1
-
-## PLT call continuation fallthrough spanning the call
-# CHECK2: callq foo
-# CHECK2-NEXT: count: 3
-
+# PREAGG-RET: T #Lfoo_ret# #Ltmp3# #Ltmp3_br# 1
## Target is a secondary entry point (unstripped) or a landing pad (stripped)
-# PREAGGT2: T X:0 #Ltmp3# #Ltmp3_br# 2
-# CHECK3: callq foo
-# CHECK3-NEXT: count: 0
+# PREAGG-EXT: T X:0 #Ltmp3# #Ltmp3_br# 1
+
+# CHECK-ATTACH: callq foo
+# CHECK-ATTACH-NEXT: count: 1
+# CHECK-SKIP: callq foo
+# CHECK-SKIP-NEXT: count: 0
Ltmp3:
cmpl $0x0, -0x18(%rbp)
diff --git a/bolt/test/X86/shrinkwrapping.test b/bolt/test/X86/shrinkwrapping.test
index 8581d7e0c0f7b..521b4561b3ba6 100644
--- a/bolt/test/X86/shrinkwrapping.test
+++ b/bolt/test/X86/shrinkwrapping.test
@@ -8,6 +8,7 @@ REQUIRES: shell
RUN: %clangxx %cxxflags -no-pie %S/Inputs/exc4sw.S -o %t.exe -Wl,-q
RUN: llvm-bolt %t.exe -o %t --relocs --frame-opt=all \
+RUN: --print-only=main --print-cfg \
RUN: --data=%p/Inputs/exc4sw.fdata --reorder-blocks=cache 2>&1 | \
RUN: FileCheck %s --check-prefix=CHECK-BOLT
@@ -19,6 +20,7 @@ RUN: llvm-objdump --dwarf=frames %t | grep -A20 -e \
RUN: `llvm-nm --numeric-sort %t | grep main | tail -n 1 | cut -f1 -d' ' | \
RUN: tail -c9` 2>&1 | FileCheck %s --check-prefix=CHECK-OUTPUT
+CHECK-BOLT: Extern Entry Count: 100
CHECK-BOLT: Shrink wrapping moved 2 spills inserting load/stores and 0 spills inserting push/pops
CHECK-INPUT: DW_CFA_advance_loc: 2
diff --git a/bolt/test/lit.local.cfg b/bolt/test/lit.local.cfg
index d5a6849b27a77..8a61d11f5825f 100644
--- a/bolt/test/lit.local.cfg
+++ b/bolt/test/lit.local.cfg
@@ -1,6 +1,11 @@
-host_linux_triple = config.target_triple.split("-")[0] + "-unknown-linux-gnu"
+host_triple = config.target_triple
+
+# Force triple on non-linux hosts to get ELF binaries on all platforms.
+if not "linux" in host_triple:
+ host_triple = host_triple.split("-")[0] + "-unknown-linux-gnu"
+
common_linker_flags = "-fuse-ld=lld -Wl,--unresolved-symbols=ignore-all -Wl,--build-id=none -pie"
-flags = f"--target={host_linux_triple} -fPIE {common_linker_flags}"
+flags = f"--target={host_triple} -fPIE {common_linker_flags}"
config.substitutions.insert(0, ("%cflags", f"%cflags {flags}"))
config.substitutions.insert(0, ("%cxxflags", f"%cxxflags {flags}"))
diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp
index 57dd514b90a2b..35058abab0663 100644
--- a/clang-tools-extra/clang-doc/BitcodeReader.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp
@@ -54,10 +54,8 @@ static llvm::Error decodeRecord(const Record &R, AccessSpecifier &Field,
case AS_none:
Field = (AccessSpecifier)R[0];
return llvm::Error::success();
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "invalid value for AccessSpecifier");
}
+ llvm_unreachable("invalid value for AccessSpecifier");
}
static llvm::Error decodeRecord(const Record &R, TagTypeKind &Field,
diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.cpp b/clang-tools-extra/clang-doc/BitcodeWriter.cpp
index 708ce09d9e5b2..f8a6859169b01 100644
--- a/clang-tools-extra/clang-doc/BitcodeWriter.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeWriter.cpp
@@ -664,7 +664,7 @@ bool ClangDocBitcodeWriter::dispatchInfoForWrite(Info *I) {
case InfoType::IT_typedef:
emitBlock(*static_cast(I));
break;
- default:
+ case InfoType::IT_default:
llvm::errs() << "Unexpected info, unable to write.\n";
return true;
}
diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp
index 3ce930c6965db..71a926f1c73e0 100644
--- a/clang-tools-extra/clang-doc/Representation.cpp
+++ b/clang-tools-extra/clang-doc/Representation.cpp
@@ -143,10 +143,11 @@ mergeInfos(std::vector> &Values) {
return reduce(Values);
case InfoType::IT_typedef:
return reduce(Values);
- default:
+ case InfoType::IT_default:
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"unexpected info type");
}
+ llvm_unreachable("unhandled enumerator");
}
bool CommentInfo::operator==(const CommentInfo &Other) const {
diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp
index 3cda38115ff7f..820e8bfd8e644 100644
--- a/clang-tools-extra/clang-doc/Serialize.cpp
+++ b/clang-tools-extra/clang-doc/Serialize.cpp
@@ -388,9 +388,11 @@ std::string serialize(std::unique_ptr &I) {
return serialize(*static_cast(I.get()));
case InfoType::IT_function:
return serialize(*static_cast(I.get()));
- default:
+ case InfoType::IT_typedef:
+ case InfoType::IT_default:
return "";
}
+ llvm_unreachable("unhandled enumerator");
}
static void parseFullComment(const FullComment *C, CommentInfo &CI) {
@@ -525,9 +527,13 @@ static std::unique_ptr makeAndInsertIntoParent(ChildType Child) {
InsertChild(ParentRec->Children, std::forward(Child));
return ParentRec;
}
- default:
- llvm_unreachable("Invalid reference type for parent namespace");
+ case InfoType::IT_default:
+ case InfoType::IT_enum:
+ case InfoType::IT_function:
+ case InfoType::IT_typedef:
+ break;
}
+ llvm_unreachable("Invalid reference type for parent namespace");
}
// There are two uses for this function.
diff --git a/clang-tools-extra/clang-reorder-fields/ReorderFieldsAction.cpp b/clang-tools-extra/clang-reorder-fields/ReorderFieldsAction.cpp
index ea0207619fb2b..3b1cd18d80346 100644
--- a/clang-tools-extra/clang-reorder-fields/ReorderFieldsAction.cpp
+++ b/clang-tools-extra/clang-reorder-fields/ReorderFieldsAction.cpp
@@ -86,6 +86,10 @@ getNewFieldsOrder(const RecordDecl *Definition,
static void
addReplacement(SourceRange Old, SourceRange New, const ASTContext &Context,
std::map &Replacements) {
+ if (Old.getBegin().isMacroID())
+ Old = Context.getSourceManager().getExpansionRange(Old).getAsRange();
+ if (New.getBegin().isMacroID())
+ New = Context.getSourceManager().getExpansionRange(New).getAsRange();
StringRef NewText =
Lexer::getSourceText(CharSourceRange::getTokenRange(New),
Context.getSourceManager(), Context.getLangOpts());
diff --git a/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp
index bedecb60569e8..203170d55f694 100644
--- a/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp
@@ -702,17 +702,16 @@ void NotNullTerminatedResultCheck::registerMatchers(MatchFinder *Finder) {
return hasArgument(
CC.LengthPos,
allOf(
- anyOf(
- ignoringImpCasts(integerLiteral().bind(WrongLengthExprName)),
- allOf(unless(hasDefinition(SizeOfCharExpr)),
- allOf(CC.WithIncrease
- ? ignoringImpCasts(hasDefinition(HasIncOp))
- : ignoringImpCasts(allOf(
- unless(hasDefinition(HasIncOp)),
- anyOf(hasDefinition(binaryOperator().bind(
- UnknownLengthName)),
- hasDefinition(anything())))),
- AnyOfWrongLengthInit))),
+ anyOf(ignoringImpCasts(integerLiteral().bind(WrongLengthExprName)),
+ allOf(unless(hasDefinition(SizeOfCharExpr)),
+ allOf(CC.WithIncrease
+ ? ignoringImpCasts(hasDefinition(HasIncOp))
+ : ignoringImpCasts(
+ allOf(unless(hasDefinition(HasIncOp)),
+ hasDefinition(optionally(
+ binaryOperator().bind(
+ UnknownLengthName))))),
+ AnyOfWrongLengthInit))),
expr().bind(LengthExprName)));
};
diff --git a/clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp b/clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
index 2b2acfdf5b08e..ed39568ea554a 100644
--- a/clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
+++ b/clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
@@ -24,14 +24,12 @@ void ExceptionBaseclassCheck::registerMatchers(MatchFinder *Finder) {
isSameOrDerivedFrom(hasName("::std::exception")))))))))),
// This condition is always true, but will bind to the
// template value if the thrown type is templated.
- anyOf(has(expr(
- hasType(substTemplateTypeParmType().bind("templ_type")))),
- anything()),
+ optionally(has(
+ expr(hasType(substTemplateTypeParmType().bind("templ_type"))))),
// Bind to the declaration of the type of the value that
- // is thrown. 'anything()' is necessary to always succeed
- // in the 'eachOf' because builtin types are not
- // 'namedDecl'.
- eachOf(has(expr(hasType(namedDecl().bind("decl")))), anything()))
+ // is thrown. 'optionally' is necessary because builtin types
+ // are not 'namedDecl'.
+ optionally(has(expr(hasType(namedDecl().bind("decl"))))))
.bind("bad_throw"),
this);
}
diff --git a/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp b/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp
index faff1c17fc61e..37fbd8c0d725f 100644
--- a/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp
@@ -38,8 +38,7 @@ void StaticAssertCheck::registerMatchers(MatchFinder *Finder) {
binaryOperator(
hasAnyOperatorName("&&", "=="),
hasEitherOperand(ignoringImpCasts(stringLiteral().bind("assertMSG"))),
- anyOf(binaryOperator(hasEitherOperand(IsAlwaysFalseWithCast)),
- anything()))
+ optionally(binaryOperator(hasEitherOperand(IsAlwaysFalseWithCast))))
.bind("assertExprRoot"),
IsAlwaysFalse);
auto NonConstexprFunctionCall =
@@ -52,12 +51,10 @@ void StaticAssertCheck::registerMatchers(MatchFinder *Finder) {
auto NonConstexprCode =
expr(anyOf(NonConstexprFunctionCall, NonConstexprVariableReference));
auto AssertCondition =
- expr(
- anyOf(expr(ignoringParenCasts(anyOf(
- AssertExprRoot, unaryOperator(hasUnaryOperand(
- ignoringParenCasts(AssertExprRoot)))))),
- anything()),
- unless(NonConstexprCode), unless(hasDescendant(NonConstexprCode)))
+ expr(optionally(expr(ignoringParenCasts(anyOf(
+ AssertExprRoot, unaryOperator(hasUnaryOperand(
+ ignoringParenCasts(AssertExprRoot))))))),
+ unless(NonConstexprCode), unless(hasDescendant(NonConstexprCode)))
.bind("condition");
auto Condition =
anyOf(ignoringParenImpCasts(callExpr(
diff --git a/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.cpp
index c8e6bf47bb82f..339462093a6d6 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.cpp
@@ -26,13 +26,12 @@ void UseBoolLiteralsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
void UseBoolLiteralsCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
- traverse(
- TK_AsIs,
- implicitCastExpr(
- has(ignoringParenImpCasts(integerLiteral().bind("literal"))),
- hasImplicitDestinationType(qualType(booleanType())),
- unless(isInTemplateInstantiation()),
- anyOf(hasParent(explicitCastExpr().bind("cast")), anything()))),
+ traverse(TK_AsIs,
+ implicitCastExpr(
+ has(ignoringParenImpCasts(integerLiteral().bind("literal"))),
+ hasImplicitDestinationType(qualType(booleanType())),
+ unless(isInTemplateInstantiation()),
+ optionally(hasParent(explicitCastExpr().bind("cast"))))),
this);
Finder->addMatcher(
diff --git a/clang-tools-extra/clang-tidy/modernize/UseIntegerSignComparisonCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseIntegerSignComparisonCheck.cpp
index c02c5dfa8756d..eeba5cce80da5 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseIntegerSignComparisonCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseIntegerSignComparisonCheck.cpp
@@ -39,28 +39,21 @@ intCastExpression(bool IsSigned,
// std::cmp_{} functions trigger a compile-time error if either LHS or RHS
// is a non-integer type, char, enum or bool
// (unsigned char/ signed char are Ok and can be used).
- const auto HasIntegerType = hasType(hasCanonicalType(qualType(
+ auto IntTypeExpr = expr(hasType(hasCanonicalType(qualType(
isInteger(), IsSigned ? isSignedInteger() : isUnsignedInteger(),
- unless(isActualChar()), unless(booleanType()), unless(enumType()))));
-
- const auto IntTypeExpr = expr(HasIntegerType);
+ unless(isActualChar()), unless(booleanType()), unless(enumType())))));
const auto ImplicitCastExpr =
CastBindName.empty() ? implicitCastExpr(hasSourceExpression(IntTypeExpr))
: implicitCastExpr(hasSourceExpression(IntTypeExpr))
.bind(CastBindName);
- const auto ExplicitCastExpr =
- anyOf(explicitCastExpr(has(ImplicitCastExpr)),
- ignoringImpCasts(explicitCastExpr(has(ImplicitCastExpr))));
-
- // Match function calls or variable references not directly wrapped by an
- // implicit cast
- const auto CallIntExpr = CastBindName.empty()
- ? callExpr(HasIntegerType)
- : callExpr(HasIntegerType).bind(CastBindName);
+ const auto CStyleCastExpr = cStyleCastExpr(has(ImplicitCastExpr));
+ const auto StaticCastExpr = cxxStaticCastExpr(has(ImplicitCastExpr));
+ const auto FunctionalCastExpr = cxxFunctionalCastExpr(has(ImplicitCastExpr));
- return expr(anyOf(ImplicitCastExpr, ExplicitCastExpr, CallIntExpr));
+ return expr(anyOf(ImplicitCastExpr, CStyleCastExpr, StaticCastExpr,
+ FunctionalCastExpr));
}
static StringRef parseOpCode(BinaryOperator::Opcode Code) {
diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
index a877f9a7ee912..d89c3a69fc841 100644
--- a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -50,7 +50,8 @@ UnnecessaryValueParamCheck::UnnecessaryValueParamCheck(
utils::IncludeSorter::IS_LLVM),
areDiagsSelfContained()),
AllowedTypes(
- utils::options::parseStringList(Options.get("AllowedTypes", ""))) {}
+ utils::options::parseStringList(Options.get("AllowedTypes", ""))),
+ IgnoreCoroutines(Options.get("IgnoreCoroutines", true)) {}
void UnnecessaryValueParamCheck::registerMatchers(MatchFinder *Finder) {
const auto ExpensiveValueParamDecl = parmVarDecl(
@@ -61,12 +62,14 @@ void UnnecessaryValueParamCheck::registerMatchers(MatchFinder *Finder) {
matchers::matchesAnyListedName(AllowedTypes))))))),
decl().bind("param"));
Finder->addMatcher(
- traverse(
- TK_AsIs,
- functionDecl(hasBody(stmt()), isDefinition(), unless(isImplicit()),
- unless(cxxMethodDecl(anyOf(isOverride(), isFinal()))),
- has(typeLoc(forEach(ExpensiveValueParamDecl))),
- decl().bind("functionDecl"))),
+ traverse(TK_AsIs,
+ functionDecl(
+ hasBody(IgnoreCoroutines ? stmt(unless(coroutineBodyStmt()))
+ : stmt()),
+ isDefinition(), unless(isImplicit()),
+ unless(cxxMethodDecl(anyOf(isOverride(), isFinal()))),
+ has(typeLoc(forEach(ExpensiveValueParamDecl))),
+ decl().bind("functionDecl"))),
this);
}
@@ -123,6 +126,7 @@ void UnnecessaryValueParamCheck::storeOptions(
Options.store(Opts, "IncludeStyle", Inserter.getStyle());
Options.store(Opts, "AllowedTypes",
utils::options::serializeStringList(AllowedTypes));
+ Options.store(Opts, "IgnoreCoroutines", IgnoreCoroutines);
}
void UnnecessaryValueParamCheck::onEndOfTranslationUnit() {
diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.h b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.h
index 8bfd814d16357..b52043416e769 100644
--- a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.h
+++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.h
@@ -46,6 +46,7 @@ class UnnecessaryValueParamCheck : public ClangTidyCheck {
ExprMutationAnalyzer::Memoized MutationAnalyzerCache;
utils::IncludeInserter Inserter;
const std::vector AllowedTypes;
+ bool IgnoreCoroutines;
};
} // namespace clang::tidy::performance
diff --git a/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp b/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp
index f9fd1d903e231..20c73299915a9 100644
--- a/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp
@@ -348,8 +348,8 @@ void ImplicitBoolConversionCheck::registerMatchers(MatchFinder *Finder) {
implicitCastExpr().bind("implicitCastFromBool"),
unless(hasParent(BitfieldConstruct)),
// Check also for nested casts, for example: bool -> int -> float.
- anyOf(hasParent(implicitCastExpr().bind("furtherImplicitCast")),
- anything()),
+ optionally(
+ hasParent(implicitCastExpr().bind("furtherImplicitCast"))),
unless(isInTemplateInstantiation()),
unless(IsInCompilerGeneratedFunction))),
this);
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index 29321f7cd3fa2..a703009e2b467 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -494,9 +494,9 @@ static std::vector semanticTokenModifiers() {
void ClangdLSPServer::onInitialize(const InitializeParams &Params,
Callback Reply) {
// Determine character encoding first as it affects constructed ClangdServer.
- if (Params.capabilities.offsetEncoding && !Opts.Encoding) {
+ if (Params.capabilities.PositionEncodings && !Opts.Encoding) {
Opts.Encoding = OffsetEncoding::UTF16; // fallback
- for (OffsetEncoding Supported : *Params.capabilities.offsetEncoding)
+ for (OffsetEncoding Supported : *Params.capabilities.PositionEncodings)
if (Supported != OffsetEncoding::UnsupportedEncoding) {
Opts.Encoding = Supported;
break;
@@ -686,6 +686,9 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params,
ServerCaps["executeCommandProvider"] =
llvm::json::Object{{"commands", Commands}};
+ if (Opts.Encoding)
+ ServerCaps["positionEncoding"] = *Opts.Encoding;
+
llvm::json::Object Result{
{{"serverInfo",
llvm::json::Object{
@@ -693,6 +696,9 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params,
{"version", llvm::formatv("{0} {1} {2}", versionString(),
featureString(), platformString())}}},
{"capabilities", std::move(ServerCaps)}}};
+
+ // TODO: offsetEncoding capability is a deprecated clangd extension and should
+ // be deleted.
if (Opts.Encoding)
Result["offsetEncoding"] = *Opts.Encoding;
Reply(std::move(Result));
diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp
index c9e8a175b5d76..2c858e28fa243 100644
--- a/clang-tools-extra/clangd/Protocol.cpp
+++ b/clang-tools-extra/clangd/Protocol.cpp
@@ -497,10 +497,19 @@ bool fromJSON(const llvm::json::Value &Params, ClientCapabilities &R,
if (auto Cancel = StaleRequestSupport->getBoolean("cancel"))
R.CancelsStaleRequests = *Cancel;
}
+ if (auto *PositionEncodings = General->get("positionEncodings")) {
+ R.PositionEncodings.emplace();
+ if (!fromJSON(*PositionEncodings, *R.PositionEncodings,
+ P.field("general").field("positionEncodings")))
+ return false;
+ }
}
if (auto *OffsetEncoding = O->get("offsetEncoding")) {
- R.offsetEncoding.emplace();
- if (!fromJSON(*OffsetEncoding, *R.offsetEncoding,
+ R.PositionEncodings.emplace();
+ elog("offsetEncoding capability is a deprecated clangd extension that'll "
+ "go away with clangd 23. Migrate to standard positionEncodings "
+ "capability introduced by LSP 3.17");
+ if (!fromJSON(*OffsetEncoding, *R.PositionEncodings,
P.field("offsetEncoding")))
return false;
}
@@ -536,8 +545,11 @@ bool fromJSON(const llvm::json::Value &Params, ClientCapabilities &R,
}
}
if (auto *OffsetEncoding = Experimental->get("offsetEncoding")) {
- R.offsetEncoding.emplace();
- if (!fromJSON(*OffsetEncoding, *R.offsetEncoding,
+ R.PositionEncodings.emplace();
+ elog("offsetEncoding capability is a deprecated clangd extension that'll "
+ "go away with clangd 23. Migrate to standard positionEncodings "
+ "capability introduced by LSP 3.17");
+ if (!fromJSON(*OffsetEncoding, *R.PositionEncodings,
P.field("offsetEncoding")))
return false;
}
diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h
index 8a7809d6677ee..3a6bf155ee153 100644
--- a/clang-tools-extra/clangd/Protocol.h
+++ b/clang-tools-extra/clangd/Protocol.h
@@ -528,8 +528,9 @@ struct ClientCapabilities {
/// textDocument.semanticHighlightingCapabilities.semanticHighlighting
bool TheiaSemanticHighlighting = false;
- /// Supported encodings for LSP character offsets. (clangd extension).
- std::optional> offsetEncoding;
+ /// Supported encodings for LSP character offsets.
+ /// general.positionEncodings
+ std::optional> PositionEncodings;
/// The content format that should be used for Hover requests.
/// textDocument.hover.contentEncoding
diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp
index d9b73b83e902a..c56375b1a98d3 100644
--- a/clang-tools-extra/clangd/refactor/Rename.cpp
+++ b/clang-tools-extra/clangd/refactor/Rename.cpp
@@ -1308,7 +1308,7 @@ getMappedRanges(ArrayRef Indexed, ArrayRef Lexed) {
return std::nullopt;
}
// Fast check for the special subset case.
- if (std::includes(Indexed.begin(), Indexed.end(), Lexed.begin(), Lexed.end()))
+ if (llvm::includes(Indexed, Lexed))
return Lexed.vec();
std::vector Best;
diff --git a/clang-tools-extra/clangd/test/positionencoding.test b/clang-tools-extra/clangd/test/positionencoding.test
new file mode 100644
index 0000000000000..eea7a1a596e9a
--- /dev/null
+++ b/clang-tools-extra/clangd/test/positionencoding.test
@@ -0,0 +1,32 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+# This test verifies that we can negotiate UTF-8 offsets via the positionEncodings capability introduced in LSP 3.17.
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"general":{"positionEncodings":["utf-8","utf-16"]}},"trace":"off"}}
+# CHECK: "positionEncoding": "utf-8"
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"/*ö*/int x;\nint y=x;"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":1,"character":6}}}
+# /*ö*/int x;
+# 01234567890
+# x is character (and utf-16) range [9,10) but byte range [10,11).
+# CHECK: "id": 1,
+# CHECK-NEXT: "jsonrpc": "2.0",
+# CHECK-NEXT: "result": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 11,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 10,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "uri": "file://{{.*}}/main.cpp"
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+---
+{"jsonrpc":"2.0","id":10000,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 69f6df46c87ce..775278ccf694b 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -974,7 +974,7 @@ class Foo final {})cpp";
HI.Name = "abc";
HI.Kind = index::SymbolKind::Variable;
HI.NamespaceScope = "";
- HI.Definition = "int abc = ()";
+ HI.Definition = "int abc";
HI.Type = "int";
HI.AccessSpecifier = "public";
}},
diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp
index 1892f87c8e82a..b04d6431f89f9 100644
--- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -2311,6 +2311,14 @@ TEST(FindReferences, WithinAST) {
$(S::deleteObject)[[de^lete]] S;
}
};
+ )cpp",
+ // Array designators
+ R"cpp(
+ const int $def[[F^oo]] = 0;
+ int Bar[] = {
+ [$(Bar)[[F^oo]]...$(Bar)[[Fo^o]] + 1] = 0,
+ [$(Bar)[[^Foo]] + 2] = 1
+ };
)cpp"};
for (const char *Test : Tests)
checkFindRefs(Test);
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 882ee0015df17..3c1ca2f929044 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -237,10 +237,6 @@ Changes in existing checks
` check by avoiding
diagnosing designated initializers for ``std::array`` initializations.
-- Improved :doc:`modernize-use-integer-sign-comparison
- ` check by matching
- valid integer expressions not directly wrapped around an implicit cast.
-
- Improved :doc:`modernize-use-ranges
` check by updating suppress
warnings logic for ``nullptr`` in ``std::find``.
@@ -269,6 +265,8 @@ Changes in existing checks
` check performance by
tolerating fix-it breaking compilation when functions is used as pointers
to avoid matching usage of functions within the current compilation unit.
+ Added an option `IgnoreCoroutines` with the default value `true` to
+ suppress this check for coroutines where passing by reference may be unsafe.
- Improved :doc:`readability-convert-member-functions-to-static
` check by
diff --git a/clang-tools-extra/docs/clang-tidy/checks/performance/enum-size.rst b/clang-tools-extra/docs/clang-tidy/checks/performance/enum-size.rst
index f72b8c7eabc22..b7631139a0133 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/performance/enum-size.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/performance/enum-size.rst
@@ -34,7 +34,7 @@ dependent).
.. code-block:: c++
// AFTER
- enum Color : std:int8_t {
+ enum Color : std::int8_t {
RED = -1,
GREEN = 0,
BLUE = 1
diff --git a/clang-tools-extra/docs/clang-tidy/checks/performance/unnecessary-value-param.rst b/clang-tools-extra/docs/clang-tidy/checks/performance/unnecessary-value-param.rst
index dc86530b95f13..cd25d7d94d99b 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/performance/unnecessary-value-param.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/performance/unnecessary-value-param.rst
@@ -56,7 +56,7 @@ Will become:
Because the fix-it needs to change the signature of the function, it may break
builds if the function is used in multiple translation units or some codes
-depends on funcion signatures.
+depends on function signatures.
Options
-------
@@ -74,3 +74,10 @@ Options
default is empty. If a name in the list contains the sequence `::`, it is
matched against the qualified type name (i.e. ``namespace::Type``),
otherwise it is matched against only the type name (i.e. ``Type``).
+
+.. option:: IgnoreCoroutines
+
+ A boolean specifying whether the check should suggest passing parameters by
+ reference in coroutines. Passing parameters by reference in coroutines may
+ not be safe, please see :doc:`cppcoreguidelines-avoid-reference-coroutine-parameters <../cppcoreguidelines/avoid-reference-coroutine-parameters>`
+ for more information. Default is `true`.
diff --git a/clang-tools-extra/modularize/CoverageChecker.cpp b/clang-tools-extra/modularize/CoverageChecker.cpp
index fe6711398ab7d..1345a6ef8f489 100644
--- a/clang-tools-extra/modularize/CoverageChecker.cpp
+++ b/clang-tools-extra/modularize/CoverageChecker.cpp
@@ -329,10 +329,8 @@ bool CoverageChecker::collectFileSystemHeaders() {
else {
// Otherwise we only look at the sub-trees specified by the
// include paths.
- for (std::vector::const_iterator I = IncludePaths.begin(),
- E = IncludePaths.end();
- I != E; ++I) {
- if (!collectFileSystemHeaders(*I))
+ for (const std::string &IncludePath : IncludePaths) {
+ if (!collectFileSystemHeaders(IncludePath))
return false;
}
}
diff --git a/clang-tools-extra/modularize/Modularize.cpp b/clang-tools-extra/modularize/Modularize.cpp
index 7f8a19280b111..2a90c5e3f6782 100644
--- a/clang-tools-extra/modularize/Modularize.cpp
+++ b/clang-tools-extra/modularize/Modularize.cpp
@@ -339,8 +339,8 @@ static std::string findInputFile(const CommandLineArguments &CLArgs) {
llvm::opt::Visibility VisibilityMask(options::CC1Option);
unsigned MissingArgIndex, MissingArgCount;
SmallVector Argv;
- for (auto I = CLArgs.begin(), E = CLArgs.end(); I != E; ++I)
- Argv.push_back(I->c_str());
+ for (const std::string &CLArg : CLArgs)
+ Argv.push_back(CLArg.c_str());
InputArgList Args = getDriverOptTable().ParseArgs(
Argv, MissingArgIndex, MissingArgCount, VisibilityMask);
std::vector Inputs = Args.getAllArgValues(OPT_INPUT);
diff --git a/clang-tools-extra/modularize/ModularizeUtilities.cpp b/clang-tools-extra/modularize/ModularizeUtilities.cpp
index 9ad1731915a8b..8a24f21d658df 100644
--- a/clang-tools-extra/modularize/ModularizeUtilities.cpp
+++ b/clang-tools-extra/modularize/ModularizeUtilities.cpp
@@ -69,8 +69,7 @@ ModularizeUtilities *ModularizeUtilities::createModularizeUtilities(
// Load all header lists and dependencies.
std::error_code ModularizeUtilities::loadAllHeaderListsAndDependencies() {
// For each input file.
- for (auto I = InputFilePaths.begin(), E = InputFilePaths.end(); I != E; ++I) {
- llvm::StringRef InputPath = *I;
+ for (llvm::StringRef InputPath : InputFilePaths) {
// If it's a module map.
if (InputPath.ends_with(".modulemap")) {
// Load the module map.
diff --git a/clang-tools-extra/test/clang-reorder-fields/MacroExpansionField.cpp b/clang-tools-extra/test/clang-reorder-fields/MacroExpansionField.cpp
new file mode 100644
index 0000000000000..a4c3cbc1e12f4
--- /dev/null
+++ b/clang-tools-extra/test/clang-reorder-fields/MacroExpansionField.cpp
@@ -0,0 +1,24 @@
+// RUN: clang-reorder-fields -record-name ::bar::Foo -fields-order z,y,x %s -- | FileCheck %s
+
+namespace bar {
+
+#define INT_DECL(NAME) int NAME // CHECK: {{^#define INT_DECL\(NAME\) int NAME}}
+#define MACRO_DECL int x; // CHECK-NEXT: {{^#define MACRO_DECL int x;}}
+
+struct Foo {
+ MACRO_DECL // CHECK: {{^ INT_DECL\(z\);}}
+ int y; // CHECK-NEXT: {{^ int y;}}
+ INT_DECL(z); // CHECK-NEXT: {{^ MACRO_DECL}}
+};
+
+#define FOO 0 // CHECK: {{^#define FOO 0}}
+#define BAR 1 // CHECK-NEXT: {{^#define BAR 1}}
+#define BAZ 2 // CHECK-NEXT: {{^#define BAZ 2}}
+
+struct Foo foo = {
+ FOO, // CHECK: {{^ BAZ,}}
+ BAR, // CHECK-NEXT: {{^ BAR,}}
+ BAZ, // CHECK-NEXT: {{^ FOO,}}
+};
+
+} // end namespace bar
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-integer-sign-comparison.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-integer-sign-comparison.cpp
index d93a05ac38050..e0a84ef5aed26 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-integer-sign-comparison.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-integer-sign-comparison.cpp
@@ -121,81 +121,3 @@ int AllComparisons() {
return 0;
}
-
-namespace PR127471 {
- int getSignedValue();
- unsigned int getUnsignedValue();
-
- void callExprTest() {
-
- if (getSignedValue() < getUnsignedValue())
- return;
-// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: comparison between 'signed' and 'unsigned' integers [modernize-use-integer-sign-comparison]
-// CHECK-FIXES: if (std::cmp_less(getSignedValue() , getUnsignedValue()))
-
- int sVar = 0;
- if (getUnsignedValue() > sVar)
- return;
-// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: comparison between 'signed' and 'unsigned' integers [modernize-use-integer-sign-comparison]
-// CHECK-FIXES: if (std::cmp_greater(getUnsignedValue() , sVar))
-
- unsigned int uVar = 0;
- if (getSignedValue() > uVar)
- return;
-// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: comparison between 'signed' and 'unsigned' integers [modernize-use-integer-sign-comparison]
-// CHECK-FIXES: if (std::cmp_greater(getSignedValue() , uVar))
-
- }
-
- // Add a class with member functions for testing member function calls
- class TestClass {
- public:
- int getSignedValue() { return -5; }
- unsigned int getUnsignedValue() { return 5; }
- };
-
- void memberFunctionTests() {
- TestClass obj;
-
- if (obj.getSignedValue() < obj.getUnsignedValue())
- return;
-// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: comparison between 'signed' and 'unsigned' integers [modernize-use-integer-sign-comparison]
-// CHECK-FIXES: if (std::cmp_less(obj.getSignedValue() , obj.getUnsignedValue()))
- }
-
- void castFunctionTests() {
- // C-style casts with function calls
- if ((int)getUnsignedValue() < (unsigned int)getSignedValue())
- return;
-// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: comparison between 'signed' and 'unsigned' integers [modernize-use-integer-sign-comparison]
-// CHECK-FIXES: if (std::cmp_less(getUnsignedValue(),getSignedValue()))
-
-
- // Static casts with function calls
- if (static_cast(getUnsignedValue()) < static_cast(getSignedValue()))
- return;
-// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: comparison between 'signed' and 'unsigned' integers [modernize-use-integer-sign-comparison]
-// CHECK-FIXES: if (std::cmp_less(getUnsignedValue(),getSignedValue()))
- }
-
- // Define tests
- #define SIGNED_FUNC getSignedValue()
- #define UNSIGNED_FUNC getUnsignedValue()
-
- void defineTests() {
- if (SIGNED_FUNC < UNSIGNED_FUNC)
- return;
-// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: comparison between 'signed' and 'unsigned' integers [modernize-use-integer-sign-comparison]
-// CHECK-FIXES: if (std::cmp_less(SIGNED_FUNC , UNSIGNED_FUNC))
- }
-
- // Template tests (should not warn)
- template
- void templateFunctionTest(T1 value) {
- if (value() < getUnsignedValue())
- return;
-
- if (value() < (getSignedValue() || getUnsignedValue()))
- return;
- }
-} // namespace PR127471
diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance/unnecessary-value-param-coroutine.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance/unnecessary-value-param-coroutine.cpp
new file mode 100644
index 0000000000000..0a84dc4676470
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/performance/unnecessary-value-param-coroutine.cpp
@@ -0,0 +1,65 @@
+// RUN: %check_clang_tidy -std=c++20-or-later %s performance-unnecessary-value-param %t -- -fix-errors
+// RUN: %check_clang_tidy -std=c++20-or-later %s performance-unnecessary-value-param %t -- \
+// RUN: -config='{CheckOptions: {performance-unnecessary-value-param.IgnoreCoroutines: true}}' -fix-errors
+// RUN: %check_clang_tidy -check-suffix=ALLOWED -std=c++20-or-later %s performance-unnecessary-value-param %t -- \
+// RUN: -config='{CheckOptions: {performance-unnecessary-value-param.IgnoreCoroutines: false}}' -fix-errors
+
+namespace std {
+
+template struct coroutine_traits {
+ using promise_type = typename Ret::promise_type;
+};
+
+template struct coroutine_handle {
+ static coroutine_handle from_address(void *) noexcept;
+ static coroutine_handle from_promise(Promise &promise);
+ constexpr void *address() const noexcept;
+};
+
+template <> struct coroutine_handle {
+ template
+ coroutine_handle(coroutine_handle) noexcept;
+ static coroutine_handle from_address(void *);
+ constexpr void *address() const noexcept;
+};
+
+struct suspend_always {
+ bool await_ready() noexcept { return false; }
+ void await_suspend(coroutine_handle<>) noexcept {}
+ void await_resume() noexcept {}
+};
+
+struct suspend_never {
+ bool await_ready() noexcept { return true; }
+ void await_suspend(coroutine_handle<>) noexcept {}
+ void await_resume() noexcept {}
+};
+
+} // namespace std
+
+struct ReturnObject {
+ struct promise_type {
+ ReturnObject get_return_object() { return {}; }
+ ReturnObject return_void() { return {}; }
+ std::suspend_always initial_suspend() { return {}; }
+ std::suspend_always final_suspend() noexcept { return {}; }
+ void unhandled_exception() {}
+ std::suspend_always yield_value(int value) { return {}; }
+ };
+};
+
+struct A {
+ A(const A&);
+};
+
+ReturnObject foo_coroutine(const A a) {
+// CHECK-MESSAGES-ALLOWED: [[@LINE-1]]:36: warning: the const qualified parameter 'a'
+// CHECK-FIXES: ReturnObject foo_coroutine(const A a) {
+ co_return;
+}
+
+ReturnObject foo_not_coroutine(const A a) {
+// CHECK-MESSAGES: [[@LINE-1]]:40: warning: the const qualified parameter 'a'
+// CHECK-MESSAGES-ALLOWED: [[@LINE-2]]:40: warning: the const qualified parameter 'a'
+ return ReturnObject{};
+}
diff --git a/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp b/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
index bbe158ed50e28..659870d2a5c0d 100644
--- a/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
@@ -37,7 +37,7 @@ static std::string writeInfo(Info *I) {
return writeInfo(*static_cast(I));
case InfoType::IT_typedef:
return writeInfo(*static_cast(I));
- default:
+ case InfoType::IT_default:
return "";
}
}
diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt
index ab2ac9bc6b9ad..94607a8e8473c 100644
--- a/clang/CMakeLists.txt
+++ b/clang/CMakeLists.txt
@@ -345,9 +345,6 @@ configure_file(
# Add appropriate flags for GCC
if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-common -Woverloaded-virtual")
- if (NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing")
- endif ()
# Enable -pedantic for Clang even if it's not enabled for LLVM.
if (NOT LLVM_ENABLE_PEDANTIC)
diff --git a/clang/docs/HIPSupport.rst b/clang/docs/HIPSupport.rst
index 051a253969943..406e1c8e5a2fe 100644
--- a/clang/docs/HIPSupport.rst
+++ b/clang/docs/HIPSupport.rst
@@ -17,7 +17,7 @@
HIP Support
=============
-HIP (Heterogeneous-Compute Interface for Portability) ``_ is
+HIP (Heterogeneous-Compute Interface for Portability) ``_ is
a C++ Runtime API and Kernel Language. It enables developers to create portable applications for
offloading computation to different hardware platforms from a single source code.
@@ -41,9 +41,9 @@ backend or the out-of-tree LLVM-SPIRV translator. The SPIR-V is then bundled and
.. note::
While Clang does not directly provide HIP support for NVIDIA GPUs and CPUs, these platforms are supported via other means:
- - NVIDIA GPUs: HIP support is offered through the HIP project ``_, which provides a header-only library for translating HIP runtime APIs into CUDA runtime APIs. The code is subsequently compiled using NVIDIA's `nvcc`.
+ - NVIDIA GPUs: HIP support is offered through the HIP project ``_, which provides a header-only library for translating HIP runtime APIs into CUDA runtime APIs. The code is subsequently compiled using NVIDIA's `nvcc`.
- - CPUs: HIP support is available through the HIP-CPU runtime library ``_. This header-only library enables CPUs to execute unmodified HIP code.
+ - CPUs: HIP support is available through the HIP-CPU runtime library ``_. This header-only library enables CPUs to execute unmodified HIP code.
Example Usage
@@ -328,7 +328,7 @@ The `parallel_unsequenced_policy `__), makes
+(e.g. `rocThrust `__), makes
it feasible to provide seamless accelerator offload for supported algorithms,
when an accelerated version exists. Thus, it becomes possible to easily access
the computational resources of an AMD accelerator, via a well specified,
@@ -483,7 +483,7 @@ such as GPUs, work.
allocation / deallocation functions with accelerator-aware equivalents,
based on a pre-established table; the list of functions that can be
interposed is available
- `here `__;
+ `here `__;
- This is only run when compiling for the host.
The second pass is optional.
@@ -627,7 +627,7 @@ Linux operating system. Support is synthesised in the following table:
The minimum Linux kernel version for running in HMM mode is 6.4.
The forwarding header can be obtained from
-`its GitHub repository `_.
+`its GitHub repository `_.
It will be packaged with a future `ROCm `_
release. Because accelerated algorithms are provided via
`rocThrust `_, a
@@ -636,7 +636,7 @@ transitive dependency on
can be obtained either by installing their associated components of the
`ROCm `_ stack, or from their respective
repositories. The list algorithms that can be offloaded is available
-`here `_.
+`here `_.
HIP Specific Elements
---------------------
diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst
index d6507071d4693..986aaabe1eed4 100644
--- a/clang/docs/OpenMPSupport.rst
+++ b/clang/docs/OpenMPSupport.rst
@@ -406,7 +406,8 @@ implementation.
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| Extensions to atomic construct | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
-| Private reductions | :part:`partial` | :none:`unclaimed` | Parse/Sema:https://github.com/llvm/llvm-project/pull/129938 |
+| Private reductions | :good:`mostly` | :none:`unclaimed` | Parse/Sema:https://github.com/llvm/llvm-project/pull/129938 |
+| | | | Codegen: https://github.com/llvm/llvm-project/pull/134709 |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| Self maps | :part:`partial` | :none:`unclaimed` | parsing/sema done: https://github.com/llvm/llvm-project/pull/129888 |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f36c82bff2ef8..12816eed2e8b5 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -65,8 +65,10 @@ C++ Specific Potentially Breaking Changes
standard library already have their own bespoke builtins.
- A workaround for libstdc++4.7 has been removed. Note that 4.8.3 remains the oldest
supported libstdc++ version.
-
- Added ``!nonnull/!align`` metadata to load of references for better codegen.
+- Checking for int->enum conversions in constant expressions is more strict;
+ in particular, ``const E x = (E)-1;`` is not treated as a constant if it's
+ out of range. This impacts old versions of Boost. (#GH143034)
ABI Changes in This Version
---------------------------
@@ -339,6 +341,8 @@ New Compiler Flags
- New option ``-Wnrvo`` added and disabled by default to warn about missed NRVO opportunities.
+- New option ``-ignore-pch`` added to disable precompiled headers. It overrides ``-emit-pch`` and ``-include-pch``. (#GH142409, `PCHDocs `_).
+
Deprecated Compiler Flags
-------------------------
@@ -357,6 +361,8 @@ Modified Compiler Flags
- The ``-fchar8_t`` flag is no longer considered in non-C++ languages modes. (#GH55373)
+- The ``-fveclib=libmvec`` option now supports AArch64 targets (requires GLIBC 2.40 or newer).
+
Removed Compiler Flags
-------------------------
@@ -622,6 +628,14 @@ Improvements to Clang's diagnostics
- Improved the FixIts for unused lambda captures.
+- Delayed typo correction was removed from the compiler; immediate typo
+ correction behavior remains the same. Delayed typo correction facilities were
+ fragile and unmaintained, and the removal closed the following issues:
+ #GH142457, #GH139913, #GH138850, #GH137867, #GH137860, #GH107840, #GH93308,
+ #GH69470, #GH59391, #GH58172, #GH46215, #GH45915, #GH45891, #GH44490,
+ #GH36703, #GH32903, #GH23312, #GH69874.
+
+
Improvements to Clang's time-trace
----------------------------------
@@ -680,6 +694,8 @@ Bug Fixes in This Version
``#include`` directive. (#GH138094)
- Fixed a crash during constant evaluation involving invalid lambda captures
(#GH138832)
+- Fixed compound literal is not constant expression inside initializer list
+ (#GH87867)
- Fixed a crash when instantiating an invalid dependent friend template specialization.
(#GH139052)
- Fixed a crash with an invalid member function parameter list with a default
@@ -693,6 +709,10 @@ Bug Fixes in This Version
- Fixed type mismatch error when 'builtin-elementwise-math' arguments have different qualifiers, this should be well-formed. (#GH141397)
- Constant evaluation now correctly runs the destructor of a variable declared in
the second clause of a C-style ``for`` loop. (#GH139818)
+- Fixed a bug with constexpr evaluation for structs containing unions in case of C++ modules. (#GH143168)
+- Fixed incorrect token location when emitting diagnostics for tokens expanded from macros. (#GH143216)
+- Fixed an infinite recursion when checking constexpr destructors. (#GH141789)
+- Fixed a crash when a malformed using declaration appears in a ``constexpr`` function. (#GH144264)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1100,6 +1120,10 @@ OpenMP Support
open parenthesis. (#GH139665)
- An error is now emitted when OpenMP ``collapse`` and ``ordered`` clauses have
an argument larger than what can fit within a 64-bit integer.
+- Added support for private variable reduction.
+- Fixed mapping of arrays of structs containing nested structs with user defined
+ mappers, by using compiler-generated default mappers for the outer structs for
+ such maps.
Improvements
^^^^^^^^^^^^
diff --git a/clang/docs/SanitizerSpecialCaseList.rst b/clang/docs/SanitizerSpecialCaseList.rst
index 61b6c55d8e6e4..2c50778d0f491 100644
--- a/clang/docs/SanitizerSpecialCaseList.rst
+++ b/clang/docs/SanitizerSpecialCaseList.rst
@@ -109,13 +109,13 @@ precedence. Here are a few examples.
.. code-block:: bash
$ cat ignorelist1.txt
- # test.cc will be instrumented.
+ # test.cc will not be instrumented.
src:*
src:*/mylib/*=sanitize
src:*/mylib/test.cc
$ cat ignorelist2.txt
- # test.cc will not be instrumented.
+ # test.cc will be instrumented.
src:*
src:*/mylib/test.cc
src:*/mylib/*=sanitize
diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index 62844f7e6a2fa..284a404026dfe 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -1458,6 +1458,19 @@ will be processed from the PCH file. Otherwise, Clang will report an error.
``test.h`` since ``test.h`` was included directly in the source file and not
specified on the command line using ``-include-pch``.
+Ignoring a PCH File
+^^^^^^^^^^^^^^^^^^^
+
+To ignore PCH options, a `-ignore-pch` option is passed to ``clang``:
+
+.. code-block:: console
+
+ $ clang -x c-header test.h -Xclang -ignore-pch -o test.h.pch
+ $ clang -include-pch test.h.pch -Xclang -ignore-pch test.c -o test
+
+This option disables precompiled headers, overrides -emit-pch and -include-pch.
+test.h.pch is not generated and not used as a prefix header.
+
Relocatable PCH Files
^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 8d24d393eab09..e01361e2466b5 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -488,8 +488,8 @@ class ASTContext : public RefCountedBase {
/// if possible.
///
/// Not serialized intentionally.
- llvm::StringMap PrimaryModuleNameMap;
- llvm::DenseMap SameModuleLookupSet;
+ mutable llvm::StringMap PrimaryModuleNameMap;
+ mutable llvm::DenseMap SameModuleLookupSet;
static constexpr unsigned ConstantArrayTypesLog2InitSize = 8;
static constexpr unsigned GeneralTypesLog2InitSize = 9;
@@ -629,10 +629,48 @@ class ASTContext : public RefCountedBase {
void setRelocationInfoForCXXRecord(const CXXRecordDecl *,
CXXRecordDeclRelocationInfo);
+ /// Examines a given type, and returns whether the type itself
+ /// is address discriminated, or any transitively embedded types
+ /// contain data that is address discriminated. This includes
+ /// implicitly authenticated values like vtable pointers, as well as
+ /// explicitly qualified fields.
+ bool containsAddressDiscriminatedPointerAuth(QualType T) {
+ if (!isPointerAuthenticationAvailable())
+ return false;
+ return findPointerAuthContent(T) != PointerAuthContent::None;
+ }
+
+ /// Examines a given type, and returns whether the type itself
+ /// or any data it transitively contains has a pointer authentication
+ /// schema that is not safely relocatable. e.g. any data or fields
+ /// with address discrimination other than any otherwise similar
+ /// vtable pointers.
+ bool containsNonRelocatablePointerAuth(QualType T) {
+ if (!isPointerAuthenticationAvailable())
+ return false;
+ return findPointerAuthContent(T) ==
+ PointerAuthContent::AddressDiscriminatedData;
+ }
+
private:
llvm::DenseMap
RelocatableClasses;
+ // FIXME: store in RecordDeclBitfields in future?
+ enum class PointerAuthContent : uint8_t {
+ None,
+ AddressDiscriminatedVTable,
+ AddressDiscriminatedData
+ };
+
+ // A simple helper function to short circuit pointer auth checks.
+ bool isPointerAuthenticationAvailable() const {
+ return LangOpts.PointerAuthCalls || LangOpts.PointerAuthIntrinsics;
+ }
+ PointerAuthContent findPointerAuthContent(QualType T);
+ llvm::DenseMap
+ RecordContainsAddressDiscriminatedPointerAuth;
+
ImportDecl *FirstLocalImport = nullptr;
ImportDecl *LastLocalImport = nullptr;
@@ -1151,7 +1189,7 @@ class ASTContext : public RefCountedBase {
///
/// FIXME: The signature may be confusing since `clang::Module` means to
/// a module fragment or a module unit but not a C++20 module.
- bool isInSameModule(const Module *M1, const Module *M2);
+ bool isInSameModule(const Module *M1, const Module *M2) const;
TranslationUnitDecl *getTranslationUnitDecl() const {
return TUDecl->getMostRecentDecl();
@@ -3668,6 +3706,7 @@ OPT_LIST(V)
/// authentication policy for the specified record.
const CXXRecordDecl *
baseForVTableAuthentication(const CXXRecordDecl *ThisClass);
+
bool useAbbreviatedThunkName(GlobalDecl VirtualMethodDecl,
StringRef MangledName);
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 375e9e2592502..dd67ebc9873ff 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -646,6 +646,10 @@ class alignas(8) Decl {
return getModuleOwnershipKind() == ModuleOwnershipKind::ModulePrivate;
}
+ /// Whether this declaration was a local declaration to a C++20
+ /// named module.
+ bool isModuleLocal() const;
+
/// Whether this declaration was exported in a lexical context.
/// e.g.:
///
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 43c28c8bf649f..9fc23d30b733f 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -240,8 +240,7 @@ class Expr : public ValueStmt {
return static_cast(getDependence() & ExprDependence::UnexpandedPack);
}
- /// Whether this expression contains subexpressions which had errors, e.g. a
- /// TypoExpr.
+ /// Whether this expression contains subexpressions which had errors.
bool containsErrors() const {
return static_cast(getDependence() & ExprDependence::Error);
}
@@ -6965,36 +6964,6 @@ class AtomicExpr : public Expr {
}
};
-/// TypoExpr - Internal placeholder for expressions where typo correction
-/// still needs to be performed and/or an error diagnostic emitted.
-class TypoExpr : public Expr {
- // The location for the typo name.
- SourceLocation TypoLoc;
-
-public:
- TypoExpr(QualType T, SourceLocation TypoLoc)
- : Expr(TypoExprClass, T, VK_LValue, OK_Ordinary), TypoLoc(TypoLoc) {
- assert(T->isDependentType() && "TypoExpr given a non-dependent type");
- setDependence(ExprDependence::TypeValueInstantiation |
- ExprDependence::Error);
- }
-
- child_range children() {
- return child_range(child_iterator(), child_iterator());
- }
- const_child_range children() const {
- return const_child_range(const_child_iterator(), const_child_iterator());
- }
-
- SourceLocation getBeginLoc() const LLVM_READONLY { return TypoLoc; }
- SourceLocation getEndLoc() const LLVM_READONLY { return TypoLoc; }
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == TypoExprClass;
- }
-
-};
-
/// This class represents BOTH the OpenMP Array Section and OpenACC 'subarray',
/// with a boolean differentiator.
/// OpenMP 5.0 [2.1.5, Array Sections].
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index b0f8ae621cf6d..5cb2f57edffe4 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2956,7 +2956,6 @@ DEF_TRAVERSE_STMT(CXXRewrittenBinaryOperator, {
}
})
DEF_TRAVERSE_STMT(OpaqueValueExpr, {})
-DEF_TRAVERSE_STMT(TypoExpr, {})
DEF_TRAVERSE_STMT(RecoveryExpr, {})
DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {})
diff --git a/clang/include/clang/Basic/AArch64ACLETypes.def b/clang/include/clang/Basic/AArch64ACLETypes.def
index 9acfd693288cf..bbe0c85f9ffbe 100644
--- a/clang/include/clang/Basic/AArch64ACLETypes.def
+++ b/clang/include/clang/Basic/AArch64ACLETypes.def
@@ -123,31 +123,31 @@
//===- Neon Vector point types --------------------------------------------===//
-NEON_VECTOR_TYPE(__Int8x8_t, CharTy, 8, 8, VectorKind::Neon)
+NEON_VECTOR_TYPE(__Int8x8_t, SignedCharTy, 8, 8, VectorKind::Neon)
NEON_VECTOR_TYPE(__Int16x4_t, ShortTy, 16, 4, VectorKind::Neon)
NEON_VECTOR_TYPE(__Int32x2_t, IntTy, 32, 2, VectorKind::Neon)
-NEON_VECTOR_TYPE(__Uint8x8_t, CharTy, 8, 8, VectorKind::Neon)
+NEON_VECTOR_TYPE(__Uint8x8_t, UnsignedCharTy, 8, 8, VectorKind::Neon)
NEON_VECTOR_TYPE(__Uint16x4_t, UnsignedShortTy, 16, 4, VectorKind::Neon)
NEON_VECTOR_TYPE(__Uint32x2_t, UnsignedIntTy, 32, 2, VectorKind::Neon)
-NEON_VECTOR_TYPE(__Float16x4_t, Float16Ty, 16, 4, VectorKind::Neon)
+NEON_VECTOR_TYPE(__Float16x4_t, HalfTy, 16, 4, VectorKind::Neon)
NEON_VECTOR_TYPE(__Float32x2_t, FloatTy, 32, 2, VectorKind::Neon)
-NEON_VECTOR_TYPE(__Poly8x8_t, CharTy, 8, 8, VectorKind::NeonPoly)
+NEON_VECTOR_TYPE(__Poly8x8_t, UnsignedCharTy, 8, 8, VectorKind::NeonPoly)
NEON_VECTOR_TYPE(__Poly16x4_t, UnsignedShortTy, 16, 4, VectorKind::NeonPoly)
NEON_VECTOR_TYPE(__Bfloat16x4_t, BFloat16Ty, 16, 4, VectorKind::Neon)
-NEON_VECTOR_TYPE(__Int8x16_t, CharTy, 8, 16, VectorKind::Neon)
+NEON_VECTOR_TYPE(__Int8x16_t, SignedCharTy, 8, 16, VectorKind::Neon)
NEON_VECTOR_TYPE(__Int16x8_t, ShortTy, 16, 8, VectorKind::Neon)
NEON_VECTOR_TYPE(__Int32x4_t, IntTy, 32, 4, VectorKind::Neon)
-NEON_VECTOR_TYPE(__Int64x2_t, LongLongTy, 64, 2, VectorKind::Neon)
-NEON_VECTOR_TYPE(__Uint8x16_t, CharTy, 8, 16, VectorKind::Neon)
+NEON_VECTOR_TYPE(__Int64x2_t, LongTy, 64, 2, VectorKind::Neon)
+NEON_VECTOR_TYPE(__Uint8x16_t, UnsignedCharTy, 8, 16, VectorKind::Neon)
NEON_VECTOR_TYPE(__Uint16x8_t, UnsignedShortTy, 16, 8, VectorKind::Neon)
NEON_VECTOR_TYPE(__Uint32x4_t, UnsignedIntTy, 32, 4, VectorKind::Neon)
-NEON_VECTOR_TYPE(__Uint64x2_t, UnsignedLongLongTy, 64, 2, VectorKind::Neon)
-NEON_VECTOR_TYPE(__Float16x8_t, Float16Ty, 16, 8, VectorKind::Neon)
+NEON_VECTOR_TYPE(__Uint64x2_t, UnsignedLongTy, 64, 2, VectorKind::Neon)
+NEON_VECTOR_TYPE(__Float16x8_t, HalfTy, 16, 8, VectorKind::Neon)
NEON_VECTOR_TYPE(__Float32x4_t, FloatTy, 32, 4, VectorKind::Neon)
NEON_VECTOR_TYPE(__Float64x2_t, DoubleTy, 64, 2, VectorKind::Neon)
-NEON_VECTOR_TYPE(__Poly8x16_t, CharTy, 8, 16, VectorKind::NeonPoly)
+NEON_VECTOR_TYPE(__Poly8x16_t, UnsignedCharTy, 8, 16, VectorKind::NeonPoly)
NEON_VECTOR_TYPE(__Poly16x8_t, UnsignedShortTy, 16, 8, VectorKind::NeonPoly)
-NEON_VECTOR_TYPE(__Poly64x2_t, UnsignedLongLongTy, 64, 2, VectorKind::NeonPoly)
+NEON_VECTOR_TYPE(__Poly64x2_t, UnsignedLongTy, 64, 2, VectorKind::NeonPoly)
NEON_VECTOR_TYPE(__Bfloat16x8_t, BFloat16Ty, 16, 8, VectorKind::Neon)
NEON_VECTOR_TYPE(__Mfloat8x8_t, MFloat8Ty, 8, 8, VectorKind::Neon)
NEON_VECTOR_TYPE(__Mfloat8x16_t, MFloat8Ty, 8, 16, VectorKind::Neon)
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index b8e5806d3c5e9..f113cd2ba2fbf 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4630,6 +4630,7 @@ def OMPDeclareVariant : InheritableAttr {
OMPTraitInfoArgument<"TraitInfos">,
VariadicExprArgument<"AdjustArgsNothing">,
VariadicExprArgument<"AdjustArgsNeedDevicePtr">,
+ VariadicExprArgument<"AdjustArgsNeedDeviceAddr">,
VariadicOMPInteropInfoArgument<"AppendArgs">,
];
let AdditionalMembers = [{
@@ -4901,6 +4902,13 @@ def HLSLResourceBinding: InheritableAttr {
}];
}
+def HLSLSV_Position : HLSLAnnotationAttr {
+ let Spellings = [HLSLAnnotation<"sv_position">];
+ let Subjects = SubjectList<[ParmVar, Field]>;
+ let LangOpts = [HLSL];
+ let Documentation = [HLSLSV_PositionDocs];
+}
+
def HLSLPackOffset: HLSLAnnotationAttr {
let Spellings = [HLSLAnnotation<"packoffset">];
let LangOpts = [HLSL];
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index ea3c43f38d9fe..6051e1fc45111 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -2934,7 +2934,7 @@ https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Function-Attributes.html
https://riscv.org/specifications/privileged-isa/
The RISC-V Instruction Set Manual Volume II: Privileged Architecture
Version 1.10.
-https://github.com/quic/riscv-unified-db/releases/tag/Xqci-0.7
+https://github.com/quic/riscv-unified-db/releases/tag/Xqci-0.13.0
https://sifive.cdn.prismic.io/sifive/d1984d2b-c9b9-4c91-8de0-d68a5e64fa0f_sifive-interrupt-cookbook-v1p2.pdf
}];
}
@@ -8529,6 +8529,20 @@ The full documentation is available here: https://docs.microsoft.com/en-us/windo
}];
}
+def HLSLSV_PositionDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``SV_Position`` semantic, when applied to an input parameter in a pixel
+shader, contains the location of the pixel center (x, y) in screen space.
+This semantic can be applied to the parameter, or a field in a struct used
+as an input parameter.
+This attribute is supported as an input in pixel, hull, domain and mesh shaders.
+This attribute is supported as an output in vertex, geometry and domain shaders.
+
+The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics
+ }];
+}
+
def HLSLGroupSharedAddressSpaceDocs : Documentation {
let Category = DocCatVariable;
let Content = [{
diff --git a/clang/include/clang/Basic/AttributeCommonInfo.h b/clang/include/clang/Basic/AttributeCommonInfo.h
index 34fc774362557..21a7a88a3fb98 100644
--- a/clang/include/clang/Basic/AttributeCommonInfo.h
+++ b/clang/include/clang/Basic/AttributeCommonInfo.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
#define LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
+#include "clang/Basic/AttributeScopeInfo.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TokenKinds.h"
@@ -61,6 +62,7 @@ class AttributeCommonInfo {
/// implicitly.
AS_Implicit
};
+
enum Kind {
#define PARSED_ATTR(NAME) AT_##NAME,
#include "clang/Basic/AttrParsedAttrList.inc"
@@ -78,9 +80,9 @@ class AttributeCommonInfo {
private:
const IdentifierInfo *AttrName = nullptr;
- const IdentifierInfo *ScopeName = nullptr;
+ AttributeScopeInfo AttrScope;
SourceRange AttrRange;
- const SourceLocation ScopeLoc;
+
// Corresponds to the Kind enum.
LLVM_PREFERRED_TYPE(Kind)
unsigned AttrKind : 16;
@@ -146,11 +148,10 @@ class AttributeCommonInfo {
};
AttributeCommonInfo(const IdentifierInfo *AttrName,
- const IdentifierInfo *ScopeName, SourceRange AttrRange,
- SourceLocation ScopeLoc, Kind AttrKind, Form FormUsed)
- : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange),
- ScopeLoc(ScopeLoc), AttrKind(AttrKind),
- SyntaxUsed(FormUsed.getSyntax()),
+ AttributeScopeInfo AttrScope, SourceRange AttrRange,
+ Kind AttrKind, Form FormUsed)
+ : AttrName(AttrName), AttrScope(AttrScope), AttrRange(AttrRange),
+ AttrKind(AttrKind), SyntaxUsed(FormUsed.getSyntax()),
SpellingIndex(FormUsed.getSpellingIndex()),
IsAlignas(FormUsed.isAlignas()),
IsRegularKeywordAttribute(FormUsed.isRegularKeywordAttribute()) {
@@ -158,21 +159,20 @@ class AttributeCommonInfo {
"Invalid syntax!");
}
- AttributeCommonInfo(const IdentifierInfo *AttrName,
- const IdentifierInfo *ScopeName, SourceRange AttrRange,
- SourceLocation ScopeLoc, Form FormUsed)
+ AttributeCommonInfo(const IdentifierInfo *AttrName, AttributeScopeInfo Scope,
+ SourceRange AttrRange, Form FormUsed)
: AttributeCommonInfo(
- AttrName, ScopeName, AttrRange, ScopeLoc,
- getParsedKind(AttrName, ScopeName, FormUsed.getSyntax()),
+ AttrName, Scope, AttrRange,
+ getParsedKind(AttrName, Scope.getName(), FormUsed.getSyntax()),
FormUsed) {}
AttributeCommonInfo(const IdentifierInfo *AttrName, SourceRange AttrRange,
Form FormUsed)
- : AttributeCommonInfo(AttrName, nullptr, AttrRange, SourceLocation(),
+ : AttributeCommonInfo(AttrName, AttributeScopeInfo(), AttrRange,
FormUsed) {}
AttributeCommonInfo(SourceRange AttrRange, Kind K, Form FormUsed)
- : AttributeCommonInfo(nullptr, nullptr, AttrRange, SourceLocation(), K,
+ : AttributeCommonInfo(nullptr, AttributeScopeInfo(), AttrRange, K,
FormUsed) {}
AttributeCommonInfo(AttributeCommonInfo &&) = default;
@@ -190,17 +190,27 @@ class AttributeCommonInfo {
SourceRange getRange() const { return AttrRange; }
void setRange(SourceRange R) { AttrRange = R; }
- bool hasScope() const { return ScopeName; }
- const IdentifierInfo *getScopeName() const { return ScopeName; }
- SourceLocation getScopeLoc() const { return ScopeLoc; }
+ bool hasScope() const { return AttrScope.isValid(); }
+ bool isExplicitScope() const { return AttrScope.isExplicit(); }
+
+ const IdentifierInfo *getScopeName() const { return AttrScope.getName(); }
+ SourceLocation getScopeLoc() const { return AttrScope.getNameLoc(); }
/// Gets the normalized full name, which consists of both scope and name and
/// with surrounding underscores removed as appropriate (e.g.
/// __gnu__::__attr__ will be normalized to gnu::attr).
std::string getNormalizedFullName() const;
- std::optional
- getCorrectedFullName(const TargetInfo &Target,
- const LangOptions &LangOpts) const;
+ std::string getNormalizedFullName(StringRef ScopeName,
+ StringRef AttrName) const;
+ StringRef getNormalizedScopeName() const;
+ StringRef getNormalizedAttrName(StringRef ScopeName) const;
+
+ std::optional tryGetCorrectedScopeName(StringRef ScopeName) const;
+ std::optional
+ tryGetCorrectedAttrName(StringRef ScopeName, StringRef AttrName,
+ const TargetInfo &Target,
+ const LangOptions &LangOpts) const;
+
SourceRange getNormalizedRange() const;
bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
diff --git a/clang/include/clang/Basic/AttributeScopeInfo.h b/clang/include/clang/Basic/AttributeScopeInfo.h
new file mode 100644
index 0000000000000..cca4df7c11b02
--- /dev/null
+++ b/clang/include/clang/Basic/AttributeScopeInfo.h
@@ -0,0 +1,48 @@
+//==- AttributeScopeInfo.h - Base info about an Attribute Scope --*- 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 the AttributeScopeInfo type, which represents information
+// about the scope of an attribute.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_ATTRIBUTESCOPEINFO_H
+#define LLVM_CLANG_BASIC_ATTRIBUTESCOPEINFO_H
+
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+
+class IdentifierInfo;
+
+class AttributeScopeInfo {
+public:
+ AttributeScopeInfo() = default;
+
+ AttributeScopeInfo(const IdentifierInfo *Name, SourceLocation NameLoc)
+ : Name(Name), NameLoc(NameLoc) {}
+
+ AttributeScopeInfo(const IdentifierInfo *Name, SourceLocation NameLoc,
+ SourceLocation CommonScopeLoc)
+ : Name(Name), NameLoc(NameLoc), CommonScopeLoc(CommonScopeLoc) {}
+
+ const IdentifierInfo *getName() const { return Name; }
+ SourceLocation getNameLoc() const { return NameLoc; }
+
+ bool isValid() const { return Name != nullptr; }
+ bool isExplicit() const { return CommonScopeLoc.isInvalid(); }
+
+private:
+ const IdentifierInfo *Name = nullptr;
+ SourceLocation NameLoc;
+ SourceLocation CommonScopeLoc;
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_BASIC_ATTRIBUTESCOPEINFO_H
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index fa9474d63ae42..e5566a540dc65 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -223,9 +223,11 @@ AFFECTING_VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is
CODEGENOPT(AtomicProfileUpdate , 1, 0) ///< Set -fprofile-update=atomic
CODEGENOPT(ContinuousProfileSync, 1, 0) ///< Enable continuous instrumentation profiling
/// Choose profile instrumenation kind or no instrumentation.
-ENUM_CODEGENOPT(ProfileInstr, ProfileInstrKind, 4, ProfileNone)
+
+ENUM_CODEGENOPT(ProfileInstr, llvm::driver::ProfileInstrKind, 4, llvm::driver::ProfileInstrKind::ProfileNone)
+
/// Choose profile kind for PGO use compilation.
-ENUM_CODEGENOPT(ProfileUse, ProfileInstrKind, 2, ProfileNone)
+ENUM_CODEGENOPT(ProfileUse, llvm::driver::ProfileInstrKind, 2, llvm::driver::ProfileInstrKind::ProfileNone)
/// Partition functions into N groups and select only functions in group i to be
/// instrumented. Selected group numbers can be 0 to N-1 inclusive.
VALUE_CODEGENOPT(ProfileTotalFunctionGroups, 32, 1)
@@ -481,8 +483,10 @@ CODEGENOPT(StaticClosure, 1, 0)
/// Assume that UAVs/SRVs may alias
CODEGENOPT(ResMayAlias, 1, 0)
-/// Enables unwind v2 (epilog) information for x64 Windows.
-CODEGENOPT(WinX64EHUnwindV2, 1, 0)
+/// Controls how unwind v2 (epilog) information should be generated for x64
+/// Windows.
+ENUM_CODEGENOPT(WinX64EHUnwindV2, llvm::WinX64EHUnwindV2Mode,
+ 2, llvm::WinX64EHUnwindV2Mode::Disabled)
/// FIXME: Make DebugOptions its own top-level .def file.
#include "DebugOptions.def"
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index a77232c281f7f..7ba21fca6dd6b 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -80,16 +80,6 @@ class CodeGenOptions : public CodeGenOptionsBase {
SRCK_InRegs // Small structs in registers (-freg-struct-return).
};
- enum ProfileInstrKind {
- ProfileNone, // Profile instrumentation is turned off.
- ProfileClangInstr, // Clang instrumentation to generate execution counts
- // to use with PGO.
- ProfileIRInstr, // IR level PGO instrumentation in LLVM.
- ProfileCSIRInstr, // IR level PGO context sensitive instrumentation in LLVM.
- ProfileIRSampleColdCov, // IR level sample pgo based cold function coverage
- // instrumentation in LLVM.
- };
-
enum EmbedBitcodeKind {
Embed_Off, // No embedded bitcode.
Embed_All, // Embed both bitcode and commandline in the output.
@@ -522,35 +512,41 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// Check if Clang profile instrumenation is on.
bool hasProfileClangInstr() const {
- return getProfileInstr() == ProfileClangInstr;
+ return getProfileInstr() ==
+ llvm::driver::ProfileInstrKind::ProfileClangInstr;
}
/// Check if IR level profile instrumentation is on.
bool hasProfileIRInstr() const {
- return getProfileInstr() == ProfileIRInstr;
+ return getProfileInstr() == llvm::driver::ProfileInstrKind::ProfileIRInstr;
}
/// Check if CS IR level profile instrumentation is on.
bool hasProfileCSIRInstr() const {
- return getProfileInstr() == ProfileCSIRInstr;
+ return getProfileInstr() ==
+ llvm::driver::ProfileInstrKind::ProfileCSIRInstr;
}
/// Check if any form of instrumentation is on.
- bool hasProfileInstr() const { return getProfileInstr() != ProfileNone; }
+ bool hasProfileInstr() const {
+ return getProfileInstr() != llvm::driver::ProfileInstrKind::ProfileNone;
+ }
/// Check if Clang profile use is on.
bool hasProfileClangUse() const {
- return getProfileUse() == ProfileClangInstr;
+ return getProfileUse() == llvm::driver::ProfileInstrKind::ProfileClangInstr;
}
/// Check if IR level profile use is on.
bool hasProfileIRUse() const {
- return getProfileUse() == ProfileIRInstr ||
- getProfileUse() == ProfileCSIRInstr;
+ return getProfileUse() == llvm::driver::ProfileInstrKind::ProfileIRInstr ||
+ getProfileUse() == llvm::driver::ProfileInstrKind::ProfileCSIRInstr;
}
/// Check if CSIR profile use is on.
- bool hasProfileCSIRUse() const { return getProfileUse() == ProfileCSIRInstr; }
+ bool hasProfileCSIRUse() const {
+ return getProfileUse() == llvm::driver::ProfileInstrKind::ProfileCSIRInstr;
+ }
/// Check if type and variable info should be emitted.
bool hasReducedDebugInfo() const {
diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h
index e9c54c3c487c9..7ae4ef7df138c 100644
--- a/clang/include/clang/Basic/Diagnostic.h
+++ b/clang/include/clang/Basic/Diagnostic.h
@@ -18,6 +18,7 @@
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/UnsignedOrNone.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FunctionExtras.h"
@@ -49,6 +50,7 @@ class FileSystem;
namespace clang {
class DeclContext;
+class Diagnostic;
class DiagnosticBuilder;
class DiagnosticConsumer;
class IdentifierInfo;
@@ -228,6 +230,8 @@ class DiagStorageAllocator {
class DiagnosticsEngine : public RefCountedBase {
public:
/// The level of the diagnostic, after it has been through mapping.
+ // FIXME: Make this an alias for DiagnosticIDs::Level as soon as
+ // we can use 'using enum'.
enum Level {
Ignored = DiagnosticIDs::Ignored,
Note = DiagnosticIDs::Note,
@@ -420,10 +424,13 @@ class DiagnosticsEngine : public RefCountedBase {
bool empty() const { return Files.empty(); }
/// Clear out this map.
- void clear() {
+ void clear(bool Soft) {
+ // Just clear the cache when in soft mode.
Files.clear();
- FirstDiagState = CurDiagState = nullptr;
- CurDiagStateLoc = SourceLocation();
+ if (!Soft) {
+ FirstDiagState = CurDiagState = nullptr;
+ CurDiagStateLoc = SourceLocation();
+ }
}
/// Produce a debugging dump of the diagnostic state.
@@ -532,7 +539,7 @@ class DiagnosticsEngine : public RefCountedBase {
///
/// This is used to emit continuation diagnostics with the same level as the
/// diagnostic that they follow.
- DiagnosticIDs::Level LastDiagLevel;
+ Level LastDiagLevel;
/// Number of warnings reported
unsigned NumWarnings;
@@ -777,18 +784,16 @@ class DiagnosticsEngine : public RefCountedBase {
/// the middle of another diagnostic.
///
/// This can be used by clients who suppress diagnostics themselves.
- void setLastDiagnosticIgnored(bool Ignored) {
- if (LastDiagLevel == DiagnosticIDs::Fatal)
+ void setLastDiagnosticIgnored(bool IsIgnored) {
+ if (LastDiagLevel == Fatal)
FatalErrorOccurred = true;
- LastDiagLevel = Ignored ? DiagnosticIDs::Ignored : DiagnosticIDs::Warning;
+ LastDiagLevel = IsIgnored ? Ignored : Warning;
}
/// Determine whether the previous diagnostic was ignored. This can
/// be used by clients that want to determine whether notes attached to a
/// diagnostic will be suppressed.
- bool isLastDiagnosticIgnored() const {
- return LastDiagLevel == DiagnosticIDs::Ignored;
- }
+ bool isLastDiagnosticIgnored() const { return LastDiagLevel == Ignored; }
/// Controls whether otherwise-unmapped extension diagnostics are
/// mapped onto ignore/warning/error.
@@ -918,6 +923,10 @@ class DiagnosticsEngine : public RefCountedBase {
/// Reset the state of the diagnostic object to its initial configuration.
/// \param[in] soft - if true, doesn't reset the diagnostic mappings and state
void Reset(bool soft = false);
+ /// We keep a cache of FileIDs for diagnostics mapped by pragmas. These might
+ /// get invalidated when diagnostics engine is shared across different
+ /// compilations. Provide users with a way to reset that.
+ void ResetPragmas();
//===--------------------------------------------------------------------===//
// DiagnosticsEngine classification and reporting interfaces.
@@ -1024,9 +1033,10 @@ class DiagnosticsEngine : public RefCountedBase {
/// Used to report a diagnostic that is finally fully formed.
///
/// \returns true if the diagnostic was emitted, false if it was suppressed.
- bool ProcessDiag(const DiagnosticBuilder &DiagBuilder) {
- return Diags->ProcessDiag(*this, DiagBuilder);
- }
+ bool ProcessDiag(const DiagnosticBuilder &DiagBuilder);
+
+ /// Forward a diagnostic to the DiagnosticConsumer.
+ void Report(Level DiagLevel, const Diagnostic &Info);
/// @name Diagnostic Emission
/// @{
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 20fb47237c56f..29f6480ba935c 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -206,6 +206,8 @@ def err_drv_cannot_open_randomize_layout_seed_file : Error<
"cannot read randomize layout seed file '%0'">;
def err_drv_invalid_version_number : Error<
"invalid version number in '%0'">;
+def err_drv_invalid_version_number_inferred
+ : Error<"invalid version number '%0' inferred from '%1'">;
def err_drv_missing_version_number : Error<"missing version number in '%0'">;
def err_drv_kcfi_arity_unsupported_target : Error<
"target '%0' is unsupported by -fsanitize-kcfi-arity">;
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index beda73e675fc6..36fa3227fd6a6 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -806,32 +806,39 @@ def UniqueObjectDuplication : DiagGroup<"unique-object-duplication"> {
Warns when objects which are supposed to be globally unique might get duplicated
when built into a shared library.
-If an object with hidden visibility is built into a shared library, each instance
+This can occur to objects which are hidden from the dynamic linker, due to
+having hidden visibility (on posix) or lacking a dllimport/dllexport attribute
+(on windows). If such an object is built into a shared library, each instance
of the library will get its own copy. This can cause very subtle bugs if there was
only supposed to be one copy of the object in question: singletons aren't single,
changes to one object won't affect the others, the object's initializer will run
once per copy, etc.
Specifically, this warning fires when it detects an object which:
-1. Is defined as ``inline`` in a header file (so it might get compiled into multiple libaries), and
-2. Has external linkage (otherwise it's supposed to be duplicated), and
-3. Has hidden visibility.
+
+#. Is defined as ``inline`` in a header file (so it might get compiled into multiple libaries), and
+#. Has external linkage (otherwise it's supposed to be duplicated), and
+#. Has hidden visibility (posix) or lacks a dllimport/dllexport attribute (windows).
As well as one of the following:
-1. The object is mutable, or
-2. The object's initializer definitely has side effects.
+
+#. The object is mutable, or
+#. The object's initializer definitely has side effects.
The warning can be resolved by removing one of the conditions above. In rough
order of preference, this may be done by:
-1. Marking the object ``const`` (if possible)
-2. Moving the object's definition to a source file
-3. Giving the object non-hidden visibility, e.g. using ``__attribute((visibility("default")))``.
+
+#. Marking the object ``const`` (if possible)
+#. Moving the object's definition to a source file
+#. Making the object visible using ``__attribute((visibility("default")))``,
+ ``__declspec(dllimport)``, or ``__declspec(dllexport)``.
+
+When annotating an object with ``__declspec(dllimport)`` or ``__declspec(dllexport)``,
+take care to ensure that the object is only exported from one dll, and is imported
+everywhere else.
Note that for (2), all levels of a pointer variable must be constant;
``const int*`` will trigger the warning because the pointer itself is mutable.
-
-This warning is not yet implemented for Windows, since Windows uses
-import/export rules instead of visibility.
}];
}
diff --git a/clang/include/clang/Basic/DiagnosticIDs.h b/clang/include/clang/Basic/DiagnosticIDs.h
index 80d52a0d01112..2b095f0fd6741 100644
--- a/clang/include/clang/Basic/DiagnosticIDs.h
+++ b/clang/include/clang/Basic/DiagnosticIDs.h
@@ -483,18 +483,6 @@ class DiagnosticIDs : public RefCountedBase {
Class getDiagClass(unsigned DiagID) const;
- /// Used to report a diagnostic that is finally fully formed.
- ///
- /// \returns \c true if the diagnostic was emitted, \c false if it was
- /// suppressed.
- bool ProcessDiag(DiagnosticsEngine &Diag,
- const DiagnosticBuilder &DiagBuilder) const;
-
- /// Used to emit a diagnostic that is finally fully formed,
- /// ignoring suppression.
- void EmitDiag(DiagnosticsEngine &Diag, const DiagnosticBuilder &DiagBuilder,
- Level DiagLevel) const;
-
/// Whether the diagnostic may leave the AST in a state where some
/// invariants can break.
bool isUnrecoverable(unsigned DiagID) const;
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 3aa36ad59d0b9..6c30da376dafb 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1581,8 +1581,10 @@ def err_omp_unexpected_append_op : Error<
"unexpected operation specified in 'append_args' clause, expected 'interop'">;
def err_omp_unexpected_execution_modifier : Error<
"unexpected 'execution' modifier in non-executable context">;
-def err_omp_unknown_adjust_args_op : Error<
- "incorrect adjust_args type, expected 'need_device_ptr' or 'nothing'">;
+def err_omp_unknown_adjust_args_op
+ : Error<
+ "incorrect 'adjust_args' type, expected 'need_device_ptr'%select{|, "
+ "'need_device_addr',}0 or 'nothing'">;
def err_omp_declare_variant_wrong_clause : Error<
"expected %select{'match'|'match', 'adjust_args', or 'append_args'}0 clause "
"on 'omp declare variant' directive">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0f77083dac9df..979ff60b73b75 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1779,7 +1779,7 @@ def note_unsatisfied_trait_reason
"%HasArcLifetime{has an ARC lifetime qualifier}|"
"%VLA{is a variably-modified type}|"
"%VBase{has a virtual base %1}|"
- "%NotScalarOrClass{not %select{a|an array of objects of}1 scalar or "
+ "%NotScalarOrClass{is not %select{a|an array of objects of}1 scalar or "
"class type}|"
"%NTRBase{has a non-trivially-relocatable base %1}|"
"%NTRField{has a non-trivially-relocatable member %1 of type %2}|"
@@ -6263,14 +6263,19 @@ def warn_static_local_in_extern_inline : Warning<
def note_convert_inline_to_static : Note<
"use 'static' to give inline function %0 internal linkage">;
-def warn_possible_object_duplication_mutable : Warning<
- "%0 may be duplicated when built into a shared library: "
- "it is mutable, has hidden visibility, and external linkage">,
- InGroup, DefaultIgnore;
-def warn_possible_object_duplication_init : Warning<
- "initialization of %0 may run twice when built into a shared library: "
- "it has hidden visibility and external linkage">,
- InGroup, DefaultIgnore;
+def warn_possible_object_duplication_mutable
+ : Warning<"%0 may be duplicated when built into a shared library: "
+ "it is mutable, with external linkage and "
+ "%select{hidden visibility|no import/export annotation}1">,
+ InGroup,
+ DefaultIgnore;
+def warn_possible_object_duplication_init
+ : Warning<"initialization of %0 may run twice when built into a shared "
+ "library: "
+ "it has external linkage and "
+ "%select{hidden visibility|no import/export annotation}1">,
+ InGroup,
+ DefaultIgnore;
def ext_redefinition_of_typedef : ExtWarn<
"redefinition of typedef %0 is a C11 feature">,
diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def
index b0de65df7e397..2b1dc1e0121b2 100644
--- a/clang/include/clang/Basic/OpenMPKinds.def
+++ b/clang/include/clang/Basic/OpenMPKinds.def
@@ -214,6 +214,7 @@ OPENMP_ORIGINAL_SHARING_MODIFIER(default)
// Adjust-op kinds for the 'adjust_args' clause.
OPENMP_ADJUST_ARGS_KIND(nothing)
OPENMP_ADJUST_ARGS_KIND(need_device_ptr)
+OPENMP_ADJUST_ARGS_KIND(need_device_addr)
// Binding kinds for the 'bind' clause.
OPENMP_BIND_KIND(teams)
diff --git a/clang/include/clang/Basic/ProfileList.h b/clang/include/clang/Basic/ProfileList.h
index b4217e49c18a3..5338ef3992ade 100644
--- a/clang/include/clang/Basic/ProfileList.h
+++ b/clang/include/clang/Basic/ProfileList.h
@@ -49,17 +49,16 @@ class ProfileList {
~ProfileList();
bool isEmpty() const { return Empty; }
- ExclusionType getDefault(CodeGenOptions::ProfileInstrKind Kind) const;
+ ExclusionType getDefault(llvm::driver::ProfileInstrKind Kind) const;
std::optional
isFunctionExcluded(StringRef FunctionName,
- CodeGenOptions::ProfileInstrKind Kind) const;
+ llvm::driver::ProfileInstrKind Kind) const;
std::optional
isLocationExcluded(SourceLocation Loc,
- CodeGenOptions::ProfileInstrKind Kind) const;
+ llvm::driver::ProfileInstrKind Kind) const;
std::optional
- isFileExcluded(StringRef FileName,
- CodeGenOptions::ProfileInstrKind Kind) const;
+ isFileExcluded(StringRef FileName, llvm::driver::ProfileInstrKind Kind) const;
};
} // namespace clang
diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td
index 9526fa5808aa5..c9c173f5c7469 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -202,7 +202,6 @@ def ShuffleVectorExpr : StmtNode;
def ConvertVectorExpr : StmtNode;
def BlockExpr : StmtNode;
def OpaqueValueExpr : StmtNode;
-def TypoExpr : StmtNode;
def RecoveryExpr : StmtNode;
def BuiltinBitCastExpr : StmtNode;
def EmbedExpr : StmtNode;
diff --git a/clang/include/clang/Basic/riscv_vector.td b/clang/include/clang/Basic/riscv_vector.td
index 3e22bfb330af6..c6fd8a1a45fd1 100644
--- a/clang/include/clang/Basic/riscv_vector.td
+++ b/clang/include/clang/Basic/riscv_vector.td
@@ -2397,7 +2397,7 @@ let RequiredFeatures = ["zvfbfmin"] in {
}
defm vrgatherei16 : RVVOutBuiltinSet<"vrgatherei16_vv", "csilfd",
[["vv", "v", "vv(Log2EEW:4)Uv"]]>;
-let RequiredFeatures = ["zvfh"] in
+let RequiredFeatures = ["zvfhmin"] in
defm vrgatherei16 : RVVOutBuiltinSet<"vrgatherei16_vv", "x",
[["vv", "v", "vv(Log2EEW:4)Uv"]]>;
// unsigned type
diff --git a/clang/include/clang/Basic/riscv_vector_common.td b/clang/include/clang/Basic/riscv_vector_common.td
index c6753978274a0..e3d589699645b 100644
--- a/clang/include/clang/Basic/riscv_vector_common.td
+++ b/clang/include/clang/Basic/riscv_vector_common.td
@@ -593,7 +593,7 @@ let UnMaskedPolicyScheme = HasPolicyOperand,
multiclass RVVSlideUpBuiltinSet {
defm "" : RVVOutBuiltinSet;
- let RequiredFeatures = ["zvfh"] in
+ let RequiredFeatures = ["zvfhmin"] in
defm "" : RVVOutBuiltinSet;
defm "" : RVVOutBuiltinSet;
- let RequiredFeatures = ["zvfh"] in
+ let RequiredFeatures = ["zvfhmin"] in
defm "" : RVVOutBuiltinSet;
defm "" : RVVOutBuiltinSet(loc, val, dst, align);
}
+ [[nodiscard]] cir::GlobalOp createGlobal(mlir::ModuleOp mlirModule,
+ mlir::Location loc,
+ mlir::StringRef name,
+ mlir::Type type,
+ cir::GlobalLinkageKind linkage) {
+ mlir::OpBuilder::InsertionGuard guard(*this);
+ setInsertionPointToStart(mlirModule.getBody());
+ return create(loc, name, type, linkage);
+ }
+
cir::GetMemberOp createGetMember(mlir::Location loc, mlir::Type resultTy,
mlir::Value base, llvm::StringRef name,
unsigned index) {
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index d22d265e82425..b48f4ed461ccb 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -307,9 +307,9 @@ def ConstComplexAttr : CIR_Attr<"ConstComplex", "const_complex",
);
let builders = [
- AttrBuilderWithInferredContext<(ins "cir::ComplexType":$type,
- "mlir::TypedAttr":$real,
+ AttrBuilderWithInferredContext<(ins "mlir::TypedAttr":$real,
"mlir::TypedAttr":$imag), [{
+ auto type = cir::ComplexType::get(real.getType());
return $_get(type.getContext(), type, real, imag);
}]>,
];
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 565c0676773e6..8dd1f0ce361d7 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2059,6 +2059,7 @@ def VecCreateOp : CIR_Op<"vec.create", [Pure]> {
}];
let hasVerifier = 1;
+ let hasFolder = 1;
}
//===----------------------------------------------------------------------===//
@@ -2154,6 +2155,8 @@ def VecCmpOp : CIR_Op<"vec.cmp", [Pure, SameTypeOperands]> {
`(` $kind `,` $lhs `,` $rhs `)` `:` qualified(type($lhs)) `,`
qualified(type($result)) attr-dict
}];
+
+ let hasFolder = 1;
}
//===----------------------------------------------------------------------===//
@@ -2277,6 +2280,38 @@ def VecTernaryOp : CIR_Op<"vec.ternary",
let hasFolder = 1;
}
+//===----------------------------------------------------------------------===//
+// VecSplatOp
+//===----------------------------------------------------------------------===//
+
+def VecSplatOp : CIR_Op<"vec.splat", [Pure,
+ TypesMatchWith<"type of 'value' matches element type of 'result'", "result",
+ "value", "cast($_self).getElementType()">]> {
+
+ let summary = "Convert a scalar into a vector";
+ let description = [{
+ The `cir.vec.splat` operation creates a vector value from a scalar value.
+ All elements of the vector have the same value, that of the given scalar.
+
+ It's a separate operation from `cir.vec.create` because more
+ efficient LLVM IR can be generated for it, and because some optimization and
+ analysis passes can benefit from knowing that all elements of the vector
+ have the same value.
+
+ ```mlir
+ %value = cir.const #cir.int<3> : !s32i
+ %value_vec = cir.vec.splat %value : !s32i, !cir.vector<4 x !s32i>
+ ```
+ }];
+
+ let arguments = (ins CIR_VectorElementType:$value);
+ let results = (outs CIR_VectorType:$result);
+
+ let assemblyFormat = [{
+ $value `:` type($value) `,` qualified(type($result)) attr-dict
+ }];
+}
+
//===----------------------------------------------------------------------===//
// BaseClassAddrOp
//===----------------------------------------------------------------------===//
@@ -2320,4 +2355,36 @@ def BaseClassAddrOp : CIR_Op<"base_class_addr"> {
}];
}
+//===----------------------------------------------------------------------===//
+// ComplexCreateOp
+//===----------------------------------------------------------------------===//
+
+def ComplexCreateOp : CIR_Op<"complex.create", [Pure, SameTypeOperands]> {
+ let summary = "Create a complex value from its real and imaginary parts";
+ let description = [{
+ The `cir.complex.create` operation takes two operands that represent the
+ real and imaginary part of a complex number, and yields the complex number.
+
+ ```mlir
+ %0 = cir.const #cir.fp<1.000000e+00> : !cir.double
+ %1 = cir.const #cir.fp<2.000000e+00> : !cir.double
+ %2 = cir.complex.create %0, %1 : !cir.double -> !cir.complex
+ ```
+ }];
+
+ let results = (outs CIR_ComplexType:$result);
+ let arguments = (ins
+ CIR_AnyIntOrFloatType:$real,
+ CIR_AnyIntOrFloatType:$imag
+ );
+
+ let assemblyFormat = [{
+ $real `,` $imag
+ `:` qualified(type($real)) `->` qualified(type($result)) attr-dict
+ }];
+
+ let hasVerifier = 1;
+ let hasFolder = 1;
+}
+
#endif // CLANG_CIR_DIALECT_IR_CIROPS_TD
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index fb96976075130..41d7d725a09e0 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -600,7 +600,8 @@ def CIRRecordType : Type<
def CIR_AnyType : AnyTypeOf<[
CIR_VoidType, CIR_BoolType, CIR_ArrayType, CIR_VectorType, CIR_IntType,
- CIR_AnyFloatType, CIR_PointerType, CIR_FuncType, CIR_RecordType
+ CIR_AnyFloatType, CIR_PointerType, CIR_FuncType, CIR_RecordType,
+ CIR_ComplexType
]>;
#endif // MLIR_CIR_DIALECT_CIR_TYPES
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 72d882beb2244..3dc28e6f2e5bf 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -81,9 +81,9 @@ struct MissingFeatures {
static bool opFuncCPUAndFeaturesAttributes() { return false; }
static bool opFuncSection() { return false; }
static bool opFuncSetComdat() { return false; }
+ static bool opFuncAttributesForDefinition() { return false; }
// CallOp handling
- static bool opCallBuiltinFunc() { return false; }
static bool opCallPseudoDtor() { return false; }
static bool opCallAggregateArgs() { return false; }
static bool opCallPaddingArgs() { return false; }
@@ -172,6 +172,11 @@ struct MissingFeatures {
static bool astVarDeclInterface() { return false; }
static bool stackSaveOp() { return false; }
static bool aggValueSlot() { return false; }
+ static bool aggValueSlotMayOverlap() { return false; }
+ static bool aggValueSlotVolatile() { return false; }
+ static bool aggValueSlotDestructedFlag() { return false; }
+ static bool aggValueSlotAlias() { return false; }
+ static bool aggValueSlotGC() { return false; }
static bool generateDebugInfo() { return false; }
static bool pointerOverflowSanitizer() { return false; }
static bool fpConstraints() { return false; }
@@ -222,6 +227,16 @@ struct MissingFeatures {
static bool instrumentation() { return false; }
static bool cleanupAfterErrorDiags() { return false; }
static bool cxxRecordStaticMembers() { return false; }
+ static bool isMemcpyEquivalentSpecialMember() { return false; }
+ static bool isTrivialCtorOrDtor() { return false; }
+ static bool implicitConstructorArgs() { return false; }
+ static bool intrinsics() { return false; }
+ static bool attributeNoBuiltin() { return false; }
+ static bool thunks() { return false; }
+ static bool runCleanupsScope() { return false; }
+ static bool lowerAggregateLoadStore() { return false; }
+ static bool dataLayoutTypeAllocSize() { return false; }
+ static bool asmLabelAttr() { return false; }
// Missing types
static bool dataMemberType() { return false; }
@@ -237,7 +252,6 @@ struct MissingFeatures {
// Future CIR operations
static bool awaitOp() { return false; }
static bool callOp() { return false; }
- static bool complexCreateOp() { return false; }
static bool complexImagOp() { return false; }
static bool complexRealOp() { return false; }
static bool ifOp() { return false; }
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 3582efd7721b0..0ffd8c40da7da 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1772,7 +1772,7 @@ def fmcdc_max_test_vectors_EQ : Joined<["-"], "fmcdc-max-test-vectors=">,
HelpText<"Maximum number of test vectors in MC/DC coverage">,
MarshallingInfoInt, "0x7FFFFFFE">;
def fprofile_generate : Flag<["-"], "fprofile-generate">,
- Group, Visibility<[ClangOption, CLOption]>,
+ Group, Visibility<[ClangOption, CLOption, FlangOption, FC1Option]>,
HelpText<"Generate instrumented code to collect execution counts into default.profraw (overridden by LLVM_PROFILE_FILE env var)">;
def fprofile_generate_EQ : Joined<["-"], "fprofile-generate=">,
Group, Visibility<[ClangOption, CLOption]>,
@@ -1789,7 +1789,7 @@ def fprofile_use : Flag<["-"], "fprofile-use">, Group,
Visibility<[ClangOption, CLOption]>, Alias;
def fprofile_use_EQ : Joined<["-"], "fprofile-use=">,
Group,
- Visibility<[ClangOption, CLOption]>,
+ Visibility<[ClangOption, CLOption, FlangOption, FC1Option]>,
MetaVarName<"">,
HelpText<"Use instrumentation data for profile-guided optimization. If pathname is a directory, it reads from /default.profdata. Otherwise, it reads from file .">;
def fno_profile_instr_generate : Flag<["-"], "fno-profile-instr-generate">,
@@ -2167,11 +2167,14 @@ defm assume_nothrow_exception_dtor: BoolFOption<"assume-nothrow-exception-dtor",
LangOpts<"AssumeNothrowExceptionDtor">, DefaultFalse,
PosFlag,
NegFlag>;
-defm winx64_eh_unwindv2 : BoolFOption<"winx64-eh-unwindv2",
- CodeGenOpts<"WinX64EHUnwindV2">, DefaultFalse,
- PosFlag,
- NegFlag,
- BothFlags<[], [ClangOption], " unwind v2 (epilog) information for x64 Windows">>;
+def winx64_eh_unwindv2
+ : Joined<["-"], "fwinx64-eh-unwindv2=">, Group,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Generate unwind v2 (epilog) information for x64 Windows">,
+ Values<"disabled,best-effort,required">,
+ NormalizedValues<["Disabled", "BestEffort", "Required"]>,
+ NormalizedValuesScope<"llvm::WinX64EHUnwindV2Mode">,
+ MarshallingInfoEnum, "Disabled">;
def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">, Group,
Visibility<[ClangOption, CLOption]>,
HelpText<"Allows control over excess precision on targets where native "
@@ -3348,6 +3351,9 @@ defm pch_codegen: OptInCC1FFlag<"pch-codegen", "Generate ", "Do not generate ",
"code for uses of this PCH that assumes an explicit object file will be built for the PCH">;
defm pch_debuginfo: OptInCC1FFlag<"pch-debuginfo", "Generate ", "Do not generate ",
"debug info for types in an object file built from this PCH and do not generate them elsewhere">;
+def ignore_pch : Flag<["-"], "ignore-pch">, Group,
+ Visibility<[ClangOption]>,
+ HelpText<"Disable precompiled headers, overrides -emit-pch and -include-pch">;
def fimplicit_module_maps : Flag <["-"], "fimplicit-module-maps">, Group,
Visibility<[ClangOption, CC1Option, CLOption]>,
@@ -3473,8 +3479,9 @@ def fveclib : Joined<["-"], "fveclib=">, Group,
Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
HelpText<"Use the given vector functions library">,
HelpTextForVariants<[ClangOption, CC1Option],
- "Use the given vector functions library. "
- "Note: -fveclib={ArmPL,SLEEF} implies -fno-math-errno">,
+ "Use the given vector functions library.\n"
+ " Note: -fveclib={ArmPL,SLEEF,libmvec} implies -fno-math-errno.\n"
+ " Note: -fveclib=libmvec on AArch64 requires GLIBC 2.40 or newer.">,
Values<"Accelerate,libmvec,MASSV,SVML,SLEEF,Darwin_libsystem_m,ArmPL,AMDLIBM,none">,
NormalizedValuesScope<"llvm::driver::VectorLibrary">,
NormalizedValues<["Accelerate", "LIBMVEC", "MASSV", "SVML", "SLEEF",
@@ -4927,8 +4934,10 @@ def ffuchsia_api_level_EQ : Joined<["-"], "ffuchsia-api-level=">,
HelpText<"Set Fuchsia API level">,
MarshallingInfoInt>;
def mmacos_version_min_EQ : Joined<["-"], "mmacos-version-min=">,
+ Visibility<[ClangOption, CC1Option, FlangOption]>,
Group, HelpText<"Set macOS deployment target">;
def : Joined<["-"], "mmacosx-version-min=">,
+ Visibility<[ClangOption, CC1Option, FC1Option, FlangOption]>,
Group, Alias;
def mms_bitfields : Flag<["-"], "mms-bitfields">, Group,
Visibility<[ClangOption, CC1Option]>,
@@ -5054,9 +5063,10 @@ def mrvv_vector_bits_EQ : Joined<["-"], "mrvv-vector-bits=">, Group,
Visibility<[ClangOption, FlangOption]>,
HelpText<"Specify the size in bits of an RVV vector register">,
DocBrief;
def mfix_cortex_a53_835769 : Flag<["-"], "mfix-cortex-a53-835769">,
Group,
- HelpText<"Workaround Cortex-A53 erratum 835769 (AArch64 only)">;
+ HelpText<"Work around Cortex-A53 erratum 835769 (AArch64 only)">;
def mno_fix_cortex_a53_835769 : Flag<["-"], "mno-fix-cortex-a53-835769">,
Group,
- HelpText<"Don't workaround Cortex-A53 erratum 835769 (AArch64 only)">;
+ HelpText<"Don't work around Cortex-A53 erratum 835769 (AArch64 only)">;
+def mfix_cortex_a53_843419 : Flag<["-"], "mfix-cortex-a53-843419">,
+ Group,
+ HelpText<"Work around Cortex-A53 erratum 843419 (AArch64 only)">;
+def mno_fix_cortex_a53_843419 : Flag<["-"], "mno-fix-cortex-a53-843419">,
+ Group,
+ HelpText<"Don't work around Cortex-A53 erratum 843419 (AArch64 only)">;
def mmark_bti_property : Flag<["-"], "mmark-bti-property">,
Group,
HelpText<"Add .note.gnu.property with BTI to assembly files (AArch64 only)">;
@@ -7759,7 +7775,7 @@ def fpatchable_function_entry_section_EQ
MarshallingInfoString>;
def fprofile_instrument_EQ : Joined<["-"], "fprofile-instrument=">,
HelpText<"Enable PGO instrumentation">, Values<"none,clang,llvm,csllvm,sample-coldcov">,
- NormalizedValuesScope<"CodeGenOptions">,
+ NormalizedValuesScope<"llvm::driver::ProfileInstrKind">,
NormalizedValues<["ProfileNone", "ProfileClangInstr", "ProfileIRInstr", "ProfileCSIRInstr", "ProfileIRSampleColdCov"]>,
MarshallingInfoEnum, "ProfileNone">;
def fprofile_instrument_path_EQ : Joined<["-"], "fprofile-instrument-path=">,
@@ -8969,7 +8985,9 @@ def _SLASH_volatile_Group : OptionGroup<"">,
Group;
def _SLASH_d2epilogunwind : CLFlag<"d2epilogunwind">,
- HelpText<"Enable unwind v2 (epilog) information for x64 Windows">;
+ HelpText<"Best effort generate unwind v2 (epilog) information for x64 Windows">;
+def _SLASH_d2epilogunwindrequirev2 : CLFlag<"d2epilogunwindrequirev2">,
+ HelpText<"Require generation of unwind v2 (epilog) information for x64 Windows">;
def _SLASH_EH : CLJoined<"EH">, HelpText<"Set exception handling model">;
def _SLASH_EP : CLFlag<"EP">,
HelpText<"Disable linemarker output and preprocess to stdout">;
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 0b2fab4a45c96..a47e23ffbd357 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -290,9 +290,7 @@ class Parser : public CodeCompletionHandler {
return ConsumeToken();
}
- SourceLocation getEndOfPreviousToken() {
- return PP.getLocForEndOfToken(PrevTokLocation);
- }
+ SourceLocation getEndOfPreviousToken() const;
/// GetLookAheadToken - This peeks ahead N tokens and returns that token
/// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1)
@@ -3600,7 +3598,7 @@ class Parser : public CodeCompletionHandler {
/// keyword.
bool isClassCompatibleKeyword(Token Tok) const;
- void ParseMicrosoftRootSignatureAttributeArgs(ParsedAttributes &Attrs);
+ void ParseHLSLRootSignatureAttributeArgs(ParsedAttributes &Attrs);
///@}
@@ -4171,8 +4169,7 @@ class Parser : public CodeCompletionHandler {
bool ParseExpressionList(SmallVectorImpl &Exprs,
llvm::function_ref ExpressionStarts =
llvm::function_ref(),
- bool FailImmediatelyOnInvalidExpr = false,
- bool EarlyTypoCorrection = false);
+ bool FailImmediatelyOnInvalidExpr = false);
/// ParseSimpleExpressionList - A simple comma-separated list of expressions,
/// used for misc language extensions.
diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h
index 9e050ab9a620e..6b3c5a173417a 100644
--- a/clang/include/clang/Sema/ParsedAttr.h
+++ b/clang/include/clang/Sema/ParsedAttr.h
@@ -204,10 +204,9 @@ class ParsedAttr final
/// Constructor for attributes with expression arguments.
ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- ArgsUnion *args, unsigned numArgs, Form formUsed,
- SourceLocation ellipsisLoc)
- : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed),
+ AttributeScopeInfo scope, ArgsUnion *args, unsigned numArgs,
+ Form formUsed, SourceLocation ellipsisLoc)
+ : AttributeCommonInfo(attrName, scope, attrRange, formUsed),
EllipsisLoc(ellipsisLoc), NumArgs(numArgs), Invalid(false),
UsedAsTypeAttr(false), IsAvailability(false),
IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
@@ -219,14 +218,14 @@ class ParsedAttr final
/// Constructor for availability attributes.
ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierLoc *Parm, const AvailabilityChange &introduced,
+ AttributeScopeInfo scope, IdentifierLoc *Parm,
+ const AvailabilityChange &introduced,
const AvailabilityChange &deprecated,
const AvailabilityChange &obsoleted, SourceLocation unavailable,
const Expr *messageExpr, Form formUsed, SourceLocation strict,
const Expr *replacementExpr, const IdentifierLoc *environmentLoc)
- : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed),
- NumArgs(1), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
+ : AttributeCommonInfo(attrName, scope, attrRange, formUsed), NumArgs(1),
+ Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
HasProcessingCache(false), IsPragmaClangAttribute(false),
UnavailableLoc(unavailable), MessageExpr(messageExpr),
@@ -240,14 +239,13 @@ class ParsedAttr final
/// Constructor for objc_bridge_related attributes.
ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierLoc *Parm1, IdentifierLoc *Parm2, IdentifierLoc *Parm3,
- Form formUsed)
- : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed),
- NumArgs(3), Invalid(false), UsedAsTypeAttr(false),
- IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
- HasParsedType(false), HasProcessingCache(false),
- IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) {
+ AttributeScopeInfo scope, IdentifierLoc *Parm1,
+ IdentifierLoc *Parm2, IdentifierLoc *Parm3, Form formUsed)
+ : AttributeCommonInfo(attrName, scope, attrRange, formUsed), NumArgs(3),
+ Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
+ HasProcessingCache(false), IsPragmaClangAttribute(false),
+ Info(ParsedAttrInfo::get(*this)) {
ArgsUnion *Args = getArgsBuffer();
Args[0] = Parm1;
Args[1] = Parm2;
@@ -256,14 +254,14 @@ class ParsedAttr final
/// Constructor for type_tag_for_datatype attribute.
ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierLoc *ArgKind, ParsedType matchingCType,
- bool layoutCompatible, bool mustBeNull, Form formUsed)
- : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed),
- NumArgs(1), Invalid(false), UsedAsTypeAttr(false),
- IsAvailability(false), IsTypeTagForDatatype(true), IsProperty(false),
- HasParsedType(false), HasProcessingCache(false),
- IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) {
+ AttributeScopeInfo scope, IdentifierLoc *ArgKind,
+ ParsedType matchingCType, bool layoutCompatible, bool mustBeNull,
+ Form formUsed)
+ : AttributeCommonInfo(attrName, scope, attrRange, formUsed), NumArgs(1),
+ Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false),
+ HasProcessingCache(false), IsPragmaClangAttribute(false),
+ Info(ParsedAttrInfo::get(*this)) {
ArgsUnion PVal(ArgKind);
memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
detail::TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
@@ -274,9 +272,9 @@ class ParsedAttr final
/// Constructor for attributes with a single type argument.
ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- ParsedType typeArg, Form formUsed, SourceLocation ellipsisLoc)
- : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed),
+ AttributeScopeInfo scope, ParsedType typeArg, Form formUsed,
+ SourceLocation ellipsisLoc)
+ : AttributeCommonInfo(attrName, scope, attrRange, formUsed),
EllipsisLoc(ellipsisLoc), NumArgs(0), Invalid(false),
UsedAsTypeAttr(false), IsAvailability(false),
IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true),
@@ -287,13 +285,13 @@ class ParsedAttr final
/// Constructor for microsoft __declspec(property) attribute.
ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *getterId, IdentifierInfo *setterId, Form formUsed)
- : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed),
- NumArgs(0), Invalid(false), UsedAsTypeAttr(false),
- IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(true),
- HasParsedType(false), HasProcessingCache(false),
- IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) {
+ AttributeScopeInfo scope, IdentifierInfo *getterId,
+ IdentifierInfo *setterId, Form formUsed)
+ : AttributeCommonInfo(attrName, scope, attrRange, formUsed), NumArgs(0),
+ Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false),
+ HasProcessingCache(false), IsPragmaClangAttribute(false),
+ Info(ParsedAttrInfo::get(*this)) {
new (&getPropertyDataBuffer()) detail::PropertyData(getterId, setterId);
}
@@ -735,21 +733,21 @@ class AttributePool {
void takeFrom(ParsedAttributesView &List, AttributePool &Pool);
ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- ArgsUnion *args, unsigned numArgs, ParsedAttr::Form form,
+ AttributeScopeInfo scope, ArgsUnion *args,
+ unsigned numArgs, ParsedAttr::Form form,
SourceLocation ellipsisLoc = SourceLocation()) {
void *memory = allocate(
ParsedAttr::totalSizeToAlloc(numArgs, 0, 0, 0,
0));
- return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
- args, numArgs, form, ellipsisLoc));
+ return add(new (memory) ParsedAttr(attrName, attrRange, scope, args,
+ numArgs, form, ellipsisLoc));
}
ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierLoc *Param, const AvailabilityChange &introduced,
+ AttributeScopeInfo scope, IdentifierLoc *Param,
+ const AvailabilityChange &introduced,
const AvailabilityChange &deprecated,
const AvailabilityChange &obsoleted,
SourceLocation unavailable, const Expr *MessageExpr,
@@ -757,58 +755,54 @@ class AttributePool {
const Expr *ReplacementExpr,
IdentifierLoc *EnvironmentLoc) {
void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
- return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
- Param, introduced, deprecated, obsoleted,
- unavailable, MessageExpr, form, strict,
- ReplacementExpr, EnvironmentLoc));
+ return add(new (memory)
+ ParsedAttr(attrName, attrRange, scope, Param, introduced,
+ deprecated, obsoleted, unavailable, MessageExpr,
+ form, strict, ReplacementExpr, EnvironmentLoc));
}
ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierLoc *Param1, IdentifierLoc *Param2,
- IdentifierLoc *Param3, ParsedAttr::Form form) {
+ AttributeScopeInfo scope, IdentifierLoc *Param1,
+ IdentifierLoc *Param2, IdentifierLoc *Param3,
+ ParsedAttr::Form form) {
void *memory = allocate(
ParsedAttr::totalSizeToAlloc(3, 0, 0, 0, 0));
- return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
- Param1, Param2, Param3, form));
+ return add(new (memory) ParsedAttr(attrName, attrRange, scope, Param1,
+ Param2, Param3, form));
}
- ParsedAttr *
- createTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierLoc *argumentKind,
- ParsedType matchingCType, bool layoutCompatible,
- bool mustBeNull, ParsedAttr::Form form) {
+ ParsedAttr *createTypeTagForDatatype(
+ IdentifierInfo *attrName, SourceRange attrRange, AttributeScopeInfo scope,
+ IdentifierLoc *argumentKind, ParsedType matchingCType,
+ bool layoutCompatible, bool mustBeNull, ParsedAttr::Form form) {
void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize);
- return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
- argumentKind, matchingCType,
- layoutCompatible, mustBeNull, form));
+ return add(new (memory) ParsedAttr(attrName, attrRange, scope, argumentKind,
+ matchingCType, layoutCompatible,
+ mustBeNull, form));
}
ParsedAttr *createTypeAttribute(IdentifierInfo *attrName,
SourceRange attrRange,
- IdentifierInfo *scopeName,
- SourceLocation scopeLoc, ParsedType typeArg,
+ AttributeScopeInfo scope, ParsedType typeArg,
ParsedAttr::Form formUsed,
SourceLocation ellipsisLoc) {
void *memory = allocate(
ParsedAttr::totalSizeToAlloc(0, 0, 0, 1, 0));
- return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
- typeArg, formUsed, ellipsisLoc));
+ return add(new (memory) ParsedAttr(attrName, attrRange, scope, typeArg,
+ formUsed, ellipsisLoc));
}
ParsedAttr *
createPropertyAttribute(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *getterId, IdentifierInfo *setterId,
- ParsedAttr::Form formUsed) {
+ AttributeScopeInfo scope, IdentifierInfo *getterId,
+ IdentifierInfo *setterId, ParsedAttr::Form formUsed) {
void *memory = allocate(AttributeFactory::PropertyAllocSize);
- return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
- getterId, setterId, formUsed));
+ return add(new (memory) ParsedAttr(attrName, attrRange, scope, getterId,
+ setterId, formUsed));
}
};
@@ -982,19 +976,19 @@ class ParsedAttributes : public ParsedAttributesView {
/// Add attribute with expression arguments.
ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- ArgsUnion *args, unsigned numArgs, ParsedAttr::Form form,
+ AttributeScopeInfo scope, ArgsUnion *args,
+ unsigned numArgs, ParsedAttr::Form form,
SourceLocation ellipsisLoc = SourceLocation()) {
- ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc,
- args, numArgs, form, ellipsisLoc);
+ ParsedAttr *attr = pool.create(attrName, attrRange, scope, args, numArgs,
+ form, ellipsisLoc);
addAtEnd(attr);
return attr;
}
/// Add availability attribute.
ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierLoc *Param, const AvailabilityChange &introduced,
+ AttributeScopeInfo scope, IdentifierLoc *Param,
+ const AvailabilityChange &introduced,
const AvailabilityChange &deprecated,
const AvailabilityChange &obsoleted,
SourceLocation unavailable, const Expr *MessageExpr,
@@ -1002,33 +996,31 @@ class ParsedAttributes : public ParsedAttributesView {
const Expr *ReplacementExpr,
IdentifierLoc *EnvironmentLoc) {
ParsedAttr *attr =
- pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced,
- deprecated, obsoleted, unavailable, MessageExpr, form,
- strict, ReplacementExpr, EnvironmentLoc);
+ pool.create(attrName, attrRange, scope, Param, introduced, deprecated,
+ obsoleted, unavailable, MessageExpr, form, strict,
+ ReplacementExpr, EnvironmentLoc);
addAtEnd(attr);
return attr;
}
/// Add objc_bridge_related attribute.
ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierLoc *Param1, IdentifierLoc *Param2,
- IdentifierLoc *Param3, ParsedAttr::Form form) {
- ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc,
- Param1, Param2, Param3, form);
+ AttributeScopeInfo scope, IdentifierLoc *Param1,
+ IdentifierLoc *Param2, IdentifierLoc *Param3,
+ ParsedAttr::Form form) {
+ ParsedAttr *attr =
+ pool.create(attrName, attrRange, scope, Param1, Param2, Param3, form);
addAtEnd(attr);
return attr;
}
/// Add type_tag_for_datatype attribute.
- ParsedAttr *
- addNewTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierLoc *argumentKind,
- ParsedType matchingCType, bool layoutCompatible,
- bool mustBeNull, ParsedAttr::Form form) {
+ ParsedAttr *addNewTypeTagForDatatype(
+ IdentifierInfo *attrName, SourceRange attrRange, AttributeScopeInfo scope,
+ IdentifierLoc *argumentKind, ParsedType matchingCType,
+ bool layoutCompatible, bool mustBeNull, ParsedAttr::Form form) {
ParsedAttr *attr = pool.createTypeTagForDatatype(
- attrName, attrRange, scopeName, scopeLoc, argumentKind, matchingCType,
+ attrName, attrRange, scope, argumentKind, matchingCType,
layoutCompatible, mustBeNull, form);
addAtEnd(attr);
return attr;
@@ -1036,12 +1028,11 @@ class ParsedAttributes : public ParsedAttributesView {
/// Add an attribute with a single type argument.
ParsedAttr *addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- ParsedType typeArg, ParsedAttr::Form formUsed,
+ AttributeScopeInfo scope, ParsedType typeArg,
+ ParsedAttr::Form formUsed,
SourceLocation ellipsisLoc = SourceLocation()) {
- ParsedAttr *attr =
- pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc,
- typeArg, formUsed, ellipsisLoc);
+ ParsedAttr *attr = pool.createTypeAttribute(attrName, attrRange, scope,
+ typeArg, formUsed, ellipsisLoc);
addAtEnd(attr);
return attr;
}
@@ -1049,11 +1040,10 @@ class ParsedAttributes : public ParsedAttributesView {
/// Add microsoft __delspec(property) attribute.
ParsedAttr *
addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange,
- IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *getterId, IdentifierInfo *setterId,
- ParsedAttr::Form formUsed) {
+ AttributeScopeInfo scope, IdentifierInfo *getterId,
+ IdentifierInfo *setterId, ParsedAttr::Form formUsed) {
ParsedAttr *attr = pool.createPropertyAttribute(
- attrName, attrRange, scopeName, scopeLoc, getterId, setterId, formUsed);
+ attrName, attrRange, scope, getterId, setterId, formUsed);
addAtEnd(attr);
return attr;
}
diff --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h
index ad12a3d73413b..07b9e1bc10f5a 100644
--- a/clang/include/clang/Sema/Scope.h
+++ b/clang/include/clang/Sema/Scope.h
@@ -427,6 +427,17 @@ class Scope {
return false;
}
+ /// isInObjcMethodScope - Return true if this scope is, or is contained, in an
+ /// C function body.
+ bool isInCFunctionScope() const {
+ for (const Scope *S = this; S; S = S->getParent()) {
+ if (S->isFunctionScope())
+ return true;
+ }
+
+ return false;
+ }
+
/// isInObjcMethodScope - Return true if this scope is, or is contained in, an
/// Objective-C method body. Note that this method is not constant time.
bool isInObjcMethodScope() const {
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0dad07e55a820..29452bb37260d 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -6713,10 +6713,6 @@ class Sema final : public SemaBase {
/// this expression evaluation context.
unsigned NumCleanupObjects;
- /// The number of typos encountered during this expression evaluation
- /// context (i.e. the number of TypoExprs created).
- unsigned NumTypos;
-
MaybeODRUseExprSet SavedMaybeODRUseExprs;
/// The lambdas that are present within this context, if it
@@ -6813,7 +6809,7 @@ class Sema final : public SemaBase {
Decl *ManglingContextDecl,
ExpressionKind ExprContext)
: Context(Context), ParentCleanup(ParentCleanup),
- NumCleanupObjects(NumCleanupObjects), NumTypos(0),
+ NumCleanupObjects(NumCleanupObjects),
ManglingContextDecl(ManglingContextDecl), ExprContext(ExprContext),
InDiscardedStatement(false), InImmediateFunctionContext(false),
InImmediateEscalatingFunctionContext(false) {}
@@ -7146,8 +7142,7 @@ class Sema final : public SemaBase {
CorrectionCandidateCallback &CCC,
TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
ArrayRef Args = {},
- DeclContext *LookupCtx = nullptr,
- TypoExpr **Out = nullptr);
+ DeclContext *LookupCtx = nullptr);
/// If \p D cannot be odr-used in the current expression evaluation context,
/// return a reason explaining why. Otherwise, return NOUR_None.
@@ -8748,40 +8743,6 @@ class Sema final : public SemaBase {
ExprResult CheckUnevaluatedOperand(Expr *E);
- /// Process any TypoExprs in the given Expr and its children,
- /// generating diagnostics as appropriate and returning a new Expr if there
- /// were typos that were all successfully corrected and ExprError if one or
- /// more typos could not be corrected.
- ///
- /// \param E The Expr to check for TypoExprs.
- ///
- /// \param InitDecl A VarDecl to avoid because the Expr being corrected is its
- /// initializer.
- ///
- /// \param RecoverUncorrectedTypos If true, when typo correction fails, it
- /// will rebuild the given Expr with all TypoExprs degraded to RecoveryExprs.
- ///
- /// \param Filter A function applied to a newly rebuilt Expr to determine if
- /// it is an acceptable/usable result from a single combination of typo
- /// corrections. As long as the filter returns ExprError, different
- /// combinations of corrections will be tried until all are exhausted.
- ExprResult CorrectDelayedTyposInExpr(
- Expr *E, VarDecl *InitDecl = nullptr,
- bool RecoverUncorrectedTypos = false,
- llvm::function_ref Filter =
- [](Expr *E) -> ExprResult { return E; });
-
- ExprResult CorrectDelayedTyposInExpr(
- ExprResult ER, VarDecl *InitDecl = nullptr,
- bool RecoverUncorrectedTypos = false,
- llvm::function_ref Filter =
- [](Expr *E) -> ExprResult { return E; }) {
- return ER.isInvalid()
- ? ER
- : CorrectDelayedTyposInExpr(ER.get(), InitDecl,
- RecoverUncorrectedTypos, Filter);
- }
-
IfExistsResult
CheckMicrosoftIfExistsSymbol(Scope *S, CXXScopeSpec &SS,
const DeclarationNameInfo &TargetNameInfo);
@@ -9283,12 +9244,6 @@ class Sema final : public SemaBase {
/// for C++ records.
llvm::FoldingSet SpecialMemberCache;
- /// Holds TypoExprs that are created from `createDelayedTypo`. This is used by
- /// `TransformTypos` in order to keep track of any TypoExprs that are created
- /// recursively during typo correction and wipe them away if the correction
- /// fails.
- llvm::SmallVector TypoExprs;
-
enum class AcceptableKind { Visible, Reachable };
// Members have to be NamespaceDecl* or TranslationUnitDecl*.
@@ -9376,10 +9331,6 @@ class Sema final : public SemaBase {
bool VolatileArg, bool RValueThis, bool ConstThis,
bool VolatileThis);
- typedef std::function TypoDiagnosticGenerator;
- typedef std::function
- TypoRecoveryCallback;
-
RedeclarationKind forRedeclarationInCurContext() const;
/// Look up a name, looking for a single declaration. Return
@@ -9733,51 +9684,6 @@ class Sema final : public SemaBase {
const ObjCObjectPointerType *OPT = nullptr,
bool RecordFailure = true);
- /// Try to "correct" a typo in the source code by finding
- /// visible declarations whose names are similar to the name that was
- /// present in the source code.
- ///
- /// \param TypoName the \c DeclarationNameInfo structure that contains
- /// the name that was present in the source code along with its location.
- ///
- /// \param LookupKind the name-lookup criteria used to search for the name.
- ///
- /// \param S the scope in which name lookup occurs.
- ///
- /// \param SS the nested-name-specifier that precedes the name we're
- /// looking for, if present.
- ///
- /// \param CCC A CorrectionCandidateCallback object that provides further
- /// validation of typo correction candidates. It also provides flags for
- /// determining the set of keywords permitted.
- ///
- /// \param TDG A TypoDiagnosticGenerator functor that will be used to print
- /// diagnostics when the actual typo correction is attempted.
- ///
- /// \param TRC A TypoRecoveryCallback functor that will be used to build an
- /// Expr from a typo correction candidate.
- ///
- /// \param MemberContext if non-NULL, the context in which to look for
- /// a member access expression.
- ///
- /// \param EnteringContext whether we're entering the context described by
- /// the nested-name-specifier SS.
- ///
- /// \param OPT when non-NULL, the search for visible declarations will
- /// also walk the protocols in the qualified interfaces of \p OPT.
- ///
- /// \returns a new \c TypoExpr that will later be replaced in the AST with an
- /// Expr representing the result of performing typo correction, or nullptr if
- /// typo correction is not possible. If nullptr is returned, no diagnostics
- /// will be emitted and it is the responsibility of the caller to emit any
- /// that are needed.
- TypoExpr *CorrectTypoDelayed(
- const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind,
- Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC,
- TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC,
- CorrectTypoKind Mode, DeclContext *MemberContext = nullptr,
- bool EnteringContext = false, const ObjCObjectPointerType *OPT = nullptr);
-
/// Kinds of missing import. Note, the values of these enumerators correspond
/// to %select values in diagnostics.
enum class MissingImportKind {
@@ -9796,20 +9702,6 @@ class Sema final : public SemaBase {
SourceLocation DeclLoc, ArrayRef Modules,
MissingImportKind MIK, bool Recover);
- struct TypoExprState {
- std::unique_ptr Consumer;
- TypoDiagnosticGenerator DiagHandler;
- TypoRecoveryCallback RecoveryHandler;
- TypoExprState();
- TypoExprState(TypoExprState &&other) noexcept;
- TypoExprState &operator=(TypoExprState &&other) noexcept;
- };
-
- const TypoExprState &getTypoExprState(TypoExpr *TE) const;
-
- /// Clears the state of the given TypoExpr.
- void clearDelayedTypo(TypoExpr *TE);
-
/// Called on #pragma clang __debug dump II
void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II);
@@ -9832,23 +9724,15 @@ class Sema final : public SemaBase {
/// Determine if we could use all the declarations in the module.
bool isUsableModule(const Module *M);
- /// Helper for CorrectTypo and CorrectTypoDelayed used to create and
- /// populate a new TypoCorrectionConsumer. Returns nullptr if typo correction
- /// should be skipped entirely.
+ /// Helper for CorrectTypo used to create and populate a new
+ /// TypoCorrectionConsumer. Returns nullptr if typo correction should be
+ /// skipped entirely.
std::unique_ptr makeTypoCorrectionConsumer(
const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind,
Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC,
DeclContext *MemberContext, bool EnteringContext,
const ObjCObjectPointerType *OPT, bool ErrorRecovery);
- /// The set of unhandled TypoExprs and their associated state.
- llvm::MapVector DelayedTypos;
-
- /// Creates a new TypoExpr AST node.
- TypoExpr *createDelayedTypo(std::unique_ptr TCC,
- TypoDiagnosticGenerator TDG,
- TypoRecoveryCallback TRC, SourceLocation TypoLoc);
-
/// Cache for module units which is usable for current module.
llvm::DenseSet UsableModuleUnitsCache;
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 66d09f49680be..33c4b8d1568bf 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -119,12 +119,26 @@ class SemaHLSL : public SemaBase {
bool IsCompAssign);
void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc);
+ /// Computes the unique Root Signature identifier from the given signature,
+ /// then lookup if there is a previousy created Root Signature decl.
+ ///
+ /// Returns the identifier and if it was found
+ std::pair
+ ActOnStartRootSignatureDecl(StringRef Signature);
+
+ /// Creates the Root Signature decl of the parsed Root Signature elements
+ /// onto the AST and push it onto current Scope
+ void ActOnFinishRootSignatureDecl(
+ SourceLocation Loc, IdentifierInfo *DeclIdent,
+ SmallVector &Elements);
+
void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL);
void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL);
void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL);
void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL);
void handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL);
void handleSV_GroupIDAttr(Decl *D, const ParsedAttr &AL);
+ void handleSV_PositionAttr(Decl *D, const ParsedAttr &AL);
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL);
void handleShaderAttr(Decl *D, const ParsedAttr &AL);
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL);
@@ -146,6 +160,7 @@ class SemaHLSL : public SemaBase {
// Diagnose whether the input ID is uint/unit2/uint3 type.
bool diagnoseInputIDType(QualType T, const ParsedAttr &AL);
+ bool diagnosePositionType(QualType T, const ParsedAttr &AL);
bool CanPerformScalarCast(QualType SrcTy, QualType DestTy);
bool ContainsBitField(QualType BaseTy);
diff --git a/clang/include/clang/Sema/SemaInternal.h b/clang/include/clang/Sema/SemaInternal.h
index 95874077050a9..4d0da1102bb59 100644
--- a/clang/include/clang/Sema/SemaInternal.h
+++ b/clang/include/clang/Sema/SemaInternal.h
@@ -314,20 +314,6 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer {
bool SearchNamespaces;
};
-inline Sema::TypoExprState::TypoExprState() {}
-
-inline Sema::TypoExprState::TypoExprState(TypoExprState &&other) noexcept {
- *this = std::move(other);
-}
-
-inline Sema::TypoExprState &Sema::TypoExprState::
-operator=(Sema::TypoExprState &&other) noexcept {
- Consumer = std::move(other.Consumer);
- DiagHandler = std::move(other.DiagHandler);
- RecoveryHandler = std::move(other.RecoveryHandler);
- return *this;
-}
-
} // end namespace clang
#endif
diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h
index 6498390fe96f7..7b169f56b6807 100644
--- a/clang/include/clang/Sema/SemaOpenMP.h
+++ b/clang/include/clang/Sema/SemaOpenMP.h
@@ -283,7 +283,7 @@ class SemaOpenMP : public SemaBase {
/// mapper' construct.
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
TypeResult ParsedType);
- /// Called on start of '#pragma omp declare mapper'.
+ /// Called for '#pragma omp declare mapper'.
DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(
Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
@@ -849,6 +849,7 @@ class SemaOpenMP : public SemaBase {
FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
ArrayRef AdjustArgsNothing,
ArrayRef AdjustArgsNeedDevicePtr,
+ ArrayRef AdjustArgsNeedDeviceAddr,
ArrayRef AppendArgs, SourceLocation AdjustArgsLoc,
SourceLocation AppendArgsLoc, SourceRange SR);
diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h
index cf4ae610ea51f..0f49646f3f022 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -899,6 +899,10 @@ class ASTWriter : public ASTDeserializationListener,
return WritingModule && WritingModule->isNamedModule();
}
+ bool isWritingStdCXXHeaderUnit() const {
+ return WritingModule && WritingModule->isHeaderUnit();
+ }
+
bool isGeneratingReducedBMI() const { return GeneratingReducedBMI; }
bool getDoneWritingDeclsAndTypes() const { return DoneWritingDeclsAndTypes; }
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 2a96df80d1001..211ce585fbac8 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -326,39 +326,34 @@ def StdVariantChecker : Checker<"StdVariant">,
let ParentPackage = Nullability in {
-def NullabilityBase : Checker<"NullabilityBase">,
- HelpText<"Stores information during the analysis about nullability.">,
- Documentation,
- Hidden;
-
-def NullPassedToNonnullChecker : Checker<"NullPassedToNonnull">,
- HelpText<"Warns when a null pointer is passed to a pointer which has a "
- "_Nonnull type.">,
- Dependencies<[NullabilityBase]>,
- Documentation;
+ def NullPassedToNonnullChecker
+ : Checker<"NullPassedToNonnull">,
+ HelpText<"Warns when a null pointer is passed to a pointer which has a "
+ "_Nonnull type.">,
+ Documentation;
-def NullReturnedFromNonnullChecker : Checker<"NullReturnedFromNonnull">,
- HelpText<"Warns when a null pointer is returned from a function that has "
- "_Nonnull return type.">,
- Dependencies<[NullabilityBase]>,
- Documentation;
+ def NullReturnedFromNonnullChecker
+ : Checker<"NullReturnedFromNonnull">,
+ HelpText<"Warns when a null pointer is returned from a function that "
+ "has _Nonnull return type.">,
+ Documentation;
-def NullableDereferencedChecker : Checker<"NullableDereferenced">,
- HelpText<"Warns when a nullable pointer is dereferenced.">,
- Dependencies<[NullabilityBase]>,
- Documentation;
+ def NullableDereferencedChecker
+ : Checker<"NullableDereferenced">,
+ HelpText<"Warns when a nullable pointer is dereferenced.">,
+ Documentation;
-def NullablePassedToNonnullChecker : Checker<"NullablePassedToNonnull">,
- HelpText<"Warns when a nullable pointer is passed to a pointer which has a "
- "_Nonnull type.">,
- Dependencies<[NullabilityBase]>,
- Documentation;
+ def NullablePassedToNonnullChecker
+ : Checker<"NullablePassedToNonnull">,
+ HelpText<"Warns when a nullable pointer is passed to a pointer which "
+ "has a _Nonnull type.">,
+ Documentation;
-def NullableReturnedFromNonnullChecker : Checker<"NullableReturnedFromNonnull">,
- HelpText<"Warns when a nullable pointer is returned from a function that has "
- "_Nonnull return type.">,
- Dependencies<[NullabilityBase]>,
- Documentation;
+ def NullableReturnedFromNonnullChecker
+ : Checker<"NullableReturnedFromNonnull">,
+ HelpText<"Warns when a nullable pointer is returned from a function "
+ "that has _Nonnull return type.">,
+ Documentation;
} // end "nullability"
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h
index 580b49a38dc72..70a7953918ace 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h
@@ -18,6 +18,8 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/Support/SMTAPI.h"
+#include
+
namespace clang {
namespace ento {
@@ -570,23 +572,35 @@ class SMTConv {
// TODO: Refactor to put elsewhere
static inline QualType getAPSIntType(ASTContext &Ctx,
const llvm::APSInt &Int) {
- return Ctx.getIntTypeForBitwidth(Int.getBitWidth(), Int.isSigned());
+ const QualType Ty =
+ Ctx.getIntTypeForBitwidth(Int.getBitWidth(), Int.isSigned());
+ if (!Ty.isNull())
+ return Ty;
+ // If Ty is Null, could be because the original type was a _BitInt.
+ // Get the size of the _BitInt type (expressed in bits) and round it up to
+ // the next power of 2 that is at least the bit size of 'char' (usually 8).
+ unsigned CharTypeSize = Ctx.getTypeSize(Ctx.CharTy);
+ unsigned Pow2DestWidth =
+ std::max(llvm::bit_ceil(Int.getBitWidth()), CharTypeSize);
+ return Ctx.getIntTypeForBitwidth(Pow2DestWidth, Int.isSigned());
}
// Get the QualTy for the input APSInt, and fix it if it has a bitwidth of 1.
static inline std::pair
fixAPSInt(ASTContext &Ctx, const llvm::APSInt &Int) {
llvm::APSInt NewInt;
+ unsigned APSIntBitwidth = Int.getBitWidth();
+ QualType Ty = getAPSIntType(Ctx, Int);
// FIXME: This should be a cast from a 1-bit integer type to a boolean type,
// but the former is not available in Clang. Instead, extend the APSInt
// directly.
- if (Int.getBitWidth() == 1 && getAPSIntType(Ctx, Int).isNull()) {
- NewInt = Int.extend(Ctx.getTypeSize(Ctx.BoolTy));
- } else
- NewInt = Int;
-
- return std::make_pair(NewInt, getAPSIntType(Ctx, NewInt));
+ if (APSIntBitwidth == 1 && Ty.isNull())
+ return {Int.extend(Ctx.getTypeSize(Ctx.BoolTy)),
+ getAPSIntType(Ctx, NewInt)};
+ if (llvm::isPowerOf2_32(APSIntBitwidth) || Ty.isNull())
+ return {Int, Ty};
+ return {Int.extend(Ctx.getTypeSize(Ty)), Ty};
}
// Perform implicit type conversion on binary symbolic expressions.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index b51f7622288df..189e67e4eed0d 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1175,7 +1175,7 @@ void ASTContext::setCurrentNamedModule(Module *M) {
CurrentCXXNamedModule = M;
}
-bool ASTContext::isInSameModule(const Module *M1, const Module *M2) {
+bool ASTContext::isInSameModule(const Module *M1, const Module *M2) const {
if (!M1 != !M2)
return false;
@@ -1705,6 +1705,73 @@ void ASTContext::setRelocationInfoForCXXRecord(
RelocatableClasses.insert({D, Info});
}
+static bool primaryBaseHaseAddressDiscriminatedVTableAuthentication(
+ ASTContext &Context, const CXXRecordDecl *Class) {
+ if (!Class->isPolymorphic())
+ return false;
+ const CXXRecordDecl *BaseType = Context.baseForVTableAuthentication(Class);
+ using AuthAttr = VTablePointerAuthenticationAttr;
+ const AuthAttr *ExplicitAuth = BaseType->getAttr();
+ if (!ExplicitAuth)
+ return Context.getLangOpts().PointerAuthVTPtrAddressDiscrimination;
+ AuthAttr::AddressDiscriminationMode AddressDiscrimination =
+ ExplicitAuth->getAddressDiscrimination();
+ if (AddressDiscrimination == AuthAttr::DefaultAddressDiscrimination)
+ return Context.getLangOpts().PointerAuthVTPtrAddressDiscrimination;
+ return AddressDiscrimination == AuthAttr::AddressDiscrimination;
+}
+
+ASTContext::PointerAuthContent ASTContext::findPointerAuthContent(QualType T) {
+ assert(isPointerAuthenticationAvailable());
+
+ T = T.getCanonicalType();
+ if (T.hasAddressDiscriminatedPointerAuth())
+ return PointerAuthContent::AddressDiscriminatedData;
+ const RecordDecl *RD = T->getAsRecordDecl();
+ if (!RD)
+ return PointerAuthContent::None;
+
+ if (auto Existing = RecordContainsAddressDiscriminatedPointerAuth.find(RD);
+ Existing != RecordContainsAddressDiscriminatedPointerAuth.end())
+ return Existing->second;
+
+ PointerAuthContent Result = PointerAuthContent::None;
+
+ auto SaveResultAndReturn = [&]() -> PointerAuthContent {
+ auto [ResultIter, DidAdd] =
+ RecordContainsAddressDiscriminatedPointerAuth.try_emplace(RD, Result);
+ (void)ResultIter;
+ (void)DidAdd;
+ assert(DidAdd);
+ return Result;
+ };
+ auto ShouldContinueAfterUpdate = [&](PointerAuthContent NewResult) {
+ static_assert(PointerAuthContent::None <
+ PointerAuthContent::AddressDiscriminatedVTable);
+ static_assert(PointerAuthContent::AddressDiscriminatedVTable <
+ PointerAuthContent::AddressDiscriminatedData);
+ if (NewResult > Result)
+ Result = NewResult;
+ return Result != PointerAuthContent::AddressDiscriminatedData;
+ };
+ if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) {
+ if (primaryBaseHaseAddressDiscriminatedVTableAuthentication(*this, CXXRD) &&
+ !ShouldContinueAfterUpdate(
+ PointerAuthContent::AddressDiscriminatedVTable))
+ return SaveResultAndReturn();
+ for (auto Base : CXXRD->bases()) {
+ if (!ShouldContinueAfterUpdate(findPointerAuthContent(Base.getType())))
+ return SaveResultAndReturn();
+ }
+ }
+ for (auto *FieldDecl : RD->fields()) {
+ if (!ShouldContinueAfterUpdate(
+ findPointerAuthContent(FieldDecl->getType())))
+ return SaveResultAndReturn();
+ }
+ return SaveResultAndReturn();
+}
+
void ASTContext::addedLocalImportDecl(ImportDecl *Import) {
assert(!Import->getNextLocalImport() &&
"Import declaration already in the chain");
@@ -7429,6 +7496,12 @@ bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) const {
cast(Y->getDeclContext()->getRedeclContext())))
return false;
+ // If either X or Y are local to the owning module, they are only possible to
+ // be the same entity if they are in the same module.
+ if (X->isModuleLocal() || Y->isModuleLocal())
+ if (!isInSameModule(X->getOwningModule(), Y->getOwningModule()))
+ return false;
+
// Two typedefs refer to the same entity if they have the same underlying
// type.
if (const auto *TypedefX = dyn_cast(X))
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 003bad225e30c..5c44353d8b987 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -9333,8 +9333,9 @@ class AttrImporter {
if (Err)
return;
- AttributeCommonInfo ToI(ToAttrName, ToScopeName, ToAttrRange, ToScopeLoc,
- FromAttr->getParsedKind(), FromAttr->getForm());
+ AttributeCommonInfo ToI(
+ ToAttrName, AttributeScopeInfo(ToScopeName, ToScopeLoc), ToAttrRange,
+ FromAttr->getParsedKind(), FromAttr->getForm());
// The "SemanticSpelling" is not needed to be passed to the constructor.
// That value is recalculated from the SpellingListIndex if needed.
ToAttr = T::Create(Importer.getToContext(),
diff --git a/clang/lib/AST/AttrImpl.cpp b/clang/lib/AST/AttrImpl.cpp
index fefb8f55a9ee2..5875a925d3fb0 100644
--- a/clang/lib/AST/AttrImpl.cpp
+++ b/clang/lib/AST/AttrImpl.cpp
@@ -224,6 +224,12 @@ void OMPDeclareVariantAttr::printPrettyPragma(
PrintExprs(adjustArgsNeedDevicePtr_begin(), adjustArgsNeedDevicePtr_end());
OS << ")";
}
+ if (adjustArgsNeedDeviceAddr_size()) {
+ OS << " adjust_args(need_device_addr:";
+ PrintExprs(adjustArgsNeedDeviceAddr_begin(),
+ adjustArgsNeedDeviceAddr_end());
+ OS << ")";
+ }
auto PrintInteropInfo = [&OS](OMPInteropInfo *Begin, OMPInteropInfo *End) {
for (OMPInteropInfo *I = Begin; I != End; ++I) {
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index bf38b2e5d537d..9fe4803ce98ec 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -6591,10 +6591,6 @@ bool Compiler::visitDeclRef(const ValueDecl *D, const Expr *E) {
return T->isReferenceType();
};
- // DecompositionDecls are just proxies for us.
- if (isa(VD))
- return revisit(VD);
-
if ((VD->hasGlobalStorage() || VD->isStaticDataMember()) &&
typeShouldBeVisited(VD->getType())) {
if (const Expr *Init = VD->getAnyInitializer();
diff --git a/clang/lib/AST/ByteCode/InterpBlock.cpp b/clang/lib/AST/ByteCode/InterpBlock.cpp
index 9ef44cd29ff87..f60307870ffcc 100644
--- a/clang/lib/AST/ByteCode/InterpBlock.cpp
+++ b/clang/lib/AST/ByteCode/InterpBlock.cpp
@@ -69,20 +69,26 @@ void Block::cleanup() {
void Block::replacePointer(Pointer *Old, Pointer *New) {
assert(Old);
assert(New);
+ assert(Old != New);
if (IsStatic) {
assert(!Pointers);
return;
}
-
#ifndef NDEBUG
assert(hasPointer(Old));
#endif
- removePointer(Old);
- addPointer(New);
+ if (Old->Prev)
+ Old->Prev->Next = New;
+ if (Old->Next)
+ Old->Next->Prev = New;
+ New->Prev = Old->Prev;
+ New->Next = Old->Next;
+ if (Pointers == Old)
+ Pointers = New;
Old->PointeeStorage.BS.Pointee = nullptr;
-
+ New->PointeeStorage.BS.Pointee = this;
#ifndef NDEBUG
assert(!hasPointer(Old));
assert(hasPointer(New));
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index b678f229d50bb..d01e3d042a8bf 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -1321,7 +1321,7 @@ static bool interp__builtin_ia32_pdep(InterpState &S, CodePtr OpPC,
if (Mask[I])
Result.setBitVal(I, Val[P++]);
}
- pushInteger(S, Result, Call->getType());
+ pushInteger(S, std::move(Result), Call->getType());
return true;
}
@@ -1344,7 +1344,7 @@ static bool interp__builtin_ia32_pext(InterpState &S, CodePtr OpPC,
if (Mask[I])
Result.setBitVal(P++, Val[I]);
}
- pushInteger(S, Result, Call->getType());
+ pushInteger(S, std::move(Result), Call->getType());
return true;
}
@@ -1423,7 +1423,6 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
// Walk up the call stack to find the appropriate caller and get the
// element type from it.
auto [NewCall, ElemType] = S.getStdAllocatorCaller("allocate");
- APSInt Bytes = popToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(0)));
if (ElemType.isNull()) {
S.FFDiag(Call, S.getLangOpts().CPlusPlus20
@@ -1439,6 +1438,25 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
return false;
}
+ // We only care about the first parameter (the size), so discard all the
+ // others.
+ {
+ unsigned NumArgs = Call->getNumArgs();
+ assert(NumArgs >= 1);
+
+ // The std::nothrow_t arg never gets put on the stack.
+ if (Call->getArg(NumArgs - 1)->getType()->isNothrowT())
+ --NumArgs;
+ auto Args = llvm::ArrayRef(Call->getArgs(), Call->getNumArgs());
+ // First arg is needed.
+ Args = Args.drop_front();
+
+ // Discard the rest.
+ for (const Expr *Arg : Args)
+ discard(S.Stk, *S.getContext().classify(Arg));
+ }
+
+ APSInt Bytes = popToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(0)));
CharUnits ElemSize = S.getASTContext().getTypeSizeInChars(ElemType);
assert(!ElemSize.isZero());
// Divide the number of bytes by sizeof(ElemType), so we get the number of
diff --git a/clang/lib/AST/ByteCode/InterpStack.cpp b/clang/lib/AST/ByteCode/InterpStack.cpp
index b183335dd5884..6b748d62b83bd 100644
--- a/clang/lib/AST/ByteCode/InterpStack.cpp
+++ b/clang/lib/AST/ByteCode/InterpStack.cpp
@@ -19,9 +19,7 @@
using namespace clang;
using namespace clang::interp;
-InterpStack::~InterpStack() { clear(); }
-
-void InterpStack::clear() {
+InterpStack::~InterpStack() {
if (Chunk && Chunk->Next)
std::free(Chunk->Next);
if (Chunk)
@@ -33,6 +31,21 @@ void InterpStack::clear() {
#endif
}
+// We keep the last chunk around to reuse.
+void InterpStack::clear() {
+ if (!Chunk)
+ return;
+
+ if (Chunk->Next)
+ std::free(Chunk->Next);
+
+ assert(Chunk);
+ StackSize = 0;
+#ifndef NDEBUG
+ ItemTypes.clear();
+#endif
+}
+
void InterpStack::clearTo(size_t NewSize) {
assert(NewSize <= size());
size_t ToShrink = size() - NewSize;
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index a1bb62bcb68fa..48c60aa4e449a 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -1132,6 +1132,12 @@ bool Decl::isInExportDeclContext() const {
return isa_and_nonnull(DC);
}
+bool Decl::isModuleLocal() const {
+ auto *M = getOwningModule();
+ return M && M->isNamedModule() &&
+ getModuleOwnershipKind() == ModuleOwnershipKind::ReachableWhenImported;
+}
+
bool Decl::isInAnotherModuleUnit() const {
auto *M = getOwningModule();
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 17d2cb4a30f30..c3722c65abf6e 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -3611,7 +3611,6 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case PackExpansionExprClass:
case SubstNonTypeTemplateParmPackExprClass:
case FunctionParmPackExprClass:
- case TypoExprClass:
case RecoveryExprClass:
case CXXFoldExprClass:
// Make a conservative assumption for dependent nodes.
diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp
index 3f37d06cc8f3a..ad66335138a42 100644
--- a/clang/lib/AST/ExprClassification.cpp
+++ b/clang/lib/AST/ExprClassification.cpp
@@ -129,7 +129,6 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
// FIXME: Is this wise? Should they get their own kind?
case Expr::UnresolvedLookupExprClass:
case Expr::UnresolvedMemberExprClass:
- case Expr::TypoExprClass:
case Expr::DependentCoawaitExprClass:
case Expr::CXXDependentScopeMemberExprClass:
case Expr::DependentScopeDeclRefExprClass:
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index fa4e10e84de05..f1580255a462a 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -6844,7 +6844,8 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
// FIXME: In this case, the values of the other subobjects are
// specified, since zero-initialization sets all padding bits to zero.
if (!Value->hasValue() ||
- (Value->isUnion() && Value->getUnionField() != FD)) {
+ (Value->isUnion() &&
+ !declaresSameEntity(Value->getUnionField(), FD))) {
if (CD->isUnion())
*Value = APValue(FD);
else
@@ -17326,7 +17327,6 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::CXXDeleteExprClass:
case Expr::CXXPseudoDestructorExprClass:
case Expr::UnresolvedLookupExprClass:
- case Expr::TypoExprClass:
case Expr::RecoveryExprClass:
case Expr::DependentScopeDeclRefExprClass:
case Expr::CXXConstructExprClass:
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index ecf5be220439b..487933a748ab8 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -4994,7 +4994,6 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
case Expr::ParenListExprClass:
case Expr::MSPropertyRefExprClass:
case Expr::MSPropertySubscriptExprClass:
- case Expr::TypoExprClass: // This should no longer exist in the AST by now.
case Expr::RecoveryExprClass:
case Expr::ArraySectionExprClass:
case Expr::OMPArrayShapingExprClass:
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 13c3bc0387890..28317911d825b 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -2914,11 +2914,6 @@ void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {
PrintExpr(Node->getSourceExpr());
}
-void StmtPrinter::VisitTypoExpr(TypoExpr *Node) {
- // TODO: Print something reasonable for a TypoExpr, if necessary.
- llvm_unreachable("Cannot print TypoExpr nodes");
-}
-
void StmtPrinter::VisitRecoveryExpr(RecoveryExpr *Node) {
OS << "(";
const char *Sep = "";
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index f7d1655f67ed1..c666d966a6e58 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2361,10 +2361,6 @@ void StmtProfiler::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
VisitExpr(E);
}
-void StmtProfiler::VisitTypoExpr(const TypoExpr *E) {
- VisitExpr(E);
-}
-
void StmtProfiler::VisitSourceLocExpr(const SourceLocExpr *E) {
VisitExpr(E);
}
diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index 8b1ca6b80971f..631a546b45ff4 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -30,7 +30,6 @@
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Casting.h"
#include
#include
#include
diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp
index 905046685934b..004e5209a44a7 100644
--- a/clang/lib/Basic/Attributes.cpp
+++ b/clang/lib/Basic/Attributes.cpp
@@ -119,7 +119,6 @@ normalizeAttrScopeName(const IdentifierInfo *ScopeName,
AttributeCommonInfo::Syntax SyntaxUsed) {
if (ScopeName)
return normalizeAttrScopeName(ScopeName->getName(), SyntaxUsed);
-
return "";
}
@@ -141,12 +140,23 @@ static StringRef normalizeAttrName(StringRef AttrName,
return AttrName;
}
+StringRef AttributeCommonInfo::getNormalizedScopeName() const {
+ return normalizeAttrScopeName(getScopeName(), getSyntax());
+}
+
+StringRef
+AttributeCommonInfo::getNormalizedAttrName(StringRef ScopeName) const {
+ return normalizeAttrName(getAttrName()->getName(), ScopeName, getSyntax());
+}
+
bool AttributeCommonInfo::isGNUScope() const {
- return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
+ return AttrScope.isValid() && (AttrScope.getName()->isStr("gnu") ||
+ AttrScope.getName()->isStr("__gnu__"));
}
bool AttributeCommonInfo::isClangScope() const {
- return ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang"));
+ return AttrScope.isValid() && (AttrScope.getName()->isStr("clang") ||
+ AttrScope.getName()->isStr("_Clang"));
}
#include "clang/Sema/AttrParsedAttrKinds.inc"
@@ -198,8 +208,16 @@ std::string AttributeCommonInfo::getNormalizedFullName() const {
normalizeName(getAttrName(), getScopeName(), getSyntax()));
}
+std::string
+AttributeCommonInfo::getNormalizedFullName(StringRef ScopeName,
+ StringRef AttrName) const {
+ return static_cast(
+ normalizeName(AttrName, ScopeName, getSyntax()));
+}
+
SourceRange AttributeCommonInfo::getNormalizedRange() const {
- return hasScope() ? SourceRange(ScopeLoc, AttrRange.getEnd()) : AttrRange;
+ return hasScope() ? SourceRange(AttrScope.getNameLoc(), AttrRange.getEnd())
+ : AttrRange;
}
static AttributeCommonInfo::Scope
@@ -239,10 +257,8 @@ static constexpr const char *AttrScopeSpellingList[] = {
#include "clang/Basic/AttributeSpellingList.inc"
};
-std::optional
-AttributeCommonInfo::getCorrectedFullName(const TargetInfo &Target,
- const LangOptions &LangOpts) const {
- StringRef ScopeName = normalizeAttrScopeName(getScopeName(), getSyntax());
+std::optional
+AttributeCommonInfo::tryGetCorrectedScopeName(StringRef ScopeName) const {
if (ScopeName.size() > 0 &&
llvm::none_of(AttrScopeSpellingList,
[&](const char *S) { return S == ScopeName; })) {
@@ -251,25 +267,26 @@ AttributeCommonInfo::getCorrectedFullName(const TargetInfo &Target,
STC.add(Scope);
if (auto CorrectedScopeName = STC.getCorrection())
- ScopeName = *CorrectedScopeName;
+ return CorrectedScopeName;
}
+ return std::nullopt;
+}
- StringRef AttrName =
- normalizeAttrName(getAttrName()->getName(), ScopeName, getSyntax());
+std::optional AttributeCommonInfo::tryGetCorrectedAttrName(
+ StringRef ScopeName, StringRef AttrName, const TargetInfo &Target,
+ const LangOptions &LangOpts) const {
if (llvm::none_of(AttrSpellingList,
[&](const char *A) { return A == AttrName; })) {
SimpleTypoCorrection STC(AttrName);
for (const auto &Attr : AttrSpellingList)
STC.add(Attr);
- if (auto CorrectedAttrName = STC.getCorrection())
- AttrName = *CorrectedAttrName;
+ if (auto CorrectedAttrName = STC.getCorrection()) {
+ if (hasAttribute(getSyntax(), ScopeName, *CorrectedAttrName, Target,
+ LangOpts,
+ /*CheckPlugins=*/true))
+ return CorrectedAttrName;
+ }
}
-
- if (hasAttribute(getSyntax(), ScopeName, AttrName, Target, LangOpts,
- /*CheckPlugins=*/true))
- return static_cast(
- normalizeName(AttrName, ScopeName, getSyntax()));
-
return std::nullopt;
}
diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp
index 694224071347a..a30bfa28eca71 100644
--- a/clang/lib/Basic/Diagnostic.cpp
+++ b/clang/lib/Basic/Diagnostic.cpp
@@ -119,6 +119,8 @@ bool DiagnosticsEngine::popMappings(SourceLocation Loc) {
return true;
}
+void DiagnosticsEngine::ResetPragmas() { DiagStatesByLoc.clear(/*Soft=*/true); }
+
void DiagnosticsEngine::Reset(bool soft /*=false*/) {
ErrorOccurred = false;
UncompilableErrorOccurred = false;
@@ -130,12 +132,12 @@ void DiagnosticsEngine::Reset(bool soft /*=false*/) {
TrapNumErrorsOccurred = 0;
TrapNumUnrecoverableErrorsOccurred = 0;
- LastDiagLevel = DiagnosticIDs::Ignored;
+ LastDiagLevel = Ignored;
if (!soft) {
// Clear state related to #pragma diagnostic.
DiagStates.clear();
- DiagStatesByLoc.clear();
+ DiagStatesByLoc.clear(false);
DiagStateOnPushStack.clear();
// Create a DiagState and DiagStatePoint representing diagnostic changes
@@ -658,13 +660,95 @@ void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) {
Level DiagLevel = storedDiag.getLevel();
Diagnostic Info(this, storedDiag.getLocation(), storedDiag.getID(),
DiagStorage, storedDiag.getMessage());
+ Report(DiagLevel, Info);
+}
+
+void DiagnosticsEngine::Report(Level DiagLevel, const Diagnostic &Info) {
+ assert(DiagLevel != Ignored && "Cannot emit ignored diagnostics!");
Client->HandleDiagnostic(DiagLevel, Info);
if (Client->IncludeInDiagnosticCounts()) {
- if (DiagLevel == DiagnosticsEngine::Warning)
+ if (DiagLevel == Warning)
++NumWarnings;
}
}
+/// ProcessDiag - This is the method used to report a diagnostic that is
+/// finally fully formed.
+bool DiagnosticsEngine::ProcessDiag(const DiagnosticBuilder &DiagBuilder) {
+ Diagnostic Info(this, DiagBuilder);
+
+ assert(getClient() && "DiagnosticClient not set!");
+
+ // Figure out the diagnostic level of this message.
+ unsigned DiagID = Info.getID();
+ Level DiagLevel = getDiagnosticLevel(DiagID, Info.getLocation());
+
+ // Update counts for DiagnosticErrorTrap even if a fatal error occurred
+ // or diagnostics are suppressed.
+ if (DiagLevel >= Error) {
+ ++TrapNumErrorsOccurred;
+ if (Diags->isUnrecoverable(DiagID))
+ ++TrapNumUnrecoverableErrorsOccurred;
+ }
+
+ if (SuppressAllDiagnostics)
+ return false;
+
+ if (DiagLevel != Note) {
+ // Record that a fatal error occurred only when we see a second
+ // non-note diagnostic. This allows notes to be attached to the
+ // fatal error, but suppresses any diagnostics that follow those
+ // notes.
+ if (LastDiagLevel == Fatal)
+ FatalErrorOccurred = true;
+
+ LastDiagLevel = DiagLevel;
+ }
+
+ // If a fatal error has already been emitted, silence all subsequent
+ // diagnostics.
+ if (FatalErrorOccurred) {
+ if (DiagLevel >= Error && Client->IncludeInDiagnosticCounts())
+ ++NumErrors;
+
+ return false;
+ }
+
+ // If the client doesn't care about this message, don't issue it. If this is
+ // a note and the last real diagnostic was ignored, ignore it too.
+ if (DiagLevel == Ignored || (DiagLevel == Note && LastDiagLevel == Ignored))
+ return false;
+
+ if (DiagLevel >= Error) {
+ if (Diags->isUnrecoverable(DiagID))
+ UnrecoverableErrorOccurred = true;
+
+ // Warnings which have been upgraded to errors do not prevent compilation.
+ if (Diags->isDefaultMappingAsError(DiagID))
+ UncompilableErrorOccurred = true;
+
+ ErrorOccurred = true;
+ if (Client->IncludeInDiagnosticCounts())
+ ++NumErrors;
+
+ // If we've emitted a lot of errors, emit a fatal error instead of it to
+ // stop a flood of bogus errors.
+ if (ErrorLimit && NumErrors > ErrorLimit && DiagLevel == Error) {
+ Report(diag::fatal_too_many_errors);
+ return false;
+ }
+ }
+
+ // Make sure we set FatalErrorOccurred to ensure that the notes from the
+ // diagnostic that caused `fatal_too_many_errors` won't be emitted.
+ if (Info.getID() == diag::fatal_too_many_errors)
+ FatalErrorOccurred = true;
+
+ // Finally, report it.
+ Report(DiagLevel, Info);
+ return true;
+}
+
bool DiagnosticsEngine::EmitDiagnostic(const DiagnosticBuilder &DB,
bool Force) {
assert(getClient() && "DiagnosticClient not set!");
@@ -674,14 +758,12 @@ bool DiagnosticsEngine::EmitDiagnostic(const DiagnosticBuilder &DB,
Diagnostic Info(this, DB);
// Figure out the diagnostic level of this message.
- DiagnosticIDs::Level DiagLevel =
- Diags->getDiagnosticLevel(Info.getID(), Info.getLocation(), *this);
+ Level DiagLevel = getDiagnosticLevel(Info.getID(), Info.getLocation());
- Emitted = (DiagLevel != DiagnosticIDs::Ignored);
- if (Emitted) {
- // Emit the diagnostic regardless of suppression level.
- Diags->EmitDiag(*this, DB, DiagLevel);
- }
+ // Emit the diagnostic regardless of suppression level.
+ Emitted = DiagLevel != Ignored;
+ if (Emitted)
+ Report(DiagLevel, Info);
} else {
// Process the diagnostic, sending the accumulated information to the
// DiagnosticConsumer.
diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp
index 3e90b2d804773..dcf0c6cb54282 100644
--- a/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/clang/lib/Basic/DiagnosticIDs.cpp
@@ -823,103 +823,6 @@ unsigned DiagnosticIDs::getCXXCompatDiagId(const LangOptions &LangOpts,
return StdVer >= D.StdVer ? D.DiagId : D.PreDiagId;
}
-/// ProcessDiag - This is the method used to report a diagnostic that is
-/// finally fully formed.
-bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag,
- const DiagnosticBuilder &DiagBuilder) const {
- Diagnostic Info(&Diag, DiagBuilder);
-
- assert(Diag.getClient() && "DiagnosticClient not set!");
-
- // Figure out the diagnostic level of this message.
- unsigned DiagID = Info.getID();
- DiagnosticIDs::Level DiagLevel
- = getDiagnosticLevel(DiagID, Info.getLocation(), Diag);
-
- // Update counts for DiagnosticErrorTrap even if a fatal error occurred
- // or diagnostics are suppressed.
- if (DiagLevel >= DiagnosticIDs::Error) {
- ++Diag.TrapNumErrorsOccurred;
- if (isUnrecoverable(DiagID))
- ++Diag.TrapNumUnrecoverableErrorsOccurred;
- }
-
- if (Diag.SuppressAllDiagnostics)
- return false;
-
- if (DiagLevel != DiagnosticIDs::Note) {
- // Record that a fatal error occurred only when we see a second
- // non-note diagnostic. This allows notes to be attached to the
- // fatal error, but suppresses any diagnostics that follow those
- // notes.
- if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
- Diag.FatalErrorOccurred = true;
-
- Diag.LastDiagLevel = DiagLevel;
- }
-
- // If a fatal error has already been emitted, silence all subsequent
- // diagnostics.
- if (Diag.FatalErrorOccurred) {
- if (DiagLevel >= DiagnosticIDs::Error &&
- Diag.Client->IncludeInDiagnosticCounts()) {
- ++Diag.NumErrors;
- }
-
- return false;
- }
-
- // If the client doesn't care about this message, don't issue it. If this is
- // a note and the last real diagnostic was ignored, ignore it too.
- if (DiagLevel == DiagnosticIDs::Ignored ||
- (DiagLevel == DiagnosticIDs::Note &&
- Diag.LastDiagLevel == DiagnosticIDs::Ignored))
- return false;
-
- if (DiagLevel >= DiagnosticIDs::Error) {
- if (isUnrecoverable(DiagID))
- Diag.UnrecoverableErrorOccurred = true;
-
- // Warnings which have been upgraded to errors do not prevent compilation.
- if (isDefaultMappingAsError(DiagID))
- Diag.UncompilableErrorOccurred = true;
-
- Diag.ErrorOccurred = true;
- if (Diag.Client->IncludeInDiagnosticCounts()) {
- ++Diag.NumErrors;
- }
-
- // If we've emitted a lot of errors, emit a fatal error instead of it to
- // stop a flood of bogus errors.
- if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
- DiagLevel == DiagnosticIDs::Error) {
- Diag.Report(diag::fatal_too_many_errors);
- return false;
- }
- }
-
- // Make sure we set FatalErrorOccurred to ensure that the notes from the
- // diagnostic that caused `fatal_too_many_errors` won't be emitted.
- if (Info.getID() == diag::fatal_too_many_errors)
- Diag.FatalErrorOccurred = true;
- // Finally, report it.
- EmitDiag(Diag, DiagBuilder, DiagLevel);
- return true;
-}
-
-void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag,
- const DiagnosticBuilder &DiagBuilder,
- Level DiagLevel) const {
- Diagnostic Info(&Diag, DiagBuilder);
- assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!");
-
- Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info);
- if (Diag.Client->IncludeInDiagnosticCounts()) {
- if (DiagLevel == DiagnosticIDs::Warning)
- ++Diag.NumWarnings;
- }
-}
-
bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
// Only errors may be unrecoverable.
if (getDiagClass(DiagID) < CLASS_ERROR)
diff --git a/clang/lib/Basic/LangOptions.cpp b/clang/lib/Basic/LangOptions.cpp
index 7e696620993f9..912b890569cf5 100644
--- a/clang/lib/Basic/LangOptions.cpp
+++ b/clang/lib/Basic/LangOptions.cpp
@@ -11,7 +11,6 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/LangOptions.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Path.h"
using namespace clang;
diff --git a/clang/lib/Basic/ProfileList.cpp b/clang/lib/Basic/ProfileList.cpp
index aaea5a00ab6ae..8481deffe2a7b 100644
--- a/clang/lib/Basic/ProfileList.cpp
+++ b/clang/lib/Basic/ProfileList.cpp
@@ -69,24 +69,24 @@ ProfileList::ProfileList(ArrayRef Paths, SourceManager &SM)
ProfileList::~ProfileList() = default;
-static StringRef getSectionName(CodeGenOptions::ProfileInstrKind Kind) {
+static StringRef getSectionName(llvm::driver::ProfileInstrKind Kind) {
switch (Kind) {
- case CodeGenOptions::ProfileNone:
+ case llvm::driver::ProfileInstrKind::ProfileNone:
return "";
- case CodeGenOptions::ProfileClangInstr:
+ case llvm::driver::ProfileInstrKind::ProfileClangInstr:
return "clang";
- case CodeGenOptions::ProfileIRInstr:
+ case llvm::driver::ProfileInstrKind::ProfileIRInstr:
return "llvm";
- case CodeGenOptions::ProfileCSIRInstr:
+ case llvm::driver::ProfileInstrKind::ProfileCSIRInstr:
return "csllvm";
- case CodeGenOptions::ProfileIRSampleColdCov:
+ case llvm::driver::ProfileInstrKind::ProfileIRSampleColdCov:
return "sample-coldcov";
}
- llvm_unreachable("Unhandled CodeGenOptions::ProfileInstrKind enum");
+ llvm_unreachable("Unhandled llvm::driver::ProfileInstrKind enum");
}
ProfileList::ExclusionType
-ProfileList::getDefault(CodeGenOptions::ProfileInstrKind Kind) const {
+ProfileList::getDefault(llvm::driver::ProfileInstrKind Kind) const {
StringRef Section = getSectionName(Kind);
// Check for "default:"
if (SCL->inSection(Section, "default", "allow"))
@@ -117,7 +117,7 @@ ProfileList::inSection(StringRef Section, StringRef Prefix,
std::optional
ProfileList::isFunctionExcluded(StringRef FunctionName,
- CodeGenOptions::ProfileInstrKind Kind) const {
+ llvm::driver::ProfileInstrKind Kind) const {
StringRef Section = getSectionName(Kind);
// Check for "function:="
if (auto V = inSection(Section, "function", FunctionName))
@@ -131,13 +131,13 @@ ProfileList::isFunctionExcluded(StringRef FunctionName,
std::optional
ProfileList::isLocationExcluded(SourceLocation Loc,
- CodeGenOptions::ProfileInstrKind Kind) const {
+ llvm::driver::ProfileInstrKind Kind) const {
return isFileExcluded(SM.getFilename(SM.getFileLoc(Loc)), Kind);
}
std::optional
ProfileList::isFileExcluded(StringRef FileName,
- CodeGenOptions::ProfileInstrKind Kind) const {
+ llvm::driver::ProfileInstrKind Kind) const {
StringRef Section = getSectionName(Kind);
// Check for "source:="
if (auto V = inSection(Section, "source", FileName))
diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp
index 09e5c6547fb51..053e82683a4a6 100644
--- a/clang/lib/Basic/SourceManager.cpp
+++ b/clang/lib/Basic/SourceManager.cpp
@@ -344,6 +344,9 @@ void SourceManager::clearIDTables() {
NextLocalOffset = 0;
CurrentLoadedOffset = MaxLoadedOffset;
createExpansionLoc(SourceLocation(), SourceLocation(), SourceLocation(), 1);
+ // Diagnostics engine keeps some references to fileids, mostly for dealing
+ // with diagnostic pragmas, make sure they're reset as well.
+ Diag.ResetPragmas();
}
bool SourceManager::isMainFile(const FileEntry &SourceFile) {
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index 7b577632fdf55..9429a316a9196 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -555,8 +555,7 @@ void TargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) {
bool TargetInfo::initFeatureMap(
llvm::StringMap &Features, DiagnosticsEngine &Diags, StringRef CPU,
const std::vector &FeatureVec) const {
- for (const auto &F : FeatureVec) {
- StringRef Name = F;
+ for (StringRef Name : FeatureVec) {
if (Name.empty())
continue;
// Apply the feature via the target.
diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp
index e8abdf9aafd82..124b340b62d9f 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -625,6 +625,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
if (HasCRC)
Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
+ if (HasCSSC)
+ Builder.defineMacro("__ARM_FEATURE_CSSC", "1");
+
if (HasRCPC3)
Builder.defineMacro("__ARM_FEATURE_RCPC", "3");
else if (HasRCPC)
@@ -874,6 +877,7 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
.Case("rdm", HasRDM)
.Case("lse", HasLSE)
.Case("crc", HasCRC)
+ .Case("cssc", HasCSSC)
.Case("sha2", HasSHA2)
.Case("sha3", HasSHA3)
.Cases("aes", "pmull", HasAES)
@@ -1249,6 +1253,8 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector &Features,
HasPAuthLR = true;
HasPAuth = true;
}
+ if (Feature == "+cssc")
+ HasCSSC = true;
}
// Check features that are manually disabled by command line options.
diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h
index a4c65361105e4..1951e0679d2ec 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -66,6 +66,7 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
unsigned FPU = FPUMode;
bool HasCRC = false;
+ bool HasCSSC = false;
bool HasAES = false;
bool HasSHA2 = false;
bool HasSHA3 = false;
diff --git a/clang/lib/Basic/Targets/AVR.cpp b/clang/lib/Basic/Targets/AVR.cpp
index 85ca4bc30c461..bbe7b01ca036d 100644
--- a/clang/lib/Basic/Targets/AVR.cpp
+++ b/clang/lib/Basic/Targets/AVR.cpp
@@ -336,6 +336,9 @@ static MCUInfo AVRMcus[] = {
{"attiny1624", "__AVR_ATtiny1624__", "103", 1},
{"attiny1626", "__AVR_ATtiny1626__", "103", 1},
{"attiny1627", "__AVR_ATtiny1627__", "103", 1},
+ {"attiny3224", "__AVR_ATtiny3224__", "103", 1},
+ {"attiny3226", "__AVR_ATtiny3226__", "103", 1},
+ {"attiny3227", "__AVR_ATtiny3227__", "103", 1},
{"atmega808", "__AVR_ATmega808__", "103", 1},
{"atmega809", "__AVR_ATmega809__", "103", 1},
{"atmega1608", "__AVR_ATmega1608__", "103", 1},
@@ -344,6 +347,72 @@ static MCUInfo AVRMcus[] = {
{"atmega3209", "__AVR_ATmega3209__", "103", 1},
{"atmega4808", "__AVR_ATmega4808__", "103", 1},
{"atmega4809", "__AVR_ATmega4809__", "103", 1},
+
+ // gcc 14 additions:
+
+ {"avr64da28", "__AVR_AVR64DA28__", "102", 1},
+ {"avr64da32", "__AVR_AVR64DA32__", "102", 1},
+ {"avr64da48", "__AVR_AVR64DA48__", "102", 1},
+ {"avr64da64", "__AVR_AVR64DA64__", "102", 1},
+ {"avr64db28", "__AVR_AVR64DB28__", "102", 1},
+ {"avr64db32", "__AVR_AVR64DB32__", "102", 1},
+ {"avr64db48", "__AVR_AVR64DB48__", "102", 1},
+ {"avr64db64", "__AVR_AVR64DB64__", "102", 1},
+ {"avr64dd14", "__AVR_AVR64DD14__", "102", 1},
+ {"avr64dd20", "__AVR_AVR64DD20__", "102", 1},
+ {"avr64dd28", "__AVR_AVR64DD28__", "102", 1},
+ {"avr64dd32", "__AVR_AVR64DD32__", "102", 1},
+ {"avr64du28", "__AVR_AVR64DU28__", "102", 1},
+ {"avr64du32", "__AVR_AVR64DU32__", "102", 1},
+ {"avr64ea28", "__AVR_AVR64EA28__", "102", 1},
+ {"avr64ea32", "__AVR_AVR64EA32__", "102", 1},
+ {"avr64ea48", "__AVR_AVR64EA48__", "102", 1},
+ {"avr64sd28", "__AVR_AVR64SD28__", "102", 1},
+ {"avr64sd32", "__AVR_AVR64SD32__", "102", 1},
+ {"avr64sd48", "__AVR_AVR64SD48__", "102", 1},
+
+ {"avr16dd20", "__AVR_AVR16DD20__", "103", 1},
+ {"avr16dd28", "__AVR_AVR16DD28__", "103", 1},
+ {"avr16dd32", "__AVR_AVR16DD32__", "103", 1},
+ {"avr16du14", "__AVR_AVR16DU14__", "103", 1},
+ {"avr16du20", "__AVR_AVR16DU20__", "103", 1},
+ {"avr16du28", "__AVR_AVR16DU28__", "103", 1},
+ {"avr16du32", "__AVR_AVR16DU32__", "103", 1},
+ {"avr32da28", "__AVR_AVR32DA28__", "103", 1},
+ {"avr32da32", "__AVR_AVR32DA32__", "103", 1},
+ {"avr32da48", "__AVR_AVR32DA48__", "103", 1},
+ {"avr32db28", "__AVR_AVR32DB28__", "103", 1},
+ {"avr32db32", "__AVR_AVR32DB32__", "103", 1},
+ {"avr32db48", "__AVR_AVR32DB48__", "103", 1},
+ {"avr32dd14", "__AVR_AVR32DD14__", "103", 1},
+ {"avr32dd20", "__AVR_AVR32DD20__", "103", 1},
+ {"avr32dd28", "__AVR_AVR32DD28__", "103", 1},
+ {"avr32dd32", "__AVR_AVR32DD32__", "103", 1},
+ {"avr32du14", "__AVR_AVR32DU14__", "103", 1},
+ {"avr32du20", "__AVR_AVR32DU20__", "103", 1},
+ {"avr32du28", "__AVR_AVR32DU28__", "103", 1},
+ {"avr32du32", "__AVR_AVR32DU32__", "103", 1},
+ {"avr16eb14", "__AVR_AVR16EB14__", "103", 1},
+ {"avr16eb20", "__AVR_AVR16EB20__", "103", 1},
+ {"avr16eb28", "__AVR_AVR16EB28__", "103", 1},
+ {"avr16eb32", "__AVR_AVR16EB32__", "103", 1},
+ {"avr16ea28", "__AVR_AVR16EA28__", "103", 1},
+ {"avr16ea32", "__AVR_AVR16EA32__", "103", 1},
+ {"avr16ea48", "__AVR_AVR16EA48__", "103", 1},
+ {"avr32ea28", "__AVR_AVR32EA28__", "103", 1},
+ {"avr32ea32", "__AVR_AVR32EA32__", "103", 1},
+ {"avr32ea48", "__AVR_AVR32EA48__", "103", 1},
+ {"avr32sd20", "__AVR_AVR32SD20__", "103", 1},
+ {"avr32sd28", "__AVR_AVR32SD28__", "103", 1},
+ {"avr32sd32", "__AVR_AVR32SD32__", "103", 1},
+ {"avr128da28", "__AVR_AVR128DA28__", "104", 2},
+ {"avr128da32", "__AVR_AVR128DA32__", "104", 2},
+ {"avr128da48", "__AVR_AVR128DA48__", "104", 2},
+ {"avr128da64", "__AVR_AVR128DA64__", "104", 2},
+ {"avr128db28", "__AVR_AVR128DB28__", "104", 2},
+ {"avr128db32", "__AVR_AVR128DB32__", "104", 2},
+ {"avr128db48", "__AVR_AVR128DB48__", "104", 2},
+ {"avr128db64", "__AVR_AVR128DB64__", "104", 2},
};
} // namespace targets
diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h
index 0eaf82eee756b..b416a01f0f374 100644
--- a/clang/lib/Basic/Targets/SPIR.h
+++ b/clang/lib/Basic/Targets/SPIR.h
@@ -46,7 +46,7 @@ static const unsigned SPIRDefIsPrivMap[] = {
0, // ptr32_sptr
0, // ptr32_uptr
0, // ptr64
- 0, // hlsl_groupshared
+ 3, // hlsl_groupshared
12, // hlsl_constant
10, // hlsl_private
11, // hlsl_device
@@ -82,7 +82,7 @@ static const unsigned SPIRDefIsGenMap[] = {
0, // ptr32_sptr
0, // ptr32_uptr
0, // ptr64
- 0, // hlsl_groupshared
+ 3, // hlsl_groupshared
0, // hlsl_constant
10, // hlsl_private
11, // hlsl_device
diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h
index 6f8a2365be256..ecb31ffa4750f 100644
--- a/clang/lib/Basic/Targets/X86.h
+++ b/clang/lib/Basic/Targets/X86.h
@@ -997,6 +997,10 @@ class LLVM_LIBRARY_VISIBILITY CygwinX86_64TargetInfo : public X86_64TargetInfo {
if (Opts.CPlusPlus)
Builder.defineMacro("_GNU_SOURCE");
}
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
};
class LLVM_LIBRARY_VISIBILITY DarwinX86_64TargetInfo
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp b/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp
index 4c8c6ed289c3b..9cec17bcb2fd0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp
@@ -39,6 +39,34 @@ mlir::Value CIRGenBuilderTy::getArrayElement(mlir::Location arrayLocBegin,
return create(arrayLocEnd, flatPtrTy, basePtr, idx);
}
+cir::ConstantOp CIRGenBuilderTy::getConstInt(mlir::Location loc,
+ llvm::APSInt intVal) {
+ bool isSigned = intVal.isSigned();
+ unsigned width = intVal.getBitWidth();
+ cir::IntType t = isSigned ? getSIntNTy(width) : getUIntNTy(width);
+ return getConstInt(loc, t,
+ isSigned ? intVal.getSExtValue() : intVal.getZExtValue());
+}
+
+cir::ConstantOp CIRGenBuilderTy::getConstInt(mlir::Location loc,
+ llvm::APInt intVal) {
+ return getConstInt(loc, llvm::APSInt(intVal));
+}
+
+cir::ConstantOp CIRGenBuilderTy::getConstInt(mlir::Location loc, mlir::Type t,
+ uint64_t c) {
+ assert(mlir::isa(t) && "expected cir::IntType");
+ return create(loc, cir::IntAttr::get(t, c));
+}
+
+cir::ConstantOp
+clang::CIRGen::CIRGenBuilderTy::getConstFP(mlir::Location loc, mlir::Type t,
+ llvm::APFloat fpVal) {
+ assert(mlir::isa(t) &&
+ "expected floating point type");
+ return create(loc, getAttr(t, fpVal));
+}
+
// This can't be defined in Address.h because that file is included by
// CIRGenBuilder.h
Address Address::withElementType(CIRGenBuilderTy &builder,
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 03077ee062a65..e38faba83b80c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -11,10 +11,12 @@
#include "Address.h"
#include "CIRGenTypeCache.h"
+#include "clang/CIR/Interfaces/CIRFPTypeInterface.h"
#include "clang/CIR/MissingFeatures.h"
#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h"
#include "clang/CIR/MissingFeatures.h"
+#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
namespace clang::CIRGen {
@@ -22,6 +24,7 @@ namespace clang::CIRGen {
class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
const CIRGenTypeCache &typeCache;
llvm::StringMap recordNames;
+ llvm::StringMap globalsVersioning;
public:
CIRGenBuilderTy(mlir::MLIRContext &mlirContext, const CIRGenTypeCache &tc)
@@ -137,8 +140,9 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
}
bool isSized(mlir::Type ty) {
- if (mlir::isa(ty))
+ if (mlir::isa(
+ ty))
return true;
if (const auto vt = mlir::dyn_cast(ty))
@@ -229,6 +233,15 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
cir::IntType getUInt32Ty() { return typeCache.UInt32Ty; }
cir::IntType getUInt64Ty() { return typeCache.UInt64Ty; }
+ cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal);
+
+ cir::ConstantOp getConstInt(mlir::Location loc, llvm::APInt intVal);
+
+ cir::ConstantOp getConstInt(mlir::Location loc, mlir::Type t, uint64_t c);
+
+ cir::ConstantOp getConstFP(mlir::Location loc, mlir::Type t,
+ llvm::APFloat fpVal);
+
bool isInt8Ty(mlir::Type i) {
return i == typeCache.UInt8Ty || i == typeCache.SInt8Ty;
}
@@ -321,6 +334,18 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
return Address(baseAddr, destType, addr.getAlignment());
}
+ /// Cast the element type of the given address to a different type,
+ /// preserving information like the alignment.
+ Address createElementBitCast(mlir::Location loc, Address addr,
+ mlir::Type destType) {
+ if (destType == addr.getElementType())
+ return addr;
+
+ auto ptrTy = getPointerTo(destType);
+ return Address(createBitcast(loc, addr.getPointer(), ptrTy), destType,
+ addr.getAlignment());
+ }
+
cir::LoadOp createLoad(mlir::Location loc, Address addr,
bool isVolatile = false) {
mlir::IntegerAttr align = getAlignmentAttr(addr.getAlignment());
@@ -335,6 +360,12 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
return CIRBaseBuilderTy::createStore(loc, val, dst.getPointer(), align);
}
+ mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real,
+ mlir::Value imag) {
+ auto resultComplexTy = cir::ComplexType::get(real.getType());
+ return create(loc, resultComplexTy, real, imag);
+ }
+
/// Create a cir.ptr_stride operation to get access to an array element.
/// \p idx is the index of the element to access, \p shouldDecay is true if
/// the result should decay to a pointer to the element type.
@@ -347,6 +378,23 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
/// pointed to by \p arrayPtr.
mlir::Value maybeBuildArrayDecay(mlir::Location loc, mlir::Value arrayPtr,
mlir::Type eltTy);
+
+ /// Creates a versioned global variable. If the symbol is already taken, an ID
+ /// will be appended to the symbol. The returned global must always be queried
+ /// for its name so it can be referenced correctly.
+ [[nodiscard]] cir::GlobalOp
+ createVersionedGlobal(mlir::ModuleOp module, mlir::Location loc,
+ mlir::StringRef name, mlir::Type type,
+ cir::GlobalLinkageKind linkage) {
+ // Create a unique name if the given name is already taken.
+ std::string uniqueName;
+ if (unsigned version = globalsVersioning[name.str()]++)
+ uniqueName = name.str() + "." + std::to_string(version);
+ else
+ uniqueName = name.str();
+
+ return createGlobal(module, loc, uniqueName, type, linkage);
+ }
};
} // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
new file mode 100644
index 0000000000000..19fac00ab8736
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -0,0 +1,90 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 contains code to emit Builtin calls as CIR or a function call to be
+// later resolved.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenCall.h"
+#include "CIRGenFunction.h"
+#include "CIRGenModule.h"
+#include "CIRGenValue.h"
+#include "mlir/IR/BuiltinAttributes.h"
+#include "mlir/IR/Value.h"
+#include "mlir/Support/LLVM.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/GlobalDecl.h"
+#include "clang/CIR/MissingFeatures.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace clang;
+using namespace clang::CIRGen;
+using namespace llvm;
+
+static RValue emitLibraryCall(CIRGenFunction &cgf, const FunctionDecl *fd,
+ const CallExpr *e, mlir::Operation *calleeValue) {
+ CIRGenCallee callee = CIRGenCallee::forDirect(calleeValue, GlobalDecl(fd));
+ return cgf.emitCall(e->getCallee()->getType(), callee, e, ReturnValueSlot());
+}
+
+RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
+ const CallExpr *e,
+ ReturnValueSlot returnValue) {
+ // See if we can constant fold this builtin. If so, don't emit it at all.
+ // TODO: Extend this handling to all builtin calls that we can constant-fold.
+ Expr::EvalResult result;
+ if (e->isPRValue() && e->EvaluateAsRValue(result, cgm.getASTContext()) &&
+ !result.hasSideEffects()) {
+ if (result.Val.isInt()) {
+ return RValue::get(builder.getConstInt(getLoc(e->getSourceRange()),
+ result.Val.getInt()));
+ }
+ if (result.Val.isFloat()) {
+ // Note: we are using result type of CallExpr to determine the type of
+ // the constant. Classic codegen uses the result value to determine the
+ // type. We feel it should be Ok to use expression type because it is
+ // hard to imagine a builtin function evaluates to a value that
+ // over/underflows its own defined type.
+ mlir::Type type = convertType(e->getType());
+ return RValue::get(builder.getConstFP(getLoc(e->getExprLoc()), type,
+ result.Val.getFloat()));
+ }
+ }
+
+ const FunctionDecl *fd = gd.getDecl()->getAsFunction();
+
+ // If this is an alias for a lib function (e.g. __builtin_sin), emit
+ // the call using the normal call path, but using the unmangled
+ // version of the function name.
+ if (getContext().BuiltinInfo.isLibFunction(builtinID))
+ return emitLibraryCall(*this, fd, e,
+ cgm.getBuiltinLibFunction(fd, builtinID));
+
+ cgm.errorNYI(e->getSourceRange(), "unimplemented builtin call");
+ return getUndefRValue(e->getType());
+}
+
+/// Given a builtin id for a function like "__builtin_fabsf", return a Function*
+/// for "fabsf".
+cir::FuncOp CIRGenModule::getBuiltinLibFunction(const FunctionDecl *fd,
+ unsigned builtinID) {
+ assert(astContext.BuiltinInfo.isLibFunction(builtinID));
+
+ // Get the name, skip over the __builtin_ prefix (if necessary). We may have
+ // to build this up so provide a small stack buffer to handle the vast
+ // majority of names.
+ llvm::SmallString<64> name;
+
+ assert(!cir::MissingFeatures::asmLabelAttr());
+ name = astContext.BuiltinInfo.getName(builtinID).substr(10);
+
+ GlobalDecl d(fd);
+ mlir::Type type = convertType(fd->getType());
+ return getOrCreateCIRFunction(name, type, d, /*forVTable=*/false);
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenCXX.cpp
new file mode 100644
index 0000000000000..51751483d34e9
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenCXX.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 contains code dealing with C++ code generation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenFunction.h"
+#include "CIRGenModule.h"
+
+#include "clang/AST/GlobalDecl.h"
+#include "clang/CIR/MissingFeatures.h"
+
+using namespace clang;
+using namespace clang::CIRGen;
+
+cir::FuncOp CIRGenModule::codegenCXXStructor(GlobalDecl gd) {
+ const CIRGenFunctionInfo &fnInfo =
+ getTypes().arrangeCXXStructorDeclaration(gd);
+ cir::FuncType funcType = getTypes().getFunctionType(fnInfo);
+ cir::FuncOp fn = getAddrOfCXXStructor(gd, &fnInfo, /*FnType=*/nullptr,
+ /*DontDefer=*/true, ForDefinition);
+ assert(!cir::MissingFeatures::opFuncLinkage());
+ CIRGenFunction cgf{*this, builder};
+ curCGF = &cgf;
+ {
+ mlir::OpBuilder::InsertionGuard guard(builder);
+ cgf.generateCode(gd, fn, funcType);
+ }
+ curCGF = nullptr;
+
+ setNonAliasAttributes(gd, fn);
+ assert(!cir::MissingFeatures::opFuncAttributesForDefinition());
+ return fn;
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
index 107535ebc7275..2d967fd307e01 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
@@ -37,6 +37,10 @@ class CIRGenCXXABI {
void setCXXABIThisValue(CIRGenFunction &cgf, mlir::Value thisPtr);
+ /// Emit a single constructor/destructor with the gen type from a C++
+ /// constructor/destructor Decl.
+ virtual void emitCXXStructor(clang::GlobalDecl gd) = 0;
+
public:
clang::ImplicitParamDecl *getThisDecl(CIRGenFunction &cgf) {
return cgf.cxxabiThisDecl;
@@ -55,12 +59,19 @@ class CIRGenCXXABI {
return md->getParent();
}
+ /// Return whether the given global decl needs a VTT (virtual table table)
+ /// parameter.
+ virtual bool needsVTTParameter(clang::GlobalDecl gd) { return false; }
+
/// Build a parameter variable suitable for 'this'.
void buildThisParam(CIRGenFunction &cgf, FunctionArgList ¶ms);
/// Loads the incoming C++ this pointer as it was passed by the caller.
mlir::Value loadIncomingCXXThis(CIRGenFunction &cgf);
+ /// Emit constructor variants required by this ABI.
+ virtual void emitCXXConstructors(const clang::CXXConstructorDecl *d) = 0;
+
/// Returns true if the given constructor or destructor is one of the kinds
/// that the ABI says returns 'this' (only applies when called non-virtually
/// for destructors).
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index b194a8670bfb9..af0e6ca822b8f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -60,6 +60,30 @@ CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
return *this;
}
+void CIRGenFunction::emitAggregateStore(mlir::Value value, Address dest) {
+ // In classic codegen:
+ // Function to store a first-class aggregate into memory. We prefer to
+ // store the elements rather than the aggregate to be more friendly to
+ // fast-isel.
+ // In CIR codegen:
+ // Emit the most simple cir.store possible (e.g. a store for a whole
+ // record), which can later be broken down in other CIR levels (or prior
+ // to dialect codegen).
+
+ // Stored result for the callers of this function expected to be in the same
+ // scope as the value, don't make assumptions about current insertion point.
+ mlir::OpBuilder::InsertionGuard guard(builder);
+ builder.setInsertionPointAfter(value.getDefiningOp());
+ builder.createStore(*currSrcLoc, value, dest);
+}
+
+/// Returns the canonical formal type of the given C++ method.
+static CanQual getFormalType(const CXXMethodDecl *md) {
+ return md->getType()
+ ->getCanonicalTypeUnqualified()
+ .getAs();
+}
+
/// Adds the formal parameters in FPT to the given prefix. If any parameter in
/// FPT has pass_object_size_attrs, then we'll add parameters for those, too.
/// TODO(cir): this should be shared with LLVM codegen
@@ -76,6 +100,48 @@ static void appendParameterTypes(const CIRGenTypes &cgt,
cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos");
}
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) {
+ auto *md = cast(gd.getDecl());
+
+ llvm::SmallVector argTypes;
+ argTypes.push_back(deriveThisType(md->getParent(), md));
+
+ bool passParams = true;
+
+ if (auto *cd = dyn_cast(md)) {
+ // A base class inheriting constructor doesn't get forwarded arguments
+ // needed to construct a virtual base (or base class thereof)
+ if (cd->getInheritedConstructor())
+ cgm.errorNYI(cd->getSourceRange(),
+ "arrangeCXXStructorDeclaration: inheriting constructor");
+ }
+
+ CanQual fpt = getFormalType(md);
+
+ if (passParams)
+ appendParameterTypes(*this, argTypes, fpt);
+
+ assert(!cir::MissingFeatures::implicitConstructorArgs());
+
+ RequiredArgs required =
+ (passParams && md->isVariadic() ? RequiredArgs(argTypes.size())
+ : RequiredArgs::All);
+
+ CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
+ : theCXXABI.hasMostDerivedReturn(gd)
+ ? astContext.VoidPtrTy
+ : astContext.VoidTy;
+
+ assert(!theCXXABI.hasThisReturn(gd) &&
+ "Please send PR with a test and remove this");
+
+ assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
+ assert(!cir::MissingFeatures::opCallFnInfoOpts());
+
+ return arrangeCIRFunctionInfo(resultType, argTypes, required);
+}
+
/// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR
/// qualification. Either or both of `rd` and `md` may be null. A null `rd`
/// indicates that there is no meaningful 'this' type, and a null `md` can occur
@@ -103,16 +169,56 @@ CanQualType CIRGenTypes::deriveThisType(const CXXRecordDecl *rd,
/// top of any implicit parameters already stored.
static const CIRGenFunctionInfo &
arrangeCIRFunctionInfo(CIRGenTypes &cgt, SmallVectorImpl &prefix,
- CanQual ftp) {
+ CanQual fpt) {
assert(!cir::MissingFeatures::opCallFnInfoOpts());
RequiredArgs required =
- RequiredArgs::getFromProtoWithExtraSlots(ftp, prefix.size());
+ RequiredArgs::getFromProtoWithExtraSlots(fpt, prefix.size());
assert(!cir::MissingFeatures::opCallExtParameterInfo());
- appendParameterTypes(cgt, prefix, ftp);
- CanQualType resultType = ftp->getReturnType().getUnqualifiedType();
+ appendParameterTypes(cgt, prefix, fpt);
+ CanQualType resultType = fpt->getReturnType().getUnqualifiedType();
return cgt.arrangeCIRFunctionInfo(resultType, prefix, required);
}
+void CIRGenFunction::emitDelegateCallArg(CallArgList &args,
+ const VarDecl *param,
+ SourceLocation loc) {
+ // StartFunction converted the ABI-lowered parameter(s) into a local alloca.
+ // We need to turn that into an r-value suitable for emitCall
+ Address local = getAddrOfLocalVar(param);
+
+ QualType type = param->getType();
+
+ if (type->getAsCXXRecordDecl()) {
+ cgm.errorNYI(param->getSourceRange(),
+ "emitDelegateCallArg: record argument");
+ return;
+ }
+
+ // GetAddrOfLocalVar returns a pointer-to-pointer for references, but the
+ // argument needs to be the original pointer.
+ if (type->isReferenceType()) {
+ args.add(
+ RValue::get(builder.createLoad(getLoc(param->getSourceRange()), local)),
+ type);
+ } else if (getLangOpts().ObjCAutoRefCount) {
+ cgm.errorNYI(param->getSourceRange(),
+ "emitDelegateCallArg: ObjCAutoRefCount");
+ // For the most part, we just need to load the alloca, except that aggregate
+ // r-values are actually pointers to temporaries.
+ } else {
+ args.add(convertTempToRValue(local, type, loc), type);
+ }
+
+ // Deactivate the cleanup for the callee-destructed param that was pushed.
+ assert(!cir::MissingFeatures::thunks());
+ if (type->isRecordType() &&
+ type->castAs()->getDecl()->isParamDestroyedInCallee() &&
+ param->needsDestruction(getContext())) {
+ cgm.errorNYI(param->getSourceRange(),
+ "emitDelegateCallArg: callee-destructed param");
+ }
+}
+
static const CIRGenFunctionInfo &
arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm,
const CallArgList &args,
@@ -141,6 +247,44 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm,
return cgt.arrangeCIRFunctionInfo(retType, argTypes, required);
}
+/// Arrange a call to a C++ method, passing the given arguments.
+///
+/// passProtoArgs indicates whether `args` has args for the parameters in the
+/// given CXXConstructorDecl.
+const CIRGenFunctionInfo &CIRGenTypes::arrangeCXXConstructorCall(
+ const CallArgList &args, const CXXConstructorDecl *d, CXXCtorType ctorKind,
+ bool passProtoArgs) {
+
+ // FIXME: Kill copy.
+ llvm::SmallVector argTypes;
+ for (const auto &arg : args)
+ argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
+
+ assert(!cir::MissingFeatures::implicitConstructorArgs());
+ // +1 for implicit this, which should always be args[0]
+ unsigned totalPrefixArgs = 1;
+
+ CanQual fpt = getFormalType(d);
+ RequiredArgs required =
+ passProtoArgs
+ ? RequiredArgs::getFromProtoWithExtraSlots(fpt, totalPrefixArgs)
+ : RequiredArgs::All;
+
+ GlobalDecl gd(d, ctorKind);
+ if (theCXXABI.hasThisReturn(gd))
+ cgm.errorNYI(d->getSourceRange(),
+ "arrangeCXXConstructorCall: hasThisReturn");
+ if (theCXXABI.hasMostDerivedReturn(gd))
+ cgm.errorNYI(d->getSourceRange(),
+ "arrangeCXXConstructorCall: hasMostDerivedReturn");
+ CanQualType resultType = astContext.VoidTy;
+
+ assert(!cir::MissingFeatures::opCallFnInfoOpts());
+ assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
+
+ return arrangeCIRFunctionInfo(resultType, argTypes, required);
+}
+
/// Arrange a call to a C++ method, passing the given arguments.
///
/// numPrefixArgs is the number of the ABI-specific prefix arguments we have. It
@@ -198,7 +342,7 @@ CIRGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *md) {
/// constructor or destructor.
const CIRGenFunctionInfo &
CIRGenTypes::arrangeCXXMethodType(const CXXRecordDecl *rd,
- const FunctionProtoType *ftp,
+ const FunctionProtoType *fpt,
const CXXMethodDecl *md) {
llvm::SmallVector argTypes;
@@ -208,7 +352,7 @@ CIRGenTypes::arrangeCXXMethodType(const CXXRecordDecl *rd,
assert(!cir::MissingFeatures::opCallFnInfoOpts());
return ::arrangeCIRFunctionInfo(
*this, argTypes,
- ftp->getCanonicalTypeUnqualified().getAs());
+ fpt->getCanonicalTypeUnqualified().getAs