Compare commits
194 Commits
main
...
release/21
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ad7bb1cc45 | ||
![]() |
7575bda7e1 | ||
![]() |
69890718e2 | ||
![]() |
0eba8cf2fb | ||
![]() |
5d71f7c2ac | ||
![]() |
65b0685821 | ||
![]() |
333bdbb852 | ||
![]() |
53aa823691 | ||
![]() |
1672f7db87 | ||
![]() |
27fc211bf0 | ||
![]() |
7d6969bc6f | ||
![]() |
45300aad3c | ||
![]() |
2cf40a6ca8 | ||
![]() |
16bea73be5 | ||
![]() |
fe59f72b9a | ||
![]() |
c587c24db5 | ||
![]() |
993c5643ce | ||
![]() |
41cf77340d | ||
![]() |
fcb91597e2 | ||
![]() |
228a893b03 | ||
![]() |
6d631510f9 | ||
![]() |
54766969b2 | ||
![]() |
482e2ffd4c | ||
![]() |
08b5797556 | ||
![]() |
9bf61a610c | ||
![]() |
5a351e93fb | ||
![]() |
08289ad13a | ||
![]() |
af18c6f22e | ||
![]() |
83f2150717 | ||
![]() |
8e0e800222 | ||
![]() |
6096d35ea9 | ||
![]() |
a619e46315 | ||
![]() |
6f5c887e55 | ||
![]() |
f64406b824 | ||
![]() |
c092e2af14 | ||
![]() |
ba87d05c55 | ||
![]() |
7be867f19d | ||
![]() |
3e55c84ab6 | ||
![]() |
17c39c1e05 | ||
![]() |
3aee9c7371 | ||
![]() |
e239f1fc58 | ||
![]() |
768c3245b4 | ||
![]() |
3290ca0fdd | ||
![]() |
0fb2434e9a | ||
![]() |
c8f64bbe68 | ||
![]() |
d51ce3406a | ||
![]() |
3c754bfd9b | ||
![]() |
2555a85378 | ||
![]() |
b398447cbc | ||
![]() |
9ec748cfb1 | ||
![]() |
79f3653fbd | ||
![]() |
6203ddea9f | ||
![]() |
d1f761c8d7 | ||
![]() |
460ff1eb0e | ||
![]() |
bf0f8eae0a | ||
![]() |
f24efe19dc | ||
![]() |
496a49d4a2 | ||
![]() |
3d6fb12dfc | ||
![]() |
400d8b0675 | ||
![]() |
7ee100cced | ||
![]() |
6419104d18 | ||
![]() |
d502822e68 | ||
![]() |
1d46440e9f | ||
![]() |
16bd92cdca | ||
![]() |
d4046ae6df | ||
![]() |
f5ad8dc687 | ||
![]() |
74a0c1e962 | ||
![]() |
489d36cedc | ||
![]() |
863f9963c3 | ||
![]() |
c7ac782942 | ||
![]() |
ca8b2f3777 | ||
![]() |
087cb2e91c | ||
![]() |
8d38ccbb5a | ||
![]() |
9869d43fc2 | ||
![]() |
d9ddd18544 | ||
![]() |
8b85cf53a1 | ||
![]() |
1f17474592 | ||
![]() |
b38f35757b | ||
![]() |
78ce57ca69 | ||
![]() |
80a6bc76cf | ||
![]() |
f207cb4ed2 | ||
![]() |
2dbbc27292 | ||
![]() |
71f9b12e1b | ||
![]() |
773b718c25 | ||
![]() |
d436146305 | ||
![]() |
3b53c84e33 | ||
![]() |
6df1a2879a | ||
![]() |
b1c834f27c | ||
![]() |
9ad630fcb7 | ||
![]() |
614544048c | ||
![]() |
6943f1bf77 | ||
![]() |
8c3ef23106 | ||
![]() |
4ca9a4bb35 | ||
![]() |
7e51c08c82 | ||
![]() |
d8e9216c27 | ||
![]() |
2ec38abcba | ||
![]() |
a3d182bfe3 | ||
![]() |
317403d705 | ||
![]() |
bbc8346e6b | ||
![]() |
f1bca175af | ||
![]() |
dc90bf0329 | ||
![]() |
81a3436485 | ||
![]() |
431af6d04c | ||
![]() |
67cec1afdb | ||
![]() |
c52ff1a825 | ||
![]() |
d4955d9b95 | ||
![]() |
16d81f85e9 | ||
![]() |
bde97f2cef | ||
![]() |
949c6cc95a | ||
![]() |
8c7cf7c06d | ||
![]() |
9ebb0abb02 | ||
![]() |
c198dc74d0 | ||
![]() |
b00e0d2a7e | ||
![]() |
ece444008a | ||
![]() |
52dfd4a272 | ||
![]() |
0d8606fc85 | ||
![]() |
be21c1395e | ||
![]() |
aae69e9f84 | ||
![]() |
ee86ae0a69 | ||
![]() |
1ddf4e3887 | ||
![]() |
6077f45cfb | ||
![]() |
9554152c8a | ||
![]() |
704f542b3d | ||
![]() |
fd13e381e4 | ||
![]() |
ede9fbeac8 | ||
![]() |
3378b765f8 | ||
![]() |
509ec13f26 | ||
![]() |
5345dc9cd3 | ||
![]() |
ba5aa84b54 | ||
![]() |
6df2bfd66b | ||
![]() |
f6c4f0eb70 | ||
![]() |
564ed8e064 | ||
![]() |
3db29aaee5 | ||
![]() |
1db54c705a | ||
![]() |
e43496bacf | ||
![]() |
4d6604adf1 | ||
![]() |
a91da31dd3 | ||
![]() |
dbe3ba0767 | ||
![]() |
132d231605 | ||
![]() |
6cd82c569d | ||
![]() |
64a274fada | ||
![]() |
f66e874504 | ||
![]() |
233fdcb395 | ||
![]() |
54c87e7fdd | ||
![]() |
475ff348f1 | ||
![]() |
6dde087056 | ||
![]() |
02b2a77edb | ||
![]() |
da20f10b5d | ||
![]() |
1ad3d3aea6 | ||
![]() |
c568a207d8 | ||
![]() |
756f489266 | ||
![]() |
aaaa54269b | ||
![]() |
3d520be273 | ||
![]() |
7fd16eecf8 | ||
![]() |
25c1d7a357 | ||
![]() |
17658dbedd | ||
![]() |
cb92bc511e | ||
![]() |
5c69f70244 | ||
![]() |
51245ebda1 | ||
![]() |
275fa26b0c | ||
![]() |
7814dca9a8 | ||
![]() |
b475893a15 | ||
![]() |
69ee6a0edd | ||
![]() |
68cae18965 | ||
![]() |
b5043a0940 | ||
![]() |
0da291f8a6 | ||
![]() |
cbe68e5140 | ||
![]() |
186df07d01 | ||
![]() |
607677c861 | ||
![]() |
e36a7daae2 | ||
![]() |
f1846e747d | ||
![]() |
728030a452 | ||
![]() |
1abeeabd65 | ||
![]() |
cbcb48a88c | ||
![]() |
7ac3c62282 | ||
![]() |
dd7710b7fd | ||
![]() |
ad9051049d | ||
![]() |
2067574f54 | ||
![]() |
38158a93d8 | ||
![]() |
68e17aec8f | ||
![]() |
194dd6679f | ||
![]() |
7c2c20dd9c | ||
![]() |
46c566f579 | ||
![]() |
6ee4eedc2a | ||
![]() |
adb453c8a6 | ||
![]() |
04d4be501d | ||
![]() |
b71c9a4366 | ||
![]() |
49722f1df1 | ||
![]() |
a0895b4581 | ||
![]() |
7d803c868a | ||
![]() |
d1517ec622 | ||
![]() |
588b813079 | ||
![]() |
18624ae54b | ||
![]() |
6296ebd45d |
@ -19,6 +19,7 @@ import sys
|
|||||||
PROJECT_DEPENDENCIES = {
|
PROJECT_DEPENDENCIES = {
|
||||||
"llvm": set(),
|
"llvm": set(),
|
||||||
"clang": {"llvm"},
|
"clang": {"llvm"},
|
||||||
|
"CIR": {"clang", "mlir"},
|
||||||
"bolt": {"clang", "lld", "llvm"},
|
"bolt": {"clang", "lld", "llvm"},
|
||||||
"clang-tools-extra": {"clang", "llvm"},
|
"clang-tools-extra": {"clang", "llvm"},
|
||||||
"compiler-rt": {"clang", "lld"},
|
"compiler-rt": {"clang", "lld"},
|
||||||
@ -55,6 +56,7 @@ DEPENDENTS_TO_TEST = {
|
|||||||
".ci": {
|
".ci": {
|
||||||
"llvm",
|
"llvm",
|
||||||
"clang",
|
"clang",
|
||||||
|
"CIR",
|
||||||
"lld",
|
"lld",
|
||||||
"lldb",
|
"lldb",
|
||||||
"bolt",
|
"bolt",
|
||||||
@ -128,6 +130,7 @@ PROJECT_CHECK_TARGETS = {
|
|||||||
"lldb": "check-lldb",
|
"lldb": "check-lldb",
|
||||||
"llvm": "check-llvm",
|
"llvm": "check-llvm",
|
||||||
"clang": "check-clang",
|
"clang": "check-clang",
|
||||||
|
"CIR": "check-clang-cir",
|
||||||
"bolt": "check-bolt",
|
"bolt": "check-bolt",
|
||||||
"lld": "check-lld",
|
"lld": "check-lld",
|
||||||
"flang": "check-flang",
|
"flang": "check-flang",
|
||||||
@ -141,6 +144,23 @@ PROJECT_CHECK_TARGETS = {
|
|||||||
|
|
||||||
RUNTIMES = {"libcxx", "libcxxabi", "libunwind", "compiler-rt", "libc"}
|
RUNTIMES = {"libcxx", "libcxxabi", "libunwind", "compiler-rt", "libc"}
|
||||||
|
|
||||||
|
# Meta projects are projects that need explicit handling but do not reside
|
||||||
|
# in their own top level folder. To add a meta project, the start of the path
|
||||||
|
# for the metaproject should be mapped to the name of the project below.
|
||||||
|
# Multiple paths can map to the same metaproject.
|
||||||
|
META_PROJECTS = {
|
||||||
|
("clang", "lib", "CIR"): "CIR",
|
||||||
|
("clang", "test", "CIR"): "CIR",
|
||||||
|
("clang", "include", "clang", "CIR"): "CIR",
|
||||||
|
("*", "docs"): "docs",
|
||||||
|
("llvm", "utils", "gn"): "gn",
|
||||||
|
(".github", "workflows", "premerge.yaml"): ".ci",
|
||||||
|
("third-party",): ".ci",
|
||||||
|
}
|
||||||
|
|
||||||
|
# Projects that should not run any tests. These need to be metaprojects.
|
||||||
|
SKIP_PROJECTS = ["docs", "gn"]
|
||||||
|
|
||||||
|
|
||||||
def _add_dependencies(projects: Set[str], runtimes: Set[str]) -> Set[str]:
|
def _add_dependencies(projects: Set[str], runtimes: Set[str]) -> Set[str]:
|
||||||
projects_with_dependents = set(projects)
|
projects_with_dependents = set(projects)
|
||||||
@ -233,21 +253,34 @@ def _compute_runtimes_to_build(
|
|||||||
return _exclude_projects(runtimes_to_build, platform)
|
return _exclude_projects(runtimes_to_build, platform)
|
||||||
|
|
||||||
|
|
||||||
|
def _path_matches(matcher: tuple[str], file_path: tuple[str]) -> bool:
|
||||||
|
if len(file_path) < len(matcher):
|
||||||
|
return False
|
||||||
|
for match_part, file_part in zip(matcher, file_path):
|
||||||
|
if match_part == "*" or file_part == "*":
|
||||||
|
continue
|
||||||
|
if match_part != file_part:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _get_modified_projects_for_file(modified_file: str) -> Set[str]:
|
||||||
|
modified_projects = set()
|
||||||
|
path_parts = pathlib.Path(modified_file).parts
|
||||||
|
for meta_project_files in META_PROJECTS.keys():
|
||||||
|
if _path_matches(meta_project_files, path_parts):
|
||||||
|
meta_project = META_PROJECTS[meta_project_files]
|
||||||
|
if meta_project in SKIP_PROJECTS:
|
||||||
|
return set()
|
||||||
|
modified_projects.add(meta_project)
|
||||||
|
modified_projects.add(pathlib.Path(modified_file).parts[0])
|
||||||
|
return modified_projects
|
||||||
|
|
||||||
|
|
||||||
def _get_modified_projects(modified_files: list[str]) -> Set[str]:
|
def _get_modified_projects(modified_files: list[str]) -> Set[str]:
|
||||||
modified_projects = set()
|
modified_projects = set()
|
||||||
for modified_file in modified_files:
|
for modified_file in modified_files:
|
||||||
path_parts = pathlib.Path(modified_file).parts
|
modified_projects.update(_get_modified_projects_for_file(modified_file))
|
||||||
# Exclude files in the docs directory. They do not impact an test
|
|
||||||
# targets and there is a separate workflow used for ensuring the
|
|
||||||
# documentation builds.
|
|
||||||
if len(path_parts) > 2 and path_parts[1] == "docs":
|
|
||||||
continue
|
|
||||||
# Exclude files for the gn build. We do not test it within premerge
|
|
||||||
# and changes occur often enough that they otherwise take up
|
|
||||||
# capacity.
|
|
||||||
if len(path_parts) > 3 and path_parts[:3] == ("llvm", "utils", "gn"):
|
|
||||||
continue
|
|
||||||
modified_projects.add(pathlib.Path(modified_file).parts[0])
|
|
||||||
return modified_projects
|
return modified_projects
|
||||||
|
|
||||||
|
|
||||||
@ -267,6 +300,13 @@ def get_env_variables(modified_files: list[str], platform: str) -> Set[str]:
|
|||||||
runtimes_check_targets_needs_reconfig = _compute_project_check_targets(
|
runtimes_check_targets_needs_reconfig = _compute_project_check_targets(
|
||||||
runtimes_to_test_needs_reconfig
|
runtimes_to_test_needs_reconfig
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# CIR is used as a pseudo-project in this script. It is built as part of the
|
||||||
|
# clang build, but it requires an explicit option to enable. We set that
|
||||||
|
# option here, and remove it from the projects_to_build list.
|
||||||
|
enable_cir = "ON" if "CIR" in projects_to_build else "OFF"
|
||||||
|
projects_to_build.discard("CIR")
|
||||||
|
|
||||||
# We use a semicolon to separate the projects/runtimes as they get passed
|
# 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
|
# 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
|
# (;). We use spaces to separate the check targets as they end up getting
|
||||||
@ -279,6 +319,7 @@ def get_env_variables(modified_files: list[str], platform: str) -> Set[str]:
|
|||||||
"runtimes_check_targets_needs_reconfig": " ".join(
|
"runtimes_check_targets_needs_reconfig": " ".join(
|
||||||
sorted(runtimes_check_targets_needs_reconfig)
|
sorted(runtimes_check_targets_needs_reconfig)
|
||||||
),
|
),
|
||||||
|
"enable_cir": enable_cir,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
# See https://llvm.org/LICENSE.txt for license information.
|
# See https://llvm.org/LICENSE.txt for license information.
|
||||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
"""Does some stuff."""
|
"""Tests for compute_projects.py"""
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
@ -104,6 +104,10 @@ class TestComputeProjects(unittest.TestCase):
|
|||||||
env_variables["runtimes_check_targets_needs_reconfig"],
|
env_variables["runtimes_check_targets_needs_reconfig"],
|
||||||
"check-cxx check-cxxabi check-unwind",
|
"check-cxx check-cxxabi check-unwind",
|
||||||
)
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
env_variables["enable_cir"],
|
||||||
|
"OFF",
|
||||||
|
)
|
||||||
|
|
||||||
def test_clang_windows(self):
|
def test_clang_windows(self):
|
||||||
env_variables = compute_projects.get_env_variables(
|
env_variables = compute_projects.get_env_variables(
|
||||||
@ -126,6 +130,32 @@ class TestComputeProjects(unittest.TestCase):
|
|||||||
env_variables["runtimes_check_targets_needs_reconfig"],
|
env_variables["runtimes_check_targets_needs_reconfig"],
|
||||||
"check-cxx check-cxxabi check-unwind",
|
"check-cxx check-cxxabi check-unwind",
|
||||||
)
|
)
|
||||||
|
self.assertEqual(env_variables["enable_cir"], "OFF")
|
||||||
|
|
||||||
|
def test_cir(self):
|
||||||
|
env_variables = compute_projects.get_env_variables(
|
||||||
|
["clang/lib/CIR/CMakeLists.txt"], "Linux"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
env_variables["projects_to_build"],
|
||||||
|
"clang;clang-tools-extra;lld;llvm;mlir",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
env_variables["project_check_targets"],
|
||||||
|
"check-clang check-clang-cir check-clang-tools",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
env_variables["runtimes_to_build"], "compiler-rt;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",
|
||||||
|
)
|
||||||
|
self.assertEqual(env_variables["enable_cir"], "ON")
|
||||||
|
|
||||||
def test_bolt(self):
|
def test_bolt(self):
|
||||||
env_variables = compute_projects.get_env_variables(
|
env_variables = compute_projects.get_env_variables(
|
||||||
@ -158,6 +188,7 @@ class TestComputeProjects(unittest.TestCase):
|
|||||||
self.assertEqual(env_variables["runtimes_to_build"], "")
|
self.assertEqual(env_variables["runtimes_to_build"], "")
|
||||||
self.assertEqual(env_variables["runtimes_check_targets"], "")
|
self.assertEqual(env_variables["runtimes_check_targets"], "")
|
||||||
self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "")
|
self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "")
|
||||||
|
self.assertEqual(env_variables["enable_cir"], "OFF")
|
||||||
|
|
||||||
def test_flang(self):
|
def test_flang(self):
|
||||||
env_variables = compute_projects.get_env_variables(
|
env_variables = compute_projects.get_env_variables(
|
||||||
@ -168,10 +199,11 @@ class TestComputeProjects(unittest.TestCase):
|
|||||||
self.assertEqual(env_variables["runtimes_to_build"], "")
|
self.assertEqual(env_variables["runtimes_to_build"], "")
|
||||||
self.assertEqual(env_variables["runtimes_check_targets"], "")
|
self.assertEqual(env_variables["runtimes_check_targets"], "")
|
||||||
self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "")
|
self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "")
|
||||||
|
self.assertEqual(env_variables["enable_cir"], "OFF")
|
||||||
|
|
||||||
def test_invalid_subproject(self):
|
def test_invalid_subproject(self):
|
||||||
env_variables = compute_projects.get_env_variables(
|
env_variables = compute_projects.get_env_variables(
|
||||||
["third-party/benchmark/CMakeLists.txt"], "Linux"
|
["llvm-libgcc/CMakeLists.txt"], "Linux"
|
||||||
)
|
)
|
||||||
self.assertEqual(env_variables["projects_to_build"], "")
|
self.assertEqual(env_variables["projects_to_build"], "")
|
||||||
self.assertEqual(env_variables["project_check_targets"], "")
|
self.assertEqual(env_variables["project_check_targets"], "")
|
||||||
@ -237,7 +269,7 @@ class TestComputeProjects(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
env_variables["project_check_targets"],
|
env_variables["project_check_targets"],
|
||||||
"check-bolt check-clang check-clang-tools check-flang check-lld check-lldb check-llvm check-mlir check-polly",
|
"check-bolt check-clang check-clang-cir check-clang-tools check-flang check-lld check-lldb check-llvm check-mlir check-polly",
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
env_variables["runtimes_to_build"],
|
env_variables["runtimes_to_build"],
|
||||||
@ -276,6 +308,66 @@ class TestComputeProjects(unittest.TestCase):
|
|||||||
self.assertEqual(env_variables["runtimes_check_targets"], "check-libc")
|
self.assertEqual(env_variables["runtimes_check_targets"], "check-libc")
|
||||||
self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "")
|
self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "")
|
||||||
|
|
||||||
|
def test_premerge_workflow(self):
|
||||||
|
env_variables = compute_projects.get_env_variables(
|
||||||
|
[".github/workflows/premerge.yaml"], "Linux"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
env_variables["projects_to_build"],
|
||||||
|
"bolt;clang;clang-tools-extra;flang;libclc;lld;lldb;llvm;mlir;polly",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
env_variables["project_check_targets"],
|
||||||
|
"check-bolt check-clang check-clang-cir check-clang-tools check-flang check-lld check-lldb check-llvm check-mlir check-polly",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
env_variables["runtimes_to_build"],
|
||||||
|
"compiler-rt;libc;libcxx;libcxxabi;libunwind",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
env_variables["runtimes_check_targets"],
|
||||||
|
"check-compiler-rt check-libc",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
env_variables["runtimes_check_targets_needs_reconfig"],
|
||||||
|
"check-cxx check-cxxabi check-unwind",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_other_github_workflow(self):
|
||||||
|
env_variables = compute_projects.get_env_variables(
|
||||||
|
[".github/workflows/docs.yml"], "Linux"
|
||||||
|
)
|
||||||
|
self.assertEqual(env_variables["projects_to_build"], "")
|
||||||
|
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_third_party_benchmark(self):
|
||||||
|
env_variables = compute_projects.get_env_variables(
|
||||||
|
["third-party/benchmark/CMakeLists.txt"], "Linux"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
env_variables["projects_to_build"],
|
||||||
|
"bolt;clang;clang-tools-extra;flang;libclc;lld;lldb;llvm;mlir;polly",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
env_variables["project_check_targets"],
|
||||||
|
"check-bolt check-clang check-clang-cir check-clang-tools check-flang check-lld check-lldb check-llvm check-mlir check-polly",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
env_variables["runtimes_to_build"],
|
||||||
|
"compiler-rt;libc;libcxx;libcxxabi;libunwind",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
env_variables["runtimes_check_targets"],
|
||||||
|
"check-compiler-rt check-libc",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
env_variables["runtimes_check_targets_needs_reconfig"],
|
||||||
|
"check-cxx check-cxxabi check-unwind",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
# 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
|
||||||
|
"""Collects Github metrics and uploads them to Grafana.
|
||||||
|
|
||||||
|
This script contains machinery that will pull metrics periodically from Github
|
||||||
|
about workflow runs. It will upload the collected metrics to the specified
|
||||||
|
Grafana instance.
|
||||||
|
"""
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
import datetime
|
import datetime
|
||||||
import github
|
import github
|
||||||
|
75
.ci/metrics/metrics_test.py
Normal file
75
.ci/metrics/metrics_test.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# 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
|
||||||
|
"""Tests for metrics.py"""
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
import requests
|
||||||
|
import unittest
|
||||||
|
import unittest.mock
|
||||||
|
|
||||||
|
import metrics
|
||||||
|
|
||||||
|
|
||||||
|
class TestMetrics(unittest.TestCase):
|
||||||
|
def test_upload_gauge_metric(self):
|
||||||
|
"""Test that we can upload a gauge metric correctly.
|
||||||
|
|
||||||
|
Also verify that we pass around parameters like API keys and user IDs
|
||||||
|
correctly to the HTTP POST request.
|
||||||
|
"""
|
||||||
|
test_metrics = [metrics.GaugeMetric("gauge_test", 5, 1000)]
|
||||||
|
return_value = requests.Response()
|
||||||
|
return_value.status_code = 204
|
||||||
|
with unittest.mock.patch(
|
||||||
|
"requests.post", return_value=return_value
|
||||||
|
) as post_mock:
|
||||||
|
metrics.upload_metrics(test_metrics, "test_userid", "test_api_key")
|
||||||
|
self.assertSequenceEqual(post_mock.call_args.args, [metrics.GRAFANA_URL])
|
||||||
|
self.assertEqual(
|
||||||
|
post_mock.call_args.kwargs["data"], "gauge_test value=5 1000"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
post_mock.call_args.kwargs["auth"], ("test_userid", "test_api_key")
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_upload_job_metric(self):
|
||||||
|
"""Test that we can upload a job metric correctly."""
|
||||||
|
test_metrics = [
|
||||||
|
metrics.JobMetrics("test_job", 5, 10, 1, 1000, 7, "test_workflow")
|
||||||
|
]
|
||||||
|
return_value = requests.Response()
|
||||||
|
return_value.status_code = 204
|
||||||
|
with unittest.mock.patch(
|
||||||
|
"requests.post", return_value=return_value
|
||||||
|
) as post_mock:
|
||||||
|
metrics.upload_metrics(test_metrics, "test_userid", "test_aoi_key")
|
||||||
|
self.assertEqual(
|
||||||
|
post_mock.call_args.kwargs["data"],
|
||||||
|
"test_job queue_time=5,run_time=10,status=1 1000",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_upload_unknown_metric(self):
|
||||||
|
"""Test we report an error if we encounter an unknown metric type."""
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class FakeMetric:
|
||||||
|
fake_data: str
|
||||||
|
|
||||||
|
test_metrics = [FakeMetric("test")]
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
metrics.upload_metrics(test_metrics, "test_userid", "test_api_key")
|
||||||
|
|
||||||
|
def test_bad_response_code(self):
|
||||||
|
"""Test that we gracefully handle HTTP response errors."""
|
||||||
|
test_metrics = [metrics.GaugeMetric("gauge_test", 5, 1000)]
|
||||||
|
return_value = requests.Response()
|
||||||
|
return_value.status_code = 403
|
||||||
|
# Just assert that we continue running here and do not raise anything.
|
||||||
|
with unittest.mock.patch("requests.post", return_value=return_value) as _:
|
||||||
|
metrics.upload_metrics(test_metrics, "test_userid", "test_api_key")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
@ -21,12 +21,7 @@ BUILD_DIR="${BUILD_DIR:=${MONOREPO_ROOT}/build}"
|
|||||||
INSTALL_DIR="${BUILD_DIR}/install"
|
INSTALL_DIR="${BUILD_DIR}/install"
|
||||||
rm -rf "${BUILD_DIR}"
|
rm -rf "${BUILD_DIR}"
|
||||||
|
|
||||||
ccache --zero-stats
|
sccache --zero-stats
|
||||||
|
|
||||||
if [[ -n "${CLEAR_CACHE:-}" ]]; then
|
|
||||||
echo "clearing cache"
|
|
||||||
ccache --clear
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p artifacts/reproducers
|
mkdir -p artifacts/reproducers
|
||||||
|
|
||||||
@ -36,7 +31,7 @@ export CLANG_CRASH_DIAGNOSTICS_DIR=`realpath artifacts/reproducers`
|
|||||||
function at-exit {
|
function at-exit {
|
||||||
retcode=$?
|
retcode=$?
|
||||||
|
|
||||||
ccache --print-stats > artifacts/ccache_stats.txt
|
sccache --show-stats > artifacts/sccache_stats.txt
|
||||||
cp "${BUILD_DIR}"/.ninja_log artifacts/.ninja_log
|
cp "${BUILD_DIR}"/.ninja_log artifacts/.ninja_log
|
||||||
cp "${BUILD_DIR}"/test-results.*.xml artifacts/ || :
|
cp "${BUILD_DIR}"/test-results.*.xml artifacts/ || :
|
||||||
|
|
||||||
@ -53,6 +48,7 @@ targets="${2}"
|
|||||||
runtimes="${3}"
|
runtimes="${3}"
|
||||||
runtime_targets="${4}"
|
runtime_targets="${4}"
|
||||||
runtime_targets_needs_reconfig="${5}"
|
runtime_targets_needs_reconfig="${5}"
|
||||||
|
enable_cir="${6}"
|
||||||
|
|
||||||
lit_args="-v --xunit-xml-output ${BUILD_DIR}/test-results.xml --use-unique-output-file-name --timeout=1200 --time-tests"
|
lit_args="-v --xunit-xml-output ${BUILD_DIR}/test-results.xml --use-unique-output-file-name --timeout=1200 --time-tests"
|
||||||
|
|
||||||
@ -72,13 +68,15 @@ cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \
|
|||||||
-G Ninja \
|
-G Ninja \
|
||||||
-D CMAKE_PREFIX_PATH="${HOME}/.local" \
|
-D CMAKE_PREFIX_PATH="${HOME}/.local" \
|
||||||
-D CMAKE_BUILD_TYPE=Release \
|
-D CMAKE_BUILD_TYPE=Release \
|
||||||
|
-D CLANG_ENABLE_CIR=${enable_cir} \
|
||||||
-D LLVM_ENABLE_ASSERTIONS=ON \
|
-D LLVM_ENABLE_ASSERTIONS=ON \
|
||||||
-D LLVM_BUILD_EXAMPLES=ON \
|
-D LLVM_BUILD_EXAMPLES=ON \
|
||||||
-D COMPILER_RT_BUILD_LIBFUZZER=OFF \
|
-D COMPILER_RT_BUILD_LIBFUZZER=OFF \
|
||||||
-D LLVM_LIT_ARGS="${lit_args}" \
|
-D LLVM_LIT_ARGS="${lit_args}" \
|
||||||
-D LLVM_ENABLE_LLD=ON \
|
-D LLVM_ENABLE_LLD=ON \
|
||||||
-D CMAKE_CXX_FLAGS=-gmlt \
|
-D CMAKE_CXX_FLAGS=-gmlt \
|
||||||
-D LLVM_CCACHE_BUILD=ON \
|
-D CMAKE_C_COMPILER_LAUNCHER=sccache \
|
||||||
|
-D CMAKE_CXX_COMPILER_LAUNCHER=sccache \
|
||||||
-D LIBCXX_CXX_ABI=libcxxabi \
|
-D LIBCXX_CXX_ABI=libcxxabi \
|
||||||
-D MLIR_ENABLE_BINDINGS_PYTHON=ON \
|
-D MLIR_ENABLE_BINDINGS_PYTHON=ON \
|
||||||
-D LLDB_ENABLE_PYTHON=ON \
|
-D LLDB_ENABLE_PYTHON=ON \
|
||||||
|
@ -21,11 +21,6 @@ BUILD_DIR="${BUILD_DIR:=${MONOREPO_ROOT}/build}"
|
|||||||
|
|
||||||
rm -rf "${BUILD_DIR}"
|
rm -rf "${BUILD_DIR}"
|
||||||
|
|
||||||
if [[ -n "${CLEAR_CACHE:-}" ]]; then
|
|
||||||
echo "clearing sccache"
|
|
||||||
rm -rf "$SCCACHE_DIR"
|
|
||||||
fi
|
|
||||||
|
|
||||||
sccache --zero-stats
|
sccache --zero-stats
|
||||||
function at-exit {
|
function at-exit {
|
||||||
retcode=$?
|
retcode=$?
|
||||||
|
4
.github/workflows/libclang-python-tests.yml
vendored
4
.github/workflows/libclang-python-tests.yml
vendored
@ -10,15 +10,15 @@ on:
|
|||||||
- 'main'
|
- 'main'
|
||||||
paths:
|
paths:
|
||||||
- 'clang/bindings/python/**'
|
- 'clang/bindings/python/**'
|
||||||
- 'clang/test/bindings/python/**'
|
|
||||||
- 'clang/tools/libclang/**'
|
- 'clang/tools/libclang/**'
|
||||||
|
- 'clang/CMakeList.txt'
|
||||||
- '.github/workflows/libclang-python-tests.yml'
|
- '.github/workflows/libclang-python-tests.yml'
|
||||||
- '.github/workflows/llvm-project-tests.yml'
|
- '.github/workflows/llvm-project-tests.yml'
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- 'clang/bindings/python/**'
|
- 'clang/bindings/python/**'
|
||||||
- 'clang/test/bindings/python/**'
|
|
||||||
- 'clang/tools/libclang/**'
|
- 'clang/tools/libclang/**'
|
||||||
|
- 'clang/CMakeList.txt'
|
||||||
- '.github/workflows/libclang-python-tests.yml'
|
- '.github/workflows/libclang-python-tests.yml'
|
||||||
- '.github/workflows/llvm-project-tests.yml'
|
- '.github/workflows/llvm-project-tests.yml'
|
||||||
|
|
||||||
|
17
.github/workflows/libcxx-build-and-test.yaml
vendored
17
.github/workflows/libcxx-build-and-test.yaml
vendored
@ -36,7 +36,7 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
stage1:
|
stage1:
|
||||||
if: github.repository_owner == 'llvm'
|
if: github.repository_owner == 'llvm'
|
||||||
runs-on: llvm-premerge-libcxx-runners
|
runs-on: llvm-premerge-libcxx-release-runners
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@ -73,7 +73,7 @@ jobs:
|
|||||||
**/crash_diagnostics/*
|
**/crash_diagnostics/*
|
||||||
stage2:
|
stage2:
|
||||||
if: github.repository_owner == 'llvm'
|
if: github.repository_owner == 'llvm'
|
||||||
runs-on: llvm-premerge-libcxx-runners
|
runs-on: llvm-premerge-libcxx-release-runners
|
||||||
needs: [ stage1 ]
|
needs: [ stage1 ]
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
strategy:
|
strategy:
|
||||||
@ -128,6 +128,7 @@ jobs:
|
|||||||
'generic-abi-unstable',
|
'generic-abi-unstable',
|
||||||
'generic-hardening-mode-debug',
|
'generic-hardening-mode-debug',
|
||||||
'generic-hardening-mode-extensive',
|
'generic-hardening-mode-extensive',
|
||||||
|
'generic-hardening-mode-extensive-observe-semantic',
|
||||||
'generic-hardening-mode-fast',
|
'generic-hardening-mode-fast',
|
||||||
'generic-hardening-mode-fast-with-abi-breaks',
|
'generic-hardening-mode-fast-with-abi-breaks',
|
||||||
'generic-merged',
|
'generic-merged',
|
||||||
@ -147,19 +148,19 @@ jobs:
|
|||||||
'generic-static',
|
'generic-static',
|
||||||
'bootstrapping-build'
|
'bootstrapping-build'
|
||||||
]
|
]
|
||||||
machine: [ 'llvm-premerge-libcxx-runners' ]
|
machine: [ 'llvm-premerge-libcxx-release-runners' ]
|
||||||
include:
|
include:
|
||||||
- config: 'generic-cxx26'
|
- config: 'generic-cxx26'
|
||||||
machine: llvm-premerge-libcxx-runners
|
machine: llvm-premerge-libcxx-release-runners
|
||||||
- config: 'generic-asan'
|
- config: 'generic-asan'
|
||||||
machine: llvm-premerge-libcxx-runners
|
machine: llvm-premerge-libcxx-release-runners
|
||||||
- config: 'generic-tsan'
|
- config: 'generic-tsan'
|
||||||
machine: llvm-premerge-libcxx-runners
|
machine: llvm-premerge-libcxx-release-runners
|
||||||
- config: 'generic-ubsan'
|
- config: 'generic-ubsan'
|
||||||
machine: llvm-premerge-libcxx-runners
|
machine: llvm-premerge-libcxx-release-runners
|
||||||
# Use a larger machine for MSAN to avoid timeout and memory allocation issues.
|
# Use a larger machine for MSAN to avoid timeout and memory allocation issues.
|
||||||
- config: 'generic-msan'
|
- config: 'generic-msan'
|
||||||
machine: llvm-premerge-libcxx-runners
|
machine: llvm-premerge-libcxx-release-runners
|
||||||
runs-on: ${{ matrix.machine }}
|
runs-on: ${{ matrix.machine }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
30
.github/workflows/premerge.yaml
vendored
30
.github/workflows/premerge.yaml
vendored
@ -34,10 +34,6 @@ jobs:
|
|||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
- name: Setup ccache
|
|
||||||
uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17
|
|
||||||
with:
|
|
||||||
max-size: "2000M"
|
|
||||||
- name: Build and Test
|
- name: Build and Test
|
||||||
# Mark the job as a success even if the step fails so that people do
|
# Mark the job as a success even if the step fails so that people do
|
||||||
# not get notified while the new premerge pipeline is in an
|
# not get notified while the new premerge pipeline is in an
|
||||||
@ -61,7 +57,20 @@ jobs:
|
|||||||
export CC=/opt/llvm/bin/clang
|
export CC=/opt/llvm/bin/clang
|
||||||
export CXX=/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}"
|
# This environment variable is passes into the container through the
|
||||||
|
# runner pod definition. This differs between our two clusters which
|
||||||
|
# why we do not hardcode it.
|
||||||
|
export SCCACHE_GCS_BUCKET=$CACHE_GCS_BUCKET
|
||||||
|
export SCCACHE_GCS_RW_MODE=READ_WRITE
|
||||||
|
|
||||||
|
# Set the idle timeout to zero to ensure sccache runs for the
|
||||||
|
# entire duration of the job. Otherwise it might stop if we run
|
||||||
|
# several test suites in a row and discard statistics that we want
|
||||||
|
# to save in the end.
|
||||||
|
export SCCACHE_IDLE_TIMEOUT=0
|
||||||
|
sccache --start-server
|
||||||
|
|
||||||
|
./.ci/monolithic-linux.sh "${projects_to_build}" "${project_check_targets}" "${runtimes_to_build}" "${runtimes_check_targets}" "${runtimes_check_targets_needs_reconfig}" "${enable_cir}"
|
||||||
- name: Upload Artifacts
|
- name: Upload Artifacts
|
||||||
if: '!cancelled()'
|
if: '!cancelled()'
|
||||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||||
@ -76,7 +85,7 @@ jobs:
|
|||||||
if: >-
|
if: >-
|
||||||
github.repository_owner == 'llvm' &&
|
github.repository_owner == 'llvm' &&
|
||||||
(github.event_name != 'pull_request' || github.event.action != 'closed')
|
(github.event_name != 'pull_request' || github.event.action != 'closed')
|
||||||
runs-on: llvm-premerge-windows-runners
|
runs-on: llvm-premerge-windows-2022-runners
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -85,11 +94,6 @@ jobs:
|
|||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
- name: Setup ccache
|
|
||||||
uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17
|
|
||||||
with:
|
|
||||||
variant: "sccache"
|
|
||||||
max-size: "2000M"
|
|
||||||
- name: Compute Projects
|
- name: Compute Projects
|
||||||
id: vars
|
id: vars
|
||||||
run: |
|
run: |
|
||||||
@ -112,7 +116,9 @@ jobs:
|
|||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
call C:\\BuildTools\\Common7\\Tools\\VsDevCmd.bat -arch=amd64 -host_arch=amd64
|
call C:\\BuildTools\\Common7\\Tools\\VsDevCmd.bat -arch=amd64 -host_arch=amd64
|
||||||
bash .ci/monolithic-windows.sh "${{ steps.vars.outputs.windows-projects }}" "${{ steps.vars.outputs.windows-check-targets }}"
|
# See the comments above in the Linux job for why we define each of
|
||||||
|
# these environment variables.
|
||||||
|
bash -c "export SCCACHE_GCS_BUCKET=$CACHE_GCS_BUCKET; export SCCACHE_GCS_RW_MODE=READ_WRITE; export SCCACHE_IDLE_TIMEOUT=0; sccache --start-server; .ci/monolithic-windows.sh \"${{ steps.vars.outputs.windows-projects }}\" \"${{ steps.vars.outputs.windows-check-targets }}\""
|
||||||
- name: Upload Artifacts
|
- name: Upload Artifacts
|
||||||
if: '!cancelled()'
|
if: '!cancelled()'
|
||||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||||
|
28
.github/workflows/release-tasks.yml
vendored
28
.github/workflows/release-tasks.yml
vendored
@ -111,3 +111,31 @@ jobs:
|
|||||||
# Called workflows don't have access to secrets by default, so we need to explicitly pass secrets that we use.
|
# Called workflows don't have access to secrets by default, so we need to explicitly pass secrets that we use.
|
||||||
secrets:
|
secrets:
|
||||||
RELEASE_TASKS_USER_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }}
|
RELEASE_TASKS_USER_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }}
|
||||||
|
|
||||||
|
uncomment-download-links:
|
||||||
|
name: Uncomment download links
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
permissions:
|
||||||
|
contents: write # For updating the release message.
|
||||||
|
needs:
|
||||||
|
- validate-tag
|
||||||
|
- release-create
|
||||||
|
- release-binaries
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install python3-github
|
||||||
|
|
||||||
|
- name: Checkout LLVM
|
||||||
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
|
with:
|
||||||
|
sparse-checkout: llvm/utils/release/github-upload-release.py
|
||||||
|
sparse-checkout-cone-mode: false
|
||||||
|
|
||||||
|
- name: Uncomment Download Links
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
run: |
|
||||||
|
./llvm/utils/release/./github-upload-release.py --token "$GITHUB_TOKEN" --release ${{ needs.validate-tag.outputs.release-version }} uncomment_download_links
|
||||||
|
@ -315,7 +315,7 @@ struct Fragment {
|
|||||||
/// AngledHeaders (i.e. a header matches a regex in both QuotedHeaders and
|
/// AngledHeaders (i.e. a header matches a regex in both QuotedHeaders and
|
||||||
/// AngledHeaders), system headers use <> and non-system headers use "".
|
/// AngledHeaders), system headers use <> and non-system headers use "".
|
||||||
/// These can match any suffix of the header file in question.
|
/// These can match any suffix of the header file in question.
|
||||||
/// Matching is performed against the header text, not its absolute path
|
/// Matching is performed against the absolute path of the header
|
||||||
/// within the project.
|
/// within the project.
|
||||||
std::vector<Located<std::string>> QuotedHeaders;
|
std::vector<Located<std::string>> QuotedHeaders;
|
||||||
/// List of regexes for headers that should always be included with a
|
/// List of regexes for headers that should always be included with a
|
||||||
@ -323,7 +323,7 @@ struct Fragment {
|
|||||||
/// AngledHeaders (i.e. a header matches a regex in both QuotedHeaders and
|
/// AngledHeaders (i.e. a header matches a regex in both QuotedHeaders and
|
||||||
/// AngledHeaders), system headers use <> and non-system headers use "".
|
/// AngledHeaders), system headers use <> and non-system headers use "".
|
||||||
/// These can match any suffix of the header file in question.
|
/// These can match any suffix of the header file in question.
|
||||||
/// Matching is performed against the header text, not its absolute path
|
/// Matching is performed against the absolute path of the header
|
||||||
/// within the project.
|
/// within the project.
|
||||||
std::vector<Located<std::string>> AngledHeaders;
|
std::vector<Located<std::string>> AngledHeaders;
|
||||||
};
|
};
|
||||||
|
@ -304,16 +304,17 @@ IncludeInserter::calculateIncludePath(const HeaderFile &InsertedHeader,
|
|||||||
// FIXME: should we allow (some limited number of) "../header.h"?
|
// FIXME: should we allow (some limited number of) "../header.h"?
|
||||||
if (llvm::sys::path::is_absolute(Suggested))
|
if (llvm::sys::path::is_absolute(Suggested))
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
auto HeaderPath = llvm::sys::path::convert_to_slash(InsertedHeader.File);
|
||||||
bool IsAngled = false;
|
bool IsAngled = false;
|
||||||
for (auto &Filter : AngledHeaders) {
|
for (auto &Filter : AngledHeaders) {
|
||||||
if (Filter(Suggested)) {
|
if (Filter(HeaderPath)) {
|
||||||
IsAngled = true;
|
IsAngled = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool IsQuoted = false;
|
bool IsQuoted = false;
|
||||||
for (auto &Filter : QuotedHeaders) {
|
for (auto &Filter : QuotedHeaders) {
|
||||||
if (Filter(Suggested)) {
|
if (Filter(HeaderPath)) {
|
||||||
IsQuoted = true;
|
IsQuoted = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -324,7 +325,7 @@ IncludeInserter::calculateIncludePath(const HeaderFile &InsertedHeader,
|
|||||||
if (IsAngled && IsQuoted) {
|
if (IsAngled && IsQuoted) {
|
||||||
elog("Header '{0}' matches both quoted and angled regexes, default will "
|
elog("Header '{0}' matches both quoted and angled regexes, default will "
|
||||||
"be used.",
|
"be used.",
|
||||||
Suggested);
|
HeaderPath);
|
||||||
}
|
}
|
||||||
IsAngled = IsAngledByDefault;
|
IsAngled = IsAngledByDefault;
|
||||||
}
|
}
|
||||||
|
@ -938,7 +938,7 @@ TEST(CompletionTest, IncludeInsertionRespectsQuotedAngledConfig) {
|
|||||||
{
|
{
|
||||||
Config C;
|
Config C;
|
||||||
C.Style.AngledHeaders.push_back(
|
C.Style.AngledHeaders.push_back(
|
||||||
[](auto header) { return header == "bar.h"; });
|
[](auto header) { return header.contains("bar.h"); });
|
||||||
WithContextValue WithCfg(Config::Key, std::move(C));
|
WithContextValue WithCfg(Config::Key, std::move(C));
|
||||||
Results = completions(TU, Test.point(), {Sym});
|
Results = completions(TU, Test.point(), {Sym});
|
||||||
EXPECT_THAT(Results.Completions,
|
EXPECT_THAT(Results.Completions,
|
||||||
@ -947,7 +947,7 @@ TEST(CompletionTest, IncludeInsertionRespectsQuotedAngledConfig) {
|
|||||||
{
|
{
|
||||||
Config C;
|
Config C;
|
||||||
C.Style.QuotedHeaders.push_back(
|
C.Style.QuotedHeaders.push_back(
|
||||||
[](auto header) { return header == "bar.h"; });
|
[](auto header) { return header.contains("bar.h"); });
|
||||||
WithContextValue WithCfg(Config::Key, std::move(C));
|
WithContextValue WithCfg(Config::Key, std::move(C));
|
||||||
Results = completions(TU, Test.point(), {Sym});
|
Results = completions(TU, Test.point(), {Sym});
|
||||||
EXPECT_THAT(Results.Completions,
|
EXPECT_THAT(Results.Completions,
|
||||||
|
@ -344,6 +344,17 @@ TEST_F(HeadersTest, ShortenIncludesInSearchPathBracketed) {
|
|||||||
EXPECT_EQ(calculate(BarHeader), "<sub/bar.h>");
|
EXPECT_EQ(calculate(BarHeader), "<sub/bar.h>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(HeadersTest, ShortenIncludesInSearchPathBracketedFilterByFullPath) {
|
||||||
|
// The filter receives the full path of the header, so it is able to filter by
|
||||||
|
// the parent directory, even if it is part of the include search path
|
||||||
|
AngledHeaders.push_back([](auto Path) {
|
||||||
|
llvm::Regex Pattern("sub/.*");
|
||||||
|
return Pattern.match(Path);
|
||||||
|
});
|
||||||
|
std::string BarHeader = testPath("sub/bar.h");
|
||||||
|
EXPECT_EQ(calculate(BarHeader), "<bar.h>");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(HeadersTest, ShortenedIncludeNotInSearchPath) {
|
TEST_F(HeadersTest, ShortenedIncludeNotInSearchPath) {
|
||||||
std::string BarHeader =
|
std::string BarHeader =
|
||||||
llvm::sys::path::convert_to_slash(testPath("sub-2/bar.h"));
|
llvm::sys::path::convert_to_slash(testPath("sub-2/bar.h"));
|
||||||
|
@ -46,14 +46,18 @@ Major New Features
|
|||||||
Improvements to clangd
|
Improvements to clangd
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
Inlay hints
|
Language feature support
|
||||||
^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Diagnostics
|
- Performance improvements and bugfixes to C++20 Modules support
|
||||||
^^^^^^^^^^^
|
- Improved support for C++23 "deducing this"
|
||||||
|
- Improvements to objective-c++ support
|
||||||
|
|
||||||
Semantic Highlighting
|
New Language Server Protocol features
|
||||||
^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
- Added support for `textDocument/rangesFormatting`
|
||||||
|
- Added support for `positionEncoding`
|
||||||
|
|
||||||
Compile flags
|
Compile flags
|
||||||
^^^^^^^^^^^^^
|
^^^^^^^^^^^^^
|
||||||
@ -64,24 +68,58 @@ Compile flags
|
|||||||
Hover
|
Hover
|
||||||
^^^^^
|
^^^^^
|
||||||
|
|
||||||
|
- Fixed a bug that would sometimes prevent documentation comments of standard library functions
|
||||||
|
from being shown
|
||||||
|
|
||||||
Code completion
|
Code completion
|
||||||
^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Code actions
|
- Added `HeaderInsertion` config option to control whether code completion inserts a missing
|
||||||
^^^^^^^^^^^^
|
header needed for the symbol being completed. This is equivalent to the `--header-insertion`
|
||||||
|
command-line option.
|
||||||
Signature help
|
- Added a `CodePatterns` config option to control whether code completion should offer code
|
||||||
^^^^^^^^^^^^^^
|
patterns as completions in addition to symbols.
|
||||||
|
|
||||||
Cross-references
|
Cross-references
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Objective-C
|
- References to symbols are now collected in array designators
|
||||||
|
- Find-references now works for operators new and delete
|
||||||
|
- Improvements to code navigation in templated code
|
||||||
|
|
||||||
|
Call hierarchy
|
||||||
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
- Call hierarchy now works with the remote index
|
||||||
|
- Fixed a bug where call hierarchy could sometimes return bogus results
|
||||||
|
|
||||||
|
Inlay hints
|
||||||
^^^^^^^^^^^
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
- Parameter hint forwarding now works for variadic forwarding functions declared in header files
|
||||||
|
- Improved presentation of block-end hints
|
||||||
|
|
||||||
|
Code actions
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
|
- Improved the rename refactor's name collision checking logic
|
||||||
|
|
||||||
|
Clang-tidy integration
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
- Disabled the cppcoreguidelines-macro-to-enum checker which is incompatible with clangd
|
||||||
|
|
||||||
|
Include-cleaner integration
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
- Clangd now respects the `AngledHeaders` and `QuotedHeaders` config options for headers
|
||||||
|
inserted to resolve include-cleaner diagnostics
|
||||||
|
|
||||||
Miscellaneous
|
Miscellaneous
|
||||||
^^^^^^^^^^^^^
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
- Various crash fixes and other stability improvements
|
||||||
|
|
||||||
Improvements to clang-doc
|
Improvements to clang-doc
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ struct Header {
|
|||||||
}
|
}
|
||||||
StringRef verbatim() const { return std::get<Verbatim>(Storage); }
|
StringRef verbatim() const { return std::get<Verbatim>(Storage); }
|
||||||
|
|
||||||
/// For phiscal files, either absolute path or path relative to the execution
|
/// For physical files, either absolute path or path relative to the execution
|
||||||
/// root. Otherwise just the spelling without surrounding quotes/brackets.
|
/// root. Otherwise just the spelling without surrounding quotes/brackets.
|
||||||
llvm::StringRef resolvedPath() const;
|
llvm::StringRef resolvedPath() const;
|
||||||
|
|
||||||
|
@ -536,6 +536,7 @@ if( CLANG_INCLUDE_TESTS )
|
|||||||
clang_unit_site_config=${CMAKE_CURRENT_BINARY_DIR}/test/Unit/lit.site.cfg
|
clang_unit_site_config=${CMAKE_CURRENT_BINARY_DIR}/test/Unit/lit.site.cfg
|
||||||
)
|
)
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
|
add_subdirectory(bindings/python/tests)
|
||||||
|
|
||||||
if(CLANG_BUILT_STANDALONE)
|
if(CLANG_BUILT_STANDALONE)
|
||||||
umbrella_lit_testsuite_end(check-all)
|
umbrella_lit_testsuite_end(check-all)
|
||||||
|
66
clang/bindings/python/tests/CMakeLists.txt
Normal file
66
clang/bindings/python/tests/CMakeLists.txt
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# Test target to run Python test suite from main build.
|
||||||
|
|
||||||
|
# Avoid configurations including '-include' from interfering with
|
||||||
|
# our tests by setting CLANG_NO_DEFAULT_CONFIG.
|
||||||
|
add_custom_target(check-clang-python
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E env
|
||||||
|
CLANG_NO_DEFAULT_CONFIG=1
|
||||||
|
CLANG_LIBRARY_PATH=$<TARGET_FILE_DIR:libclang>
|
||||||
|
"${Python3_EXECUTABLE}" -m unittest discover
|
||||||
|
DEPENDS libclang
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||||
|
|
||||||
|
set(RUN_PYTHON_TESTS TRUE)
|
||||||
|
set_target_properties(check-clang-python PROPERTIES FOLDER "Clang/Tests")
|
||||||
|
|
||||||
|
# Tests require libclang.so which is only built with LLVM_ENABLE_PIC=ON
|
||||||
|
if(NOT LLVM_ENABLE_PIC)
|
||||||
|
set(RUN_PYTHON_TESTS FALSE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Do not try to run if libclang was built with sanitizers because
|
||||||
|
# the sanitizer library will likely be loaded too late to perform
|
||||||
|
# interception and will then fail.
|
||||||
|
# We could use LD_PRELOAD/DYLD_INSERT_LIBRARIES but this isn't
|
||||||
|
# portable so its easier just to not run the tests when building
|
||||||
|
# with ASan.
|
||||||
|
if(NOT LLVM_USE_SANITIZER STREQUAL "")
|
||||||
|
set(RUN_PYTHON_TESTS FALSE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Tests fail on Windows, and need someone knowledgeable to fix.
|
||||||
|
# It's not clear whether it's a test or a valid binding problem.
|
||||||
|
if(WIN32)
|
||||||
|
set(RUN_PYTHON_TESTS FALSE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# The Python FFI interface is broken on AIX: https://bugs.python.org/issue38628.
|
||||||
|
if(${CMAKE_SYSTEM_NAME} MATCHES "AIX")
|
||||||
|
set(RUN_PYTHON_TESTS FALSE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# AArch64, Hexagon, and Sparc have known test failures that need to be
|
||||||
|
# addressed.
|
||||||
|
# SystemZ has broken Python/FFI interface:
|
||||||
|
# https://reviews.llvm.org/D52840#1265716
|
||||||
|
if(${LLVM_NATIVE_ARCH} MATCHES "^(AArch64|Hexagon|Sparc|SystemZ)$")
|
||||||
|
set(RUN_PYTHON_TESTS FALSE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Tests will fail if cross-compiling for a different target, as tests will try
|
||||||
|
# to use the host Python3_EXECUTABLE and make FFI calls to functions in target
|
||||||
|
# libraries.
|
||||||
|
if(CMAKE_CROSSCOMPILING)
|
||||||
|
# FIXME: Consider a solution that allows better control over these tests in
|
||||||
|
# a crosscompiling scenario. e.g. registering them with lit to allow them to
|
||||||
|
# be explicitly skipped via appropriate LIT_ARGS, or adding a mechanism to
|
||||||
|
# allow specifying a python interpreter compiled for the target that could
|
||||||
|
# be executed using qemu-user.
|
||||||
|
message(WARNING "check-clang-python not added to check-all as these tests fail in a cross-build setup")
|
||||||
|
set(RUN_PYTHON_TESTS FALSE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(RUN_PYTHON_TESTS)
|
||||||
|
set_property(GLOBAL APPEND PROPERTY
|
||||||
|
LLVM_ALL_ADDITIONAL_TEST_TARGETS check-clang-python)
|
||||||
|
endif()
|
@ -6390,6 +6390,14 @@ the configuration (without a prefix: ``Auto``).
|
|||||||
IF (...) vs. IF(...)
|
IF (...) vs. IF(...)
|
||||||
<conditional-body> <conditional-body>
|
<conditional-body> <conditional-body>
|
||||||
|
|
||||||
|
* ``bool AfterNot`` If ``true``, put a space between alternative operator ``not`` and the
|
||||||
|
opening parenthesis.
|
||||||
|
|
||||||
|
.. code-block:: c++
|
||||||
|
|
||||||
|
true: false:
|
||||||
|
return not (a || b); vs. return not(a || b);
|
||||||
|
|
||||||
* ``bool AfterOverloadedOperator`` If ``true``, put a space between operator overloading and opening
|
* ``bool AfterOverloadedOperator`` If ``true``, put a space between operator overloading and opening
|
||||||
parentheses.
|
parentheses.
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -55,7 +55,7 @@ C/C++ Language Potentially Breaking Changes
|
|||||||
case for old-style offsetof idioms like ``((int)(&(((struct S *)0)->field)))``, to
|
case for old-style offsetof idioms like ``((int)(&(((struct S *)0)->field)))``, to
|
||||||
ensure they are not caught by these optimizations. It is also possible to use
|
ensure they are not caught by these optimizations. It is also possible to use
|
||||||
``-fwrapv-pointer`` or ``-fno-delete-null-pointer-checks`` to make pointer arithmetic
|
``-fwrapv-pointer`` or ``-fno-delete-null-pointer-checks`` to make pointer arithmetic
|
||||||
on null pointers well-defined. (#GH130734, #GH130742, #GH130952)
|
on null pointers well-defined. (#GH130734, #GH130952)
|
||||||
|
|
||||||
C++ Specific Potentially Breaking Changes
|
C++ Specific Potentially Breaking Changes
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
@ -359,6 +359,12 @@ Non-comprehensive list of changes in this release
|
|||||||
ARC-managed pointers and other pointer types. The prior behavior was overly
|
ARC-managed pointers and other pointer types. The prior behavior was overly
|
||||||
strict and inconsistent with the ARC specification.
|
strict and inconsistent with the ARC specification.
|
||||||
|
|
||||||
|
- Use of ``__has_feature`` to detect the ``ptrauth_qualifier`` and ``ptrauth_intrinsics``
|
||||||
|
features has been deprecated, and is restricted to the arm64e target only. The
|
||||||
|
correct method to check for these features is to test for the ``__PTRAUTH__``
|
||||||
|
macro.
|
||||||
|
|
||||||
|
|
||||||
New Compiler Flags
|
New Compiler Flags
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
@ -376,6 +382,8 @@ New Compiler Flags
|
|||||||
|
|
||||||
- New options ``-g[no-]key-instructions`` added, disabled by default. Reduces jumpiness of debug stepping for optimized code in some debuggers (not LLDB at this time). Not recommended for use without optimizations. DWARF only. Note both the positive and negative flags imply ``-g``.
|
- New options ``-g[no-]key-instructions`` added, disabled by default. Reduces jumpiness of debug stepping for optimized code in some debuggers (not LLDB at this time). Not recommended for use without optimizations. DWARF only. Note both the positive and negative flags imply ``-g``.
|
||||||
|
|
||||||
|
- New options ``-fthinlto-distributor=`` and ``-Xthinlto-distributor=`` added for Integrated Distributed ThinLTO (DTLTO). DTLTO enables the distribution of backend ThinLTO compilations via external distribution systems, such as Incredibuild, during the traditional link step. (#GH147265, `ThinLTODocs <https://clang.llvm.org/docs/ThinLTO.html#integrated-distributed-thinlto-dtlto>`_).
|
||||||
|
|
||||||
Deprecated Compiler Flags
|
Deprecated Compiler Flags
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
@ -800,6 +808,8 @@ Bug Fixes in This Version
|
|||||||
declaration statements. Clang now emits a warning for these patterns. (#GH141659)
|
declaration statements. Clang now emits a warning for these patterns. (#GH141659)
|
||||||
- Fixed false positives for redeclaration errors of using enum in
|
- Fixed false positives for redeclaration errors of using enum in
|
||||||
nested scopes. (#GH147495)
|
nested scopes. (#GH147495)
|
||||||
|
- Fixed a crash in `clang-scan-deps` when a module with the same name is found
|
||||||
|
in different locations (#GH134404, #GH146976).
|
||||||
|
|
||||||
Bug Fixes to Compiler Builtins
|
Bug Fixes to Compiler Builtins
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -949,7 +959,6 @@ Bug Fixes to C++ Support
|
|||||||
- Fixed an access checking bug when initializing non-aggregates in default arguments (#GH62444), (#GH83608)
|
- Fixed an access checking bug when initializing non-aggregates in default arguments (#GH62444), (#GH83608)
|
||||||
- Fixed a pack substitution bug in deducing class template partial specializations. (#GH53609)
|
- Fixed a pack substitution bug in deducing class template partial specializations. (#GH53609)
|
||||||
- Fixed a crash when constant evaluating some explicit object member assignment operators. (#GH142835)
|
- Fixed a crash when constant evaluating some explicit object member assignment operators. (#GH142835)
|
||||||
- Fixed an access checking bug when substituting into concepts (#GH115838)
|
|
||||||
- Fix a bug where private access specifier of overloaded function not respected. (#GH107629)
|
- Fix a bug where private access specifier of overloaded function not respected. (#GH107629)
|
||||||
- Correctly handles calling an explicit object member function template overload set
|
- Correctly handles calling an explicit object member function template overload set
|
||||||
through its address (``(&Foo::bar<baz>)()``).
|
through its address (``(&Foo::bar<baz>)()``).
|
||||||
@ -967,6 +976,7 @@ Bug Fixes to C++ Support
|
|||||||
- Fix a crash with NTTP when instantiating local class.
|
- Fix a crash with NTTP when instantiating local class.
|
||||||
- Fixed a crash involving list-initialization of an empty class with a
|
- Fixed a crash involving list-initialization of an empty class with a
|
||||||
non-empty initializer list. (#GH147949)
|
non-empty initializer list. (#GH147949)
|
||||||
|
- Fixed constant evaluation of equality comparisons of constexpr-unknown references. (#GH147663)
|
||||||
|
|
||||||
Bug Fixes to AST Handling
|
Bug Fixes to AST Handling
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -993,6 +1003,19 @@ Miscellaneous Clang Crashes Fixed
|
|||||||
OpenACC Specific Changes
|
OpenACC Specific Changes
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
- OpenACC support, enabled via `-fopenacc` has reached a level of completeness
|
||||||
|
to finally be at least notionally usable. Currently, the OpenACC 3.4
|
||||||
|
specification has been completely implemented for Sema and AST creation, so
|
||||||
|
nodes will show up in the AST after having been properly checked. Lowering is
|
||||||
|
currently a work in progress, with compute, loop, and combined constructs
|
||||||
|
partially implemented, plus a handful of data and executable constructs
|
||||||
|
implemented. Lowering will only work in Clang-IR mode (so only with a compiler
|
||||||
|
built with Clang-IR enabled, and with `-fclangir` used on the command line).
|
||||||
|
However, note that the Clang-IR implementation status is also quite partial,
|
||||||
|
so frequent 'not yet implemented' diagnostics should be expected. Also, the
|
||||||
|
ACC MLIR dialect does not currently implement any lowering to LLVM-IR, so no
|
||||||
|
code generation is possible for OpenACC.
|
||||||
|
|
||||||
Target Specific Changes
|
Target Specific Changes
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
@ -1071,6 +1094,8 @@ Windows Support
|
|||||||
extensions are enabled. This allows for properly processing ``intsafe.h`` in
|
extensions are enabled. This allows for properly processing ``intsafe.h`` in
|
||||||
the Windows SDK.
|
the Windows SDK.
|
||||||
|
|
||||||
|
- Clang now supports `mipsel-windows-gnu` and `mipsel-windows-msvc` targets.
|
||||||
|
|
||||||
LoongArch Support
|
LoongArch Support
|
||||||
^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
@ -1119,9 +1144,19 @@ CUDA/HIP Language Changes
|
|||||||
CUDA Support
|
CUDA Support
|
||||||
^^^^^^^^^^^^
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
|
PowerPC Support
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
* Add `__dmr1024` type for Dense Math Facility.
|
||||||
|
* Add prototype for Dense Math Facility integer calculation builtins.
|
||||||
|
|
||||||
AIX Support
|
AIX Support
|
||||||
^^^^^^^^^^^
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
* Fixed `-print-runtime-dir` to fallback to the target subdirectory (rather than OS subdirectory) if the runtime path is not found.
|
||||||
|
* Fixed `-print-runtime-dir` to find the correct runtime path if the triple has "unknown" as the environment component.
|
||||||
|
* Changed AIX targets to use the per-target runtime directories for compiler runtimes (i.e. `lib/clang/20/lib/aix` became `lib/clang/21/lib/powerpc-ibm-aix` and `clang/21/lib/powerpc64-ibm-aix`).
|
||||||
|
|
||||||
NetBSD Support
|
NetBSD Support
|
||||||
^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
@ -1202,18 +1237,6 @@ New features
|
|||||||
the runtime for the Blocks extension on Windows. This flag currently only
|
the runtime for the Blocks extension on Windows. This flag currently only
|
||||||
changes the code generation, and even then, only on Windows. This does not
|
changes the code generation, and even then, only on Windows. This does not
|
||||||
impact the linker behaviour like the other `-static-*` flags.
|
impact the linker behaviour like the other `-static-*` flags.
|
||||||
- OpenACC support, enabled via `-fopenacc` has reached a level of completeness
|
|
||||||
to finally be at least notionally usable. Currently, the OpenACC 3.4
|
|
||||||
specification has been completely implemented for Sema and AST creation, so
|
|
||||||
nodes will show up in the AST after having been properly checked. Lowering is
|
|
||||||
currently a work in progress, with compute, loop, and combined constructs
|
|
||||||
partially implemented, plus a handful of data and executable constructs
|
|
||||||
implemented. Lowering will only work in Clang-IR mode (so only with a compiler
|
|
||||||
built with Clang-IR enabled, and with `-fclangir` used on the command line).
|
|
||||||
However, note that the Clang-IR implementation status is also quite partial,
|
|
||||||
so frequent 'not yet implemented' diagnostics should be expected. Also, the
|
|
||||||
ACC MLIR dialect does not currently implement any lowering to LLVM-IR, so no
|
|
||||||
code generation is possible for OpenACC.
|
|
||||||
- Implemented `P2719R5 Type-aware allocation and deallocation functions <https://wg21.link/P2719>`_
|
- Implemented `P2719R5 Type-aware allocation and deallocation functions <https://wg21.link/P2719>`_
|
||||||
as an extension in all C++ language modes.
|
as an extension in all C++ language modes.
|
||||||
|
|
||||||
|
@ -240,6 +240,53 @@ The ``BOOTSTRAP_LLVM_ENABLE_LTO=Thin`` will enable ThinLTO for stage 2 and
|
|||||||
stage 3 in case the compiler used for stage 1 does not support the ThinLTO
|
stage 3 in case the compiler used for stage 1 does not support the ThinLTO
|
||||||
option.
|
option.
|
||||||
|
|
||||||
|
Integrated Distributed ThinLTO (DTLTO)
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
Integrated Distributed ThinLTO (DTLTO) enables the distribution of backend
|
||||||
|
ThinLTO compilations via external distribution systems, such as Incredibuild,
|
||||||
|
during the traditional link step.
|
||||||
|
|
||||||
|
The implementation is documented here: https://llvm.org/docs/DTLTO.html.
|
||||||
|
|
||||||
|
Command-Line Options
|
||||||
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
DTLTO requires the LLD linker (``-fuse-ld=lld``).
|
||||||
|
|
||||||
|
``-fthinlto-distributor=<path>``
|
||||||
|
- Specifies the ``<path>`` to the distributor process executable for DTLTO.
|
||||||
|
- If specified, ThinLTO backend compilations will be distributed by LLD.
|
||||||
|
|
||||||
|
``-Xthinlto-distributor=<arg>``
|
||||||
|
- Passes ``<arg>`` to the distributor process (see ``-fthinlto-distributor=``).
|
||||||
|
- Can be specified multiple times to pass multiple options.
|
||||||
|
- Multiple options can also be specified by separating them with commas.
|
||||||
|
|
||||||
|
If ``-fthinlto-distributor=`` is specified, Clang supplies the path to a
|
||||||
|
compiler to be executed remotely to perform the ThinLTO backend
|
||||||
|
compilations. Currently, this is Clang itself.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
Compilation is unchanged from ThinLTO. DTLTO options need to supplied for the link step:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
% clang -flto=thin -fthinlto-distributor=distribute.sh -Xthinlto-distributor=--verbose,--j10 -fuse-ld=lld file1.o file2.o
|
||||||
|
% clang -flto=thin -fthinlto-distributor=$(which python) -Xthinlto-distributor=distribute.py -fuse-ld=lld file1.o file2.o
|
||||||
|
|
||||||
|
When using lld-link:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
% lld-link /out:a.exe file1.obj file2.obj /thinlto-distributor:distribute.exe /thinlto-remote-compiler:${LLVM}\bin\clang.exe /thinlto-distributor-arg:--verbose
|
||||||
|
|
||||||
|
Note that currently, DTLTO is only supported in some LLD flavors. Support can
|
||||||
|
be added to other LLD flavours in the future.
|
||||||
|
See `DTLTO <https://lld.llvm.org/DTLTO.html>`_ for more information.
|
||||||
|
|
||||||
More Information
|
More Information
|
||||||
================
|
================
|
||||||
|
|
||||||
|
@ -6953,6 +6953,21 @@ clang_getCursorUnaryOperatorKind(CXCursor cursor);
|
|||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
CINDEX_DEPRECATED
|
||||||
|
typedef void *CXRemapping;
|
||||||
|
|
||||||
|
CINDEX_DEPRECATED CINDEX_LINKAGE CXRemapping clang_getRemappings(const char *);
|
||||||
|
|
||||||
|
CINDEX_DEPRECATED CINDEX_LINKAGE CXRemapping
|
||||||
|
clang_getRemappingsFromFileList(const char **, unsigned);
|
||||||
|
|
||||||
|
CINDEX_DEPRECATED CINDEX_LINKAGE unsigned clang_remap_getNumFiles(CXRemapping);
|
||||||
|
|
||||||
|
CINDEX_DEPRECATED CINDEX_LINKAGE void
|
||||||
|
clang_remap_getFilenames(CXRemapping, unsigned, CXString *, CXString *);
|
||||||
|
|
||||||
|
CINDEX_DEPRECATED CINDEX_LINKAGE void clang_remap_dispose(CXRemapping);
|
||||||
|
|
||||||
LLVM_CLANG_C_EXTERN_C_END
|
LLVM_CLANG_C_EXTERN_C_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -9417,9 +9417,9 @@ def NonStringDocs : Documentation {
|
|||||||
let Category = DocCatDecl;
|
let Category = DocCatDecl;
|
||||||
let Content = [{
|
let Content = [{
|
||||||
The ``nonstring`` attribute can be applied to the declaration of a variable or
|
The ``nonstring`` attribute can be applied to the declaration of a variable or
|
||||||
a field whose type is a character array to specify that the character array is
|
a field whose type is a character pointer or character array to specify that
|
||||||
not intended to behave like a null-terminated string. This will silence
|
the buffer is not intended to behave like a null-terminated string. This will
|
||||||
diagnostics with code like:
|
silence diagnostics with code like:
|
||||||
|
|
||||||
.. code-block:: c
|
.. code-block:: c
|
||||||
|
|
||||||
|
@ -507,6 +507,14 @@ def note_odr_number_of_bases : Note<
|
|||||||
"class has %0 base %plural{1:class|:classes}0">;
|
"class has %0 base %plural{1:class|:classes}0">;
|
||||||
def note_odr_enumerator : Note<"enumerator %0 with value %1 here">;
|
def note_odr_enumerator : Note<"enumerator %0 with value %1 here">;
|
||||||
def note_odr_missing_enumerator : Note<"no corresponding enumerator here">;
|
def note_odr_missing_enumerator : Note<"no corresponding enumerator here">;
|
||||||
|
def note_odr_incompatible_fixed_underlying_type : Note<
|
||||||
|
"enumeration %0 declared with incompatible fixed underlying types (%1 vs. "
|
||||||
|
"%2)">;
|
||||||
|
def note_odr_fixed_underlying_type : Note<
|
||||||
|
"enumeration %0 has fixed underlying type here">;
|
||||||
|
def note_odr_missing_fixed_underlying_type : Note<
|
||||||
|
"enumeration %0 missing fixed underlying type here">;
|
||||||
|
|
||||||
def err_odr_field_type_inconsistent : Error<
|
def err_odr_field_type_inconsistent : Error<
|
||||||
"field %0 declared with incompatible types in different "
|
"field %0 declared with incompatible types in different "
|
||||||
"translation units (%1 vs. %2)">;
|
"translation units (%1 vs. %2)">;
|
||||||
|
@ -147,14 +147,17 @@ FEATURE(type_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Type))
|
|||||||
FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread))
|
FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread))
|
||||||
FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow))
|
FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow))
|
||||||
FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo))
|
FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo))
|
||||||
FEATURE(ptrauth_intrinsics, LangOpts.PointerAuthIntrinsics)
|
FEATURE(ptrauth_intrinsics, LangOpts.PointerAuthIntrinsics &&
|
||||||
EXTENSION(ptrauth_qualifier, LangOpts.PointerAuthIntrinsics)
|
PP.getTargetInfo().getTriple().isOSDarwin())
|
||||||
|
FEATURE(ptrauth_qualifier, LangOpts.PointerAuthIntrinsics &&
|
||||||
|
PP.getTargetInfo().getTriple().isOSDarwin())
|
||||||
FEATURE(ptrauth_calls, LangOpts.PointerAuthCalls)
|
FEATURE(ptrauth_calls, LangOpts.PointerAuthCalls)
|
||||||
FEATURE(ptrauth_returns, LangOpts.PointerAuthReturns)
|
FEATURE(ptrauth_returns, LangOpts.PointerAuthReturns)
|
||||||
FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtrAddressDiscrimination)
|
FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtrAddressDiscrimination)
|
||||||
FEATURE(ptrauth_vtable_pointer_type_discrimination, LangOpts.PointerAuthVTPtrTypeDiscrimination)
|
FEATURE(ptrauth_vtable_pointer_type_discrimination, LangOpts.PointerAuthVTPtrTypeDiscrimination)
|
||||||
FEATURE(ptrauth_type_info_vtable_pointer_discrimination, LangOpts.PointerAuthTypeInfoVTPtrDiscrimination)
|
FEATURE(ptrauth_type_info_vtable_pointer_discrimination, LangOpts.PointerAuthTypeInfoVTPtrDiscrimination)
|
||||||
FEATURE(ptrauth_member_function_pointer_type_discrimination, LangOpts.PointerAuthCalls)
|
FEATURE(ptrauth_member_function_pointer_type_discrimination, LangOpts.PointerAuthCalls)
|
||||||
|
FEATURE(ptrauth_signed_block_descriptors, LangOpts.PointerAuthBlockDescriptorPointers)
|
||||||
FEATURE(ptrauth_function_pointer_type_discrimination, LangOpts.PointerAuthFunctionTypeDiscrimination)
|
FEATURE(ptrauth_function_pointer_type_discrimination, LangOpts.PointerAuthFunctionTypeDiscrimination)
|
||||||
FEATURE(ptrauth_indirect_gotos, LangOpts.PointerAuthIndirectGotos)
|
FEATURE(ptrauth_indirect_gotos, LangOpts.PointerAuthIndirectGotos)
|
||||||
FEATURE(ptrauth_init_fini, LangOpts.PointerAuthInitFini)
|
FEATURE(ptrauth_init_fini, LangOpts.PointerAuthInitFini)
|
||||||
@ -163,7 +166,7 @@ FEATURE(ptrauth_elf_got, LangOpts.PointerAuthELFGOT)
|
|||||||
|
|
||||||
FEATURE(ptrauth_objc_isa, LangOpts.PointerAuthObjcIsa)
|
FEATURE(ptrauth_objc_isa, LangOpts.PointerAuthObjcIsa)
|
||||||
FEATURE(ptrauth_objc_interface_sel, LangOpts.PointerAuthObjcInterfaceSel)
|
FEATURE(ptrauth_objc_interface_sel, LangOpts.PointerAuthObjcInterfaceSel)
|
||||||
FEATURE(ptrauth_objc_signable_class, true)
|
FEATURE(ptrauth_objc_signable_class, LangOpts.PointerAuthIntrinsics)
|
||||||
FEATURE(ptrauth_objc_method_list_pointer, LangOpts.PointerAuthCalls)
|
FEATURE(ptrauth_objc_method_list_pointer, LangOpts.PointerAuthCalls)
|
||||||
|
|
||||||
EXTENSION(swiftcc,
|
EXTENSION(swiftcc,
|
||||||
|
@ -138,6 +138,8 @@ LANGOPT(PointerAuthObjcInterfaceSel, 1, 0, NotCompatible, "authentication of SEL
|
|||||||
LANGOPT(PointerAuthObjcInterfaceSelKey, 16, 0, NotCompatible, "authentication key for SEL fields of ObjC interfaces")
|
LANGOPT(PointerAuthObjcInterfaceSelKey, 16, 0, NotCompatible, "authentication key for SEL fields of ObjC interfaces")
|
||||||
LANGOPT(PointerAuthObjcClassROPointers, 1, 0, Benign, "class_ro_t pointer authentication")
|
LANGOPT(PointerAuthObjcClassROPointers, 1, 0, Benign, "class_ro_t pointer authentication")
|
||||||
|
|
||||||
|
LANGOPT(PointerAuthBlockDescriptorPointers, 1, 0, NotCompatible, "enable signed block descriptors")
|
||||||
|
|
||||||
LANGOPT(DoubleSquareBracketAttributes, 1, 0, NotCompatible, "'[[]]' attributes extension for all language standard modes")
|
LANGOPT(DoubleSquareBracketAttributes, 1, 0, NotCompatible, "'[[]]' attributes extension for all language standard modes")
|
||||||
LANGOPT(ExperimentalLateParseAttributes, 1, 0, NotCompatible, "experimental late parsing of attributes")
|
LANGOPT(ExperimentalLateParseAttributes, 1, 0, NotCompatible, "experimental late parsing of attributes")
|
||||||
|
|
||||||
@ -496,6 +498,8 @@ LANGOPT(CheckConstexprFunctionBodies, 1, 1, Benign,
|
|||||||
|
|
||||||
LANGOPT(BoundsSafety, 1, 0, NotCompatible, "Bounds safety extension for C")
|
LANGOPT(BoundsSafety, 1, 0, NotCompatible, "Bounds safety extension for C")
|
||||||
|
|
||||||
|
LANGOPT(EnableLifetimeSafety, 1, 0, NotCompatible, "Experimental lifetime safety analysis for C++")
|
||||||
|
|
||||||
LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector type")
|
LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector type")
|
||||||
|
|
||||||
#undef LANGOPT
|
#undef LANGOPT
|
||||||
|
@ -23,6 +23,10 @@
|
|||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
||||||
|
/// Constant discriminator to be used with block descriptor pointers. The value
|
||||||
|
/// is ptrauth_string_discriminator("block_descriptor")
|
||||||
|
constexpr uint16_t BlockDescriptorConstantDiscriminator = 0xC0BB;
|
||||||
|
|
||||||
/// Constant discriminator to be used with function pointers in .init_array and
|
/// Constant discriminator to be used with function pointers in .init_array and
|
||||||
/// .fini_array. The value is ptrauth_string_discriminator("init_fini")
|
/// .fini_array. The value is ptrauth_string_discriminator("init_fini")
|
||||||
constexpr uint16_t InitFiniPointerConstantDiscriminator = 0xD9D4;
|
constexpr uint16_t InitFiniPointerConstantDiscriminator = 0xD9D4;
|
||||||
@ -223,6 +227,18 @@ struct PointerAuthOptions {
|
|||||||
/// The ABI for function addresses in .init_array and .fini_array
|
/// The ABI for function addresses in .init_array and .fini_array
|
||||||
PointerAuthSchema InitFiniPointers;
|
PointerAuthSchema InitFiniPointers;
|
||||||
|
|
||||||
|
/// The ABI for block invocation function pointers.
|
||||||
|
PointerAuthSchema BlockInvocationFunctionPointers;
|
||||||
|
|
||||||
|
/// The ABI for block object copy/destroy function pointers.
|
||||||
|
PointerAuthSchema BlockHelperFunctionPointers;
|
||||||
|
|
||||||
|
/// The ABI for __block variable copy/destroy function pointers.
|
||||||
|
PointerAuthSchema BlockByrefHelperFunctionPointers;
|
||||||
|
|
||||||
|
/// The ABI for pointers to block descriptors.
|
||||||
|
PointerAuthSchema BlockDescriptorPointers;
|
||||||
|
|
||||||
/// The ABI for Objective-C method lists.
|
/// The ABI for Objective-C method lists.
|
||||||
PointerAuthSchema ObjCMethodListFunctionPointers;
|
PointerAuthSchema ObjCMethodListFunctionPointers;
|
||||||
|
|
||||||
|
@ -990,6 +990,13 @@ def Xlinker : Separate<["-"], "Xlinker">, Flags<[LinkerInput, RenderAsInput]>,
|
|||||||
Visibility<[ClangOption, CLOption, FlangOption]>,
|
Visibility<[ClangOption, CLOption, FlangOption]>,
|
||||||
HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">,
|
HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">,
|
||||||
Group<Link_Group>;
|
Group<Link_Group>;
|
||||||
|
def Xthinlto_distributor_EQ : CommaJoined<["-"], "Xthinlto-distributor=">,
|
||||||
|
Flags<[LinkOption]>,
|
||||||
|
Visibility<[ClangOption, CLOption]>,
|
||||||
|
HelpText<"Pass <arg> to the ThinLTO distributor process. Can be specified "
|
||||||
|
"multiple times or with comma-separated values.">,
|
||||||
|
MetaVarName<"<arg>">,
|
||||||
|
Group<Link_Group>;
|
||||||
def Xoffload_linker : JoinedAndSeparate<["-"], "Xoffload-linker">,
|
def Xoffload_linker : JoinedAndSeparate<["-"], "Xoffload-linker">,
|
||||||
Visibility<[ClangOption, FlangOption]>,
|
Visibility<[ClangOption, FlangOption]>,
|
||||||
HelpText<"Pass <arg> to the offload linkers or the ones identified by -<triple>">,
|
HelpText<"Pass <arg> to the offload linkers or the ones identified by -<triple>">,
|
||||||
@ -1910,6 +1917,14 @@ defm bounds_safety : BoolFOption<
|
|||||||
BothFlags<[], [CC1Option],
|
BothFlags<[], [CC1Option],
|
||||||
" experimental bounds safety extension for C">>;
|
" experimental bounds safety extension for C">>;
|
||||||
|
|
||||||
|
defm lifetime_safety : BoolFOption<
|
||||||
|
"experimental-lifetime-safety",
|
||||||
|
LangOpts<"EnableLifetimeSafety">, DefaultFalse,
|
||||||
|
PosFlag<SetTrue, [], [CC1Option], "Enable">,
|
||||||
|
NegFlag<SetFalse, [], [CC1Option], "Disable">,
|
||||||
|
BothFlags<[], [CC1Option],
|
||||||
|
" experimental lifetime safety for C++">>;
|
||||||
|
|
||||||
defm addrsig : BoolFOption<"addrsig",
|
defm addrsig : BoolFOption<"addrsig",
|
||||||
CodeGenOpts<"Addrsig">, DefaultFalse,
|
CodeGenOpts<"Addrsig">, DefaultFalse,
|
||||||
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Emit">,
|
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Emit">,
|
||||||
@ -4249,7 +4264,12 @@ def ffinite_loops: Flag<["-"], "ffinite-loops">, Group<f_Group>,
|
|||||||
def fno_finite_loops: Flag<["-"], "fno-finite-loops">, Group<f_Group>,
|
def fno_finite_loops: Flag<["-"], "fno-finite-loops">, Group<f_Group>,
|
||||||
HelpText<"Do not assume that any loop is finite.">,
|
HelpText<"Do not assume that any loop is finite.">,
|
||||||
Visibility<[ClangOption, CC1Option]>;
|
Visibility<[ClangOption, CC1Option]>;
|
||||||
|
def fthinlto_distributor_EQ : Joined<["-"], "fthinlto-distributor=">,
|
||||||
|
Group<f_Group>,
|
||||||
|
HelpText<"Path to the ThinLTO distributor process. If specified, "
|
||||||
|
"ThinLTO backend compilations will be distributed by LLD">,
|
||||||
|
MetaVarName<"<path>">,
|
||||||
|
Visibility<[ClangOption, CLOption]>;
|
||||||
def ftrigraphs : Flag<["-"], "ftrigraphs">, Group<f_Group>,
|
def ftrigraphs : Flag<["-"], "ftrigraphs">, Group<f_Group>,
|
||||||
HelpText<"Process trigraph sequences">, Visibility<[ClangOption, CC1Option]>;
|
HelpText<"Process trigraph sequences">, Visibility<[ClangOption, CC1Option]>;
|
||||||
def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>,
|
def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>,
|
||||||
@ -4507,6 +4527,7 @@ defm aarch64_jump_table_hardening: OptInCC1FFlag<"aarch64-jump-table-hardening",
|
|||||||
defm ptrauth_objc_isa : OptInCC1FFlag<"ptrauth-objc-isa", "Enable signing and authentication of Objective-C object's 'isa' field">;
|
defm ptrauth_objc_isa : OptInCC1FFlag<"ptrauth-objc-isa", "Enable signing and authentication of Objective-C object's 'isa' field">;
|
||||||
defm ptrauth_objc_interface_sel : OptInCC1FFlag<"ptrauth-objc-interface-sel", "Enable signing and authentication of Objective-C object's 'SEL' fields">;
|
defm ptrauth_objc_interface_sel : OptInCC1FFlag<"ptrauth-objc-interface-sel", "Enable signing and authentication of Objective-C object's 'SEL' fields">;
|
||||||
defm ptrauth_objc_class_ro : OptInCC1FFlag<"ptrauth-objc-class-ro", "Enable signing and authentication for ObjC class_ro pointers">;
|
defm ptrauth_objc_class_ro : OptInCC1FFlag<"ptrauth-objc-class-ro", "Enable signing and authentication for ObjC class_ro pointers">;
|
||||||
|
defm ptrauth_block_descriptor_pointers : OptInCC1FFlag<"ptrauth-block-descriptor-pointers", "Enable signing and authentication of block descriptors">;
|
||||||
}
|
}
|
||||||
|
|
||||||
def fenable_matrix : Flag<["-"], "fenable-matrix">, Group<f_Group>,
|
def fenable_matrix : Flag<["-"], "fenable-matrix">, Group<f_Group>,
|
||||||
|
@ -4694,6 +4694,13 @@ struct FormatStyle {
|
|||||||
/// <conditional-body> <conditional-body>
|
/// <conditional-body> <conditional-body>
|
||||||
/// \endcode
|
/// \endcode
|
||||||
bool AfterIfMacros;
|
bool AfterIfMacros;
|
||||||
|
/// If ``true``, put a space between alternative operator ``not`` and the
|
||||||
|
/// opening parenthesis.
|
||||||
|
/// \code
|
||||||
|
/// true: false:
|
||||||
|
/// return not (a || b); vs. return not(a || b);
|
||||||
|
/// \endcode
|
||||||
|
bool AfterNot;
|
||||||
/// If ``true``, put a space between operator overloading and opening
|
/// If ``true``, put a space between operator overloading and opening
|
||||||
/// parentheses.
|
/// parentheses.
|
||||||
/// \code
|
/// \code
|
||||||
@ -4742,9 +4749,9 @@ struct FormatStyle {
|
|||||||
: AfterControlStatements(false), AfterForeachMacros(false),
|
: AfterControlStatements(false), AfterForeachMacros(false),
|
||||||
AfterFunctionDeclarationName(false),
|
AfterFunctionDeclarationName(false),
|
||||||
AfterFunctionDefinitionName(false), AfterIfMacros(false),
|
AfterFunctionDefinitionName(false), AfterIfMacros(false),
|
||||||
AfterOverloadedOperator(false), AfterPlacementOperator(true),
|
AfterNot(false), AfterOverloadedOperator(false),
|
||||||
AfterRequiresInClause(false), AfterRequiresInExpression(false),
|
AfterPlacementOperator(true), AfterRequiresInClause(false),
|
||||||
BeforeNonEmptyParentheses(false) {}
|
AfterRequiresInExpression(false), BeforeNonEmptyParentheses(false) {}
|
||||||
|
|
||||||
bool operator==(const SpaceBeforeParensCustom &Other) const {
|
bool operator==(const SpaceBeforeParensCustom &Other) const {
|
||||||
return AfterControlStatements == Other.AfterControlStatements &&
|
return AfterControlStatements == Other.AfterControlStatements &&
|
||||||
@ -4753,6 +4760,7 @@ struct FormatStyle {
|
|||||||
Other.AfterFunctionDeclarationName &&
|
Other.AfterFunctionDeclarationName &&
|
||||||
AfterFunctionDefinitionName == Other.AfterFunctionDefinitionName &&
|
AfterFunctionDefinitionName == Other.AfterFunctionDefinitionName &&
|
||||||
AfterIfMacros == Other.AfterIfMacros &&
|
AfterIfMacros == Other.AfterIfMacros &&
|
||||||
|
AfterNot == Other.AfterNot &&
|
||||||
AfterOverloadedOperator == Other.AfterOverloadedOperator &&
|
AfterOverloadedOperator == Other.AfterOverloadedOperator &&
|
||||||
AfterPlacementOperator == Other.AfterPlacementOperator &&
|
AfterPlacementOperator == Other.AfterPlacementOperator &&
|
||||||
AfterRequiresInClause == Other.AfterRequiresInClause &&
|
AfterRequiresInClause == Other.AfterRequiresInClause &&
|
||||||
|
@ -143,9 +143,6 @@ class Lexer : public PreprocessorLexer {
|
|||||||
/// True if this is the first time we're lexing the input file.
|
/// True if this is the first time we're lexing the input file.
|
||||||
bool IsFirstTimeLexingFile;
|
bool IsFirstTimeLexingFile;
|
||||||
|
|
||||||
/// True if current lexing token is the first pp-token.
|
|
||||||
bool IsFirstPPToken;
|
|
||||||
|
|
||||||
// NewLinePtr - A pointer to new line character '\n' being lexed. For '\r\n',
|
// NewLinePtr - A pointer to new line character '\n' being lexed. For '\r\n',
|
||||||
// it also points to '\n.'
|
// it also points to '\n.'
|
||||||
const char *NewLinePtr;
|
const char *NewLinePtr;
|
||||||
|
310
clang/include/clang/Lex/NoTrivialPPDirectiveTracer.h
Normal file
310
clang/include/clang/Lex/NoTrivialPPDirectiveTracer.h
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
//===--- NoTrivialPPDirectiveTracer.h ---------------------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file defines the NoTrivialPPDirectiveTracer interface.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_CLANG_LEX_NO_TRIVIAL_PPDIRECTIVE_TRACER_H
|
||||||
|
#define LLVM_CLANG_LEX_NO_TRIVIAL_PPDIRECTIVE_TRACER_H
|
||||||
|
|
||||||
|
#include "clang/Lex/PPCallbacks.h"
|
||||||
|
|
||||||
|
namespace clang {
|
||||||
|
class Preprocessor;
|
||||||
|
|
||||||
|
/// Consider the following code:
|
||||||
|
///
|
||||||
|
/// # 1 __FILE__ 1 3
|
||||||
|
/// export module a;
|
||||||
|
///
|
||||||
|
/// According to the wording in
|
||||||
|
/// [P1857R3](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1857r3.html):
|
||||||
|
///
|
||||||
|
/// A module directive may only appear as the first preprocessing tokens in a
|
||||||
|
/// file (excluding the global module fragment.)
|
||||||
|
///
|
||||||
|
/// and the wording in
|
||||||
|
/// [[cpp.pre]](https://eel.is/c++draft/cpp.pre#nt:module-file):
|
||||||
|
/// module-file:
|
||||||
|
/// pp-global-module-fragment[opt] pp-module group[opt]
|
||||||
|
/// pp-private-module-fragment[opt]
|
||||||
|
///
|
||||||
|
/// `#` is the first pp-token in the translation unit, and it was rejected by
|
||||||
|
/// clang, but they really should be exempted from this rule. The goal is to not
|
||||||
|
/// allow any preprocessor conditionals or most state changes, but these don't
|
||||||
|
/// fit that.
|
||||||
|
///
|
||||||
|
/// State change would mean most semantically observable preprocessor state,
|
||||||
|
/// particularly anything that is order dependent. Global flags like being a
|
||||||
|
/// system header/module shouldn't matter.
|
||||||
|
///
|
||||||
|
/// We should exempt a brunch of directives, even though it violates the current
|
||||||
|
/// standard wording.
|
||||||
|
///
|
||||||
|
/// This class used to trace 'no-trivial' pp-directives in main file, which may
|
||||||
|
/// change the preprocessing state.
|
||||||
|
///
|
||||||
|
/// FIXME: Once the wording of the standard is revised, we need to follow the
|
||||||
|
/// wording of the standard. Currently this is just a workaround
|
||||||
|
class NoTrivialPPDirectiveTracer : public PPCallbacks {
|
||||||
|
Preprocessor &PP;
|
||||||
|
|
||||||
|
/// Whether preprocessing main file. We only focus on the main file.
|
||||||
|
bool InMainFile = true;
|
||||||
|
|
||||||
|
/// Whether one or more conditional, include or other 'no-trivial'
|
||||||
|
/// pp-directives has seen before.
|
||||||
|
bool SeenNoTrivialPPDirective = false;
|
||||||
|
|
||||||
|
void setSeenNoTrivialPPDirective();
|
||||||
|
|
||||||
|
public:
|
||||||
|
NoTrivialPPDirectiveTracer(Preprocessor &P) : PP(P) {}
|
||||||
|
|
||||||
|
bool hasSeenNoTrivialPPDirective() const;
|
||||||
|
|
||||||
|
/// Callback invoked whenever the \p Lexer moves to a different file for
|
||||||
|
/// lexing. Unlike \p FileChanged line number directives and other related
|
||||||
|
/// pragmas do not trigger callbacks to \p LexedFileChanged.
|
||||||
|
///
|
||||||
|
/// \param FID The \p FileID that the \p Lexer moved to.
|
||||||
|
///
|
||||||
|
/// \param Reason Whether the \p Lexer entered a new file or exited one.
|
||||||
|
///
|
||||||
|
/// \param FileType The \p CharacteristicKind of the file the \p Lexer moved
|
||||||
|
/// to.
|
||||||
|
///
|
||||||
|
/// \param PrevFID The \p FileID the \p Lexer was using before the change.
|
||||||
|
///
|
||||||
|
/// \param Loc The location where the \p Lexer entered a new file from or the
|
||||||
|
/// location that the \p Lexer moved into after exiting a file.
|
||||||
|
void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
|
||||||
|
SrcMgr::CharacteristicKind FileType, FileID PrevFID,
|
||||||
|
SourceLocation Loc) override;
|
||||||
|
|
||||||
|
/// Callback invoked whenever an embed directive has been processed,
|
||||||
|
/// regardless of whether the embed will actually find a file.
|
||||||
|
///
|
||||||
|
/// \param HashLoc The location of the '#' that starts the embed directive.
|
||||||
|
///
|
||||||
|
/// \param FileName The name of the file being included, as written in the
|
||||||
|
/// source code.
|
||||||
|
///
|
||||||
|
/// \param IsAngled Whether the file name was enclosed in angle brackets;
|
||||||
|
/// otherwise, it was enclosed in quotes.
|
||||||
|
///
|
||||||
|
/// \param File The actual file that may be included by this embed directive.
|
||||||
|
///
|
||||||
|
/// \param Params The parameters used by the directive.
|
||||||
|
void EmbedDirective(SourceLocation HashLoc, StringRef FileName, bool IsAngled,
|
||||||
|
OptionalFileEntryRef File,
|
||||||
|
const LexEmbedParametersResult &Params) override {
|
||||||
|
setSeenNoTrivialPPDirective();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Callback invoked whenever an inclusion directive of
|
||||||
|
/// any kind (\c \#include, \c \#import, etc.) has been processed, regardless
|
||||||
|
/// of whether the inclusion will actually result in an inclusion.
|
||||||
|
///
|
||||||
|
/// \param HashLoc The location of the '#' that starts the inclusion
|
||||||
|
/// directive.
|
||||||
|
///
|
||||||
|
/// \param IncludeTok The token that indicates the kind of inclusion
|
||||||
|
/// directive, e.g., 'include' or 'import'.
|
||||||
|
///
|
||||||
|
/// \param FileName The name of the file being included, as written in the
|
||||||
|
/// source code.
|
||||||
|
///
|
||||||
|
/// \param IsAngled Whether the file name was enclosed in angle brackets;
|
||||||
|
/// otherwise, it was enclosed in quotes.
|
||||||
|
///
|
||||||
|
/// \param FilenameRange The character range of the quotes or angle brackets
|
||||||
|
/// for the written file name.
|
||||||
|
///
|
||||||
|
/// \param File The actual file that may be included by this inclusion
|
||||||
|
/// directive.
|
||||||
|
///
|
||||||
|
/// \param SearchPath Contains the search path which was used to find the file
|
||||||
|
/// in the file system. If the file was found via an absolute include path,
|
||||||
|
/// SearchPath will be empty. For framework includes, the SearchPath and
|
||||||
|
/// RelativePath will be split up. For example, if an include of "Some/Some.h"
|
||||||
|
/// is found via the framework path
|
||||||
|
/// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be
|
||||||
|
/// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be
|
||||||
|
/// "Some.h".
|
||||||
|
///
|
||||||
|
/// \param RelativePath The path relative to SearchPath, at which the include
|
||||||
|
/// file was found. This is equal to FileName except for framework includes.
|
||||||
|
///
|
||||||
|
/// \param SuggestedModule The module suggested for this header, if any.
|
||||||
|
///
|
||||||
|
/// \param ModuleImported Whether this include was translated into import of
|
||||||
|
/// \p SuggestedModule.
|
||||||
|
///
|
||||||
|
/// \param FileType The characteristic kind, indicates whether a file or
|
||||||
|
/// directory holds normal user code, system code, or system code which is
|
||||||
|
/// implicitly 'extern "C"' in C++ mode.
|
||||||
|
///
|
||||||
|
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
|
||||||
|
StringRef FileName, bool IsAngled,
|
||||||
|
CharSourceRange FilenameRange,
|
||||||
|
OptionalFileEntryRef File, StringRef SearchPath,
|
||||||
|
StringRef RelativePath, const Module *SuggestedModule,
|
||||||
|
bool ModuleImported,
|
||||||
|
SrcMgr::CharacteristicKind FileType) override {
|
||||||
|
setSeenNoTrivialPPDirective();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Callback invoked whenever there was an explicit module-import
|
||||||
|
/// syntax.
|
||||||
|
///
|
||||||
|
/// \param ImportLoc The location of import directive token.
|
||||||
|
///
|
||||||
|
/// \param Path The identifiers (and their locations) of the module
|
||||||
|
/// "path", e.g., "std.vector" would be split into "std" and "vector".
|
||||||
|
///
|
||||||
|
/// \param Imported The imported module; can be null if importing failed.
|
||||||
|
///
|
||||||
|
void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
|
||||||
|
const Module *Imported) override {
|
||||||
|
setSeenNoTrivialPPDirective();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Callback invoked when the end of the main file is reached.
|
||||||
|
///
|
||||||
|
/// No subsequent callbacks will be made.
|
||||||
|
void EndOfMainFile() override { setSeenNoTrivialPPDirective(); }
|
||||||
|
|
||||||
|
/// Callback invoked when start reading any pragma directive.
|
||||||
|
void PragmaDirective(SourceLocation Loc,
|
||||||
|
PragmaIntroducerKind Introducer) override {}
|
||||||
|
|
||||||
|
/// Called by Preprocessor::HandleMacroExpandedIdentifier when a
|
||||||
|
/// macro invocation is found.
|
||||||
|
void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
|
||||||
|
SourceRange Range, const MacroArgs *Args) override;
|
||||||
|
|
||||||
|
/// Hook called whenever a macro definition is seen.
|
||||||
|
void MacroDefined(const Token &MacroNameTok,
|
||||||
|
const MacroDirective *MD) override {
|
||||||
|
setSeenNoTrivialPPDirective();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hook called whenever a macro \#undef is seen.
|
||||||
|
/// \param MacroNameTok The active Token
|
||||||
|
/// \param MD A MacroDefinition for the named macro.
|
||||||
|
/// \param Undef New MacroDirective if the macro was defined, null otherwise.
|
||||||
|
///
|
||||||
|
/// MD is released immediately following this callback.
|
||||||
|
void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD,
|
||||||
|
const MacroDirective *Undef) override {
|
||||||
|
setSeenNoTrivialPPDirective();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hook called whenever the 'defined' operator is seen.
|
||||||
|
/// \param MD The MacroDirective if the name was a macro, null otherwise.
|
||||||
|
void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
|
||||||
|
SourceRange Range) override {
|
||||||
|
setSeenNoTrivialPPDirective();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hook called whenever an \#if is seen.
|
||||||
|
/// \param Loc the source location of the directive.
|
||||||
|
/// \param ConditionRange The SourceRange of the expression being tested.
|
||||||
|
/// \param ConditionValue The evaluated value of the condition.
|
||||||
|
///
|
||||||
|
// FIXME: better to pass in a list (or tree!) of Tokens.
|
||||||
|
void If(SourceLocation Loc, SourceRange ConditionRange,
|
||||||
|
ConditionValueKind ConditionValue) override {
|
||||||
|
setSeenNoTrivialPPDirective();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hook called whenever an \#elif is seen.
|
||||||
|
/// \param Loc the source location of the directive.
|
||||||
|
/// \param ConditionRange The SourceRange of the expression being tested.
|
||||||
|
/// \param ConditionValue The evaluated value of the condition.
|
||||||
|
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
|
||||||
|
// FIXME: better to pass in a list (or tree!) of Tokens.
|
||||||
|
void Elif(SourceLocation Loc, SourceRange ConditionRange,
|
||||||
|
ConditionValueKind ConditionValue, SourceLocation IfLoc) override {
|
||||||
|
setSeenNoTrivialPPDirective();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hook called whenever an \#ifdef is seen.
|
||||||
|
/// \param Loc the source location of the directive.
|
||||||
|
/// \param MacroNameTok Information on the token being tested.
|
||||||
|
/// \param MD The MacroDefinition if the name was a macro, null otherwise.
|
||||||
|
void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
|
||||||
|
const MacroDefinition &MD) override {
|
||||||
|
setSeenNoTrivialPPDirective();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hook called whenever an \#elifdef branch is taken.
|
||||||
|
/// \param Loc the source location of the directive.
|
||||||
|
/// \param MacroNameTok Information on the token being tested.
|
||||||
|
/// \param MD The MacroDefinition if the name was a macro, null otherwise.
|
||||||
|
void Elifdef(SourceLocation Loc, const Token &MacroNameTok,
|
||||||
|
const MacroDefinition &MD) override {
|
||||||
|
setSeenNoTrivialPPDirective();
|
||||||
|
}
|
||||||
|
/// Hook called whenever an \#elifdef is skipped.
|
||||||
|
/// \param Loc the source location of the directive.
|
||||||
|
/// \param ConditionRange The SourceRange of the expression being tested.
|
||||||
|
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
|
||||||
|
// FIXME: better to pass in a list (or tree!) of Tokens.
|
||||||
|
void Elifdef(SourceLocation Loc, SourceRange ConditionRange,
|
||||||
|
SourceLocation IfLoc) override {
|
||||||
|
setSeenNoTrivialPPDirective();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hook called whenever an \#ifndef is seen.
|
||||||
|
/// \param Loc the source location of the directive.
|
||||||
|
/// \param MacroNameTok Information on the token being tested.
|
||||||
|
/// \param MD The MacroDefiniton if the name was a macro, null otherwise.
|
||||||
|
void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
|
||||||
|
const MacroDefinition &MD) override {
|
||||||
|
setSeenNoTrivialPPDirective();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hook called whenever an \#elifndef branch is taken.
|
||||||
|
/// \param Loc the source location of the directive.
|
||||||
|
/// \param MacroNameTok Information on the token being tested.
|
||||||
|
/// \param MD The MacroDefinition if the name was a macro, null otherwise.
|
||||||
|
void Elifndef(SourceLocation Loc, const Token &MacroNameTok,
|
||||||
|
const MacroDefinition &MD) override {
|
||||||
|
setSeenNoTrivialPPDirective();
|
||||||
|
}
|
||||||
|
/// Hook called whenever an \#elifndef is skipped.
|
||||||
|
/// \param Loc the source location of the directive.
|
||||||
|
/// \param ConditionRange The SourceRange of the expression being tested.
|
||||||
|
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
|
||||||
|
// FIXME: better to pass in a list (or tree!) of Tokens.
|
||||||
|
void Elifndef(SourceLocation Loc, SourceRange ConditionRange,
|
||||||
|
SourceLocation IfLoc) override {
|
||||||
|
setSeenNoTrivialPPDirective();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hook called whenever an \#else is seen.
|
||||||
|
/// \param Loc the source location of the directive.
|
||||||
|
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
|
||||||
|
void Else(SourceLocation Loc, SourceLocation IfLoc) override {
|
||||||
|
setSeenNoTrivialPPDirective();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hook called whenever an \#endif is seen.
|
||||||
|
/// \param Loc the source location of the directive.
|
||||||
|
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
|
||||||
|
void Endif(SourceLocation Loc, SourceLocation IfLoc) override {
|
||||||
|
setSeenNoTrivialPPDirective();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace clang
|
||||||
|
|
||||||
|
#endif // LLVM_CLANG_LEX_NO_TRIVIAL_PPDIRECTIVE_TRACER_H
|
@ -82,6 +82,7 @@ class PreprocessorLexer;
|
|||||||
class PreprocessorOptions;
|
class PreprocessorOptions;
|
||||||
class ScratchBuffer;
|
class ScratchBuffer;
|
||||||
class TargetInfo;
|
class TargetInfo;
|
||||||
|
class NoTrivialPPDirectiveTracer;
|
||||||
|
|
||||||
namespace Builtin {
|
namespace Builtin {
|
||||||
class Context;
|
class Context;
|
||||||
@ -353,6 +354,11 @@ private:
|
|||||||
/// First pp-token source location in current translation unit.
|
/// First pp-token source location in current translation unit.
|
||||||
SourceLocation FirstPPTokenLoc;
|
SourceLocation FirstPPTokenLoc;
|
||||||
|
|
||||||
|
/// A preprocessor directive tracer to trace whether the preprocessing
|
||||||
|
/// state changed. These changes would mean most semantically observable
|
||||||
|
/// preprocessor state, particularly anything that is order dependent.
|
||||||
|
NoTrivialPPDirectiveTracer *DirTracer = nullptr;
|
||||||
|
|
||||||
/// A position within a C++20 import-seq.
|
/// A position within a C++20 import-seq.
|
||||||
class StdCXXImportSeq {
|
class StdCXXImportSeq {
|
||||||
public:
|
public:
|
||||||
@ -609,6 +615,8 @@ private:
|
|||||||
return State == NamedModuleImplementation && !getName().contains(':');
|
return State == NamedModuleImplementation && !getName().contains(':');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isNotAModuleDecl() const { return State == NotAModuleDecl; }
|
||||||
|
|
||||||
StringRef getName() const {
|
StringRef getName() const {
|
||||||
assert(isNamedModule() && "Can't get name from a non named module");
|
assert(isNamedModule() && "Can't get name from a non named module");
|
||||||
return Name;
|
return Name;
|
||||||
@ -3087,6 +3095,10 @@ public:
|
|||||||
bool setDeserializedSafeBufferOptOutMap(
|
bool setDeserializedSafeBufferOptOutMap(
|
||||||
const SmallVectorImpl<SourceLocation> &SrcLocSeqs);
|
const SmallVectorImpl<SourceLocation> &SrcLocSeqs);
|
||||||
|
|
||||||
|
/// Whether we've seen pp-directives which may have changed the preprocessing
|
||||||
|
/// state.
|
||||||
|
bool hasSeenNoTrivialPPDirective() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Helper functions to forward lexing to the actual lexer. They all share the
|
/// Helper functions to forward lexing to the actual lexer. They all share the
|
||||||
/// same signature.
|
/// same signature.
|
||||||
|
@ -86,12 +86,12 @@ public:
|
|||||||
// macro stringizing or charizing operator.
|
// macro stringizing or charizing operator.
|
||||||
CommaAfterElided = 0x200, // The comma following this token was elided (MS).
|
CommaAfterElided = 0x200, // The comma following this token was elided (MS).
|
||||||
IsEditorPlaceholder = 0x400, // This identifier is a placeholder.
|
IsEditorPlaceholder = 0x400, // This identifier is a placeholder.
|
||||||
|
IsReinjected = 0x800, // A phase 4 token that was produced before and
|
||||||
IsReinjected = 0x800, // A phase 4 token that was produced before and
|
// re-added, e.g. via EnterTokenStream. Annotation
|
||||||
// re-added, e.g. via EnterTokenStream. Annotation
|
// tokens are *not* reinjected.
|
||||||
// tokens are *not* reinjected.
|
HasSeenNoTrivialPPDirective =
|
||||||
FirstPPToken = 0x1000, // This token is the first pp token in the
|
0x1000, // Whether we've seen any 'no-trivial' pp-directives before
|
||||||
// translation unit.
|
// current position.
|
||||||
};
|
};
|
||||||
|
|
||||||
tok::TokenKind getKind() const { return Kind; }
|
tok::TokenKind getKind() const { return Kind; }
|
||||||
@ -321,8 +321,9 @@ public:
|
|||||||
/// lexer uses identifier tokens to represent placeholders.
|
/// lexer uses identifier tokens to represent placeholders.
|
||||||
bool isEditorPlaceholder() const { return getFlag(IsEditorPlaceholder); }
|
bool isEditorPlaceholder() const { return getFlag(IsEditorPlaceholder); }
|
||||||
|
|
||||||
/// Returns true if this token is the first pp-token.
|
bool hasSeenNoTrivialPPDirective() const {
|
||||||
bool isFirstPPToken() const { return getFlag(FirstPPToken); }
|
return getFlag(HasSeenNoTrivialPPDirective);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Information about the conditional stack (\#if directives)
|
/// Information about the conditional stack (\#if directives)
|
||||||
|
@ -350,11 +350,6 @@ class Sema;
|
|||||||
LLVM_PREFERRED_TYPE(bool)
|
LLVM_PREFERRED_TYPE(bool)
|
||||||
unsigned BindsToRvalue : 1;
|
unsigned BindsToRvalue : 1;
|
||||||
|
|
||||||
/// Whether this was an identity conversion with qualification
|
|
||||||
/// conversion for the implicit object argument.
|
|
||||||
LLVM_PREFERRED_TYPE(bool)
|
|
||||||
unsigned IsImplicitObjectArgumentQualificationConversion : 1;
|
|
||||||
|
|
||||||
/// Whether this binds an implicit object argument to a
|
/// Whether this binds an implicit object argument to a
|
||||||
/// non-static member function without a ref-qualifier.
|
/// non-static member function without a ref-qualifier.
|
||||||
LLVM_PREFERRED_TYPE(bool)
|
LLVM_PREFERRED_TYPE(bool)
|
||||||
@ -453,11 +448,11 @@ class Sema;
|
|||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (!C.hasSameType(getFromType(), getToType(2)))
|
||||||
|
return false;
|
||||||
if (BindsToRvalue && IsLvalueReference)
|
if (BindsToRvalue && IsLvalueReference)
|
||||||
return false;
|
return false;
|
||||||
if (IsImplicitObjectArgumentQualificationConversion)
|
return true;
|
||||||
return C.hasSameUnqualifiedType(getFromType(), getToType(2));
|
|
||||||
return C.hasSameType(getFromType(), getToType(2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImplicitConversionRank getRank() const;
|
ImplicitConversionRank getRank() const;
|
||||||
|
@ -9836,7 +9836,7 @@ public:
|
|||||||
SourceLocation ModuleLoc, ModuleDeclKind MDK,
|
SourceLocation ModuleLoc, ModuleDeclKind MDK,
|
||||||
ModuleIdPath Path, ModuleIdPath Partition,
|
ModuleIdPath Path, ModuleIdPath Partition,
|
||||||
ModuleImportState &ImportState,
|
ModuleImportState &ImportState,
|
||||||
bool IntroducerIsFirstPPToken);
|
bool SeenNoTrivialPPDirective);
|
||||||
|
|
||||||
/// The parser has processed a global-module-fragment declaration that begins
|
/// The parser has processed a global-module-fragment declaration that begins
|
||||||
/// the definition of the global module fragment of the current module unit.
|
/// the definition of the global module fragment of the current module unit.
|
||||||
|
@ -456,7 +456,9 @@ CheckStructurallyEquivalentAttributes(StructuralEquivalenceContext &Context,
|
|||||||
const Decl *D1, const Decl *D2,
|
const Decl *D1, const Decl *D2,
|
||||||
const Decl *PrimaryDecl = nullptr) {
|
const Decl *PrimaryDecl = nullptr) {
|
||||||
// If either declaration has an attribute on it, we treat the declarations
|
// If either declaration has an attribute on it, we treat the declarations
|
||||||
// as not being structurally equivalent.
|
// as not being structurally equivalent unless both declarations are implicit
|
||||||
|
// (ones generated by the compiler like __NSConstantString_tag).
|
||||||
|
//
|
||||||
// FIXME: this should be handled on a case-by-case basis via tablegen in
|
// FIXME: this should be handled on a case-by-case basis via tablegen in
|
||||||
// Attr.td. There are multiple cases to consider: one declaration with the
|
// Attr.td. There are multiple cases to consider: one declaration with the
|
||||||
// attribute, another without it; different attribute syntax|spellings for
|
// attribute, another without it; different attribute syntax|spellings for
|
||||||
@ -468,7 +470,7 @@ CheckStructurallyEquivalentAttributes(StructuralEquivalenceContext &Context,
|
|||||||
D1Attr = *D1->getAttrs().begin();
|
D1Attr = *D1->getAttrs().begin();
|
||||||
if (D2->hasAttrs())
|
if (D2->hasAttrs())
|
||||||
D2Attr = *D2->getAttrs().begin();
|
D2Attr = *D2->getAttrs().begin();
|
||||||
if (D1Attr || D2Attr) {
|
if ((D1Attr || D2Attr) && !D1->isImplicit() && !D2->isImplicit()) {
|
||||||
const auto *DiagnoseDecl = cast<TypeDecl>(PrimaryDecl ? PrimaryDecl : D2);
|
const auto *DiagnoseDecl = cast<TypeDecl>(PrimaryDecl ? PrimaryDecl : D2);
|
||||||
Context.Diag2(DiagnoseDecl->getLocation(),
|
Context.Diag2(DiagnoseDecl->getLocation(),
|
||||||
diag::warn_odr_tag_type_with_attributes)
|
diag::warn_odr_tag_type_with_attributes)
|
||||||
@ -873,7 +875,29 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
|||||||
else if (T1->getTypeClass() == Type::FunctionNoProto &&
|
else if (T1->getTypeClass() == Type::FunctionNoProto &&
|
||||||
T2->getTypeClass() == Type::FunctionProto)
|
T2->getTypeClass() == Type::FunctionProto)
|
||||||
TC = Type::FunctionNoProto;
|
TC = Type::FunctionNoProto;
|
||||||
else
|
else if (Context.LangOpts.C23 && !Context.StrictTypeSpelling &&
|
||||||
|
(T1->getTypeClass() == Type::Enum ||
|
||||||
|
T2->getTypeClass() == Type::Enum)) {
|
||||||
|
// In C23, if not being strict about token equivalence, we need to handle
|
||||||
|
// the case where one type is an enumeration and the other type is an
|
||||||
|
// integral type.
|
||||||
|
//
|
||||||
|
// C23 6.7.3.3p16: The enumerated type is compatible with the underlying
|
||||||
|
// type of the enumeration.
|
||||||
|
//
|
||||||
|
// Treat the enumeration as its underlying type and use the builtin type
|
||||||
|
// class comparison.
|
||||||
|
if (T1->getTypeClass() == Type::Enum) {
|
||||||
|
T1 = T1->getAs<EnumType>()->getDecl()->getIntegerType();
|
||||||
|
if (!T2->isBuiltinType() || T1.isNull()) // Sanity check
|
||||||
|
return false;
|
||||||
|
} else if (T2->getTypeClass() == Type::Enum) {
|
||||||
|
T2 = T2->getAs<EnumType>()->getDecl()->getIntegerType();
|
||||||
|
if (!T1->isBuiltinType() || T2.isNull()) // Sanity check
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TC = Type::Builtin;
|
||||||
|
} else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2067,6 +2091,48 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
|||||||
!CheckStructurallyEquivalentAttributes(Context, D1, D2))
|
!CheckStructurallyEquivalentAttributes(Context, D1, D2))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// In C23, if one enumeration has a fixed underlying type, the other shall
|
||||||
|
// have a compatible fixed underlying type (6.2.7).
|
||||||
|
if (Context.LangOpts.C23) {
|
||||||
|
if (D1->isFixed() != D2->isFixed()) {
|
||||||
|
if (Context.Complain) {
|
||||||
|
Context.Diag2(D2->getLocation(),
|
||||||
|
Context.getApplicableDiagnostic(
|
||||||
|
diag::err_odr_tag_type_inconsistent))
|
||||||
|
<< Context.ToCtx.getTypeDeclType(D2)
|
||||||
|
<< (&Context.FromCtx != &Context.ToCtx);
|
||||||
|
Context.Diag1(D1->getLocation(),
|
||||||
|
D1->isFixed()
|
||||||
|
? diag::note_odr_fixed_underlying_type
|
||||||
|
: diag::note_odr_missing_fixed_underlying_type)
|
||||||
|
<< D1;
|
||||||
|
Context.Diag2(D2->getLocation(),
|
||||||
|
D2->isFixed()
|
||||||
|
? diag::note_odr_fixed_underlying_type
|
||||||
|
: diag::note_odr_missing_fixed_underlying_type)
|
||||||
|
<< D2;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (D1->isFixed()) {
|
||||||
|
assert(D2->isFixed() && "enums expected to have fixed underlying types");
|
||||||
|
if (!IsStructurallyEquivalent(Context, D1->getIntegerType(),
|
||||||
|
D2->getIntegerType())) {
|
||||||
|
if (Context.Complain) {
|
||||||
|
Context.Diag2(D2->getLocation(),
|
||||||
|
Context.getApplicableDiagnostic(
|
||||||
|
diag::err_odr_tag_type_inconsistent))
|
||||||
|
<< Context.ToCtx.getTypeDeclType(D2)
|
||||||
|
<< (&Context.FromCtx != &Context.ToCtx);
|
||||||
|
Context.Diag2(D2->getLocation(),
|
||||||
|
diag::note_odr_incompatible_fixed_underlying_type)
|
||||||
|
<< D2 << D2->getIntegerType() << D1->getIntegerType();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
llvm::SmallVector<const EnumConstantDecl *, 8> D1Enums, D2Enums;
|
llvm::SmallVector<const EnumConstantDecl *, 8> D1Enums, D2Enums;
|
||||||
auto CopyEnumerators =
|
auto CopyEnumerators =
|
||||||
[](auto &&Range, llvm::SmallVectorImpl<const EnumConstantDecl *> &Cont) {
|
[](auto &&Range, llvm::SmallVectorImpl<const EnumConstantDecl *> &Cont) {
|
||||||
|
@ -4441,7 +4441,8 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
|
|||||||
}
|
}
|
||||||
} else if (!IsAccess) {
|
} else if (!IsAccess) {
|
||||||
return CompleteObject(LVal.getLValueBase(), nullptr, BaseType);
|
return CompleteObject(LVal.getLValueBase(), nullptr, BaseType);
|
||||||
} else if (IsConstant && Info.checkingPotentialConstantExpression() &&
|
} else if ((IsConstant || BaseType->isReferenceType()) &&
|
||||||
|
Info.checkingPotentialConstantExpression() &&
|
||||||
BaseType->isLiteralType(Info.Ctx) && !VD->hasDefinition()) {
|
BaseType->isLiteralType(Info.Ctx) && !VD->hasDefinition()) {
|
||||||
// This variable might end up being constexpr. Don't diagnose it yet.
|
// This variable might end up being constexpr. Don't diagnose it yet.
|
||||||
} else if (IsConstant) {
|
} else if (IsConstant) {
|
||||||
@ -4478,9 +4479,11 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
|
|||||||
// a null BaseVal. Any constexpr-unknown variable seen here is an error:
|
// a null BaseVal. Any constexpr-unknown variable seen here is an error:
|
||||||
// we can't access a constexpr-unknown object.
|
// we can't access a constexpr-unknown object.
|
||||||
if (!BaseVal) {
|
if (!BaseVal) {
|
||||||
Info.FFDiag(E, diag::note_constexpr_access_unknown_variable, 1)
|
if (!Info.checkingPotentialConstantExpression()) {
|
||||||
<< AK << VD;
|
Info.FFDiag(E, diag::note_constexpr_access_unknown_variable, 1)
|
||||||
Info.Note(VD->getLocation(), diag::note_declared_at);
|
<< AK << VD;
|
||||||
|
Info.Note(VD->getLocation(), diag::note_declared_at);
|
||||||
|
}
|
||||||
return CompleteObject();
|
return CompleteObject();
|
||||||
}
|
}
|
||||||
} else if (DynamicAllocLValue DA = LVal.Base.dyn_cast<DynamicAllocLValue>()) {
|
} else if (DynamicAllocLValue DA = LVal.Base.dyn_cast<DynamicAllocLValue>()) {
|
||||||
@ -14478,12 +14481,6 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
|
|||||||
if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK)
|
if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// If we have Unknown pointers we should fail if they are not global values.
|
|
||||||
if (!(IsGlobalLValue(LHSValue.getLValueBase()) &&
|
|
||||||
IsGlobalLValue(RHSValue.getLValueBase())) &&
|
|
||||||
(LHSValue.AllowConstexprUnknown || RHSValue.AllowConstexprUnknown))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Reject differing bases from the normal codepath; we special-case
|
// Reject differing bases from the normal codepath; we special-case
|
||||||
// comparisons to null.
|
// comparisons to null.
|
||||||
if (!HasSameBase(LHSValue, RHSValue)) {
|
if (!HasSameBase(LHSValue, RHSValue)) {
|
||||||
@ -14545,6 +14542,10 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
|
|||||||
(LHSValue.Base && isZeroSized(RHSValue)))
|
(LHSValue.Base && isZeroSized(RHSValue)))
|
||||||
return DiagComparison(
|
return DiagComparison(
|
||||||
diag::note_constexpr_pointer_comparison_zero_sized);
|
diag::note_constexpr_pointer_comparison_zero_sized);
|
||||||
|
if (LHSValue.AllowConstexprUnknown || RHSValue.AllowConstexprUnknown)
|
||||||
|
return DiagComparison(
|
||||||
|
diag::note_constexpr_pointer_comparison_unspecified);
|
||||||
|
// FIXME: Verify both variables are live.
|
||||||
return Success(CmpResult::Unequal, E);
|
return Success(CmpResult::Unequal, E);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14565,7 +14566,9 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
|
|||||||
if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && IsRelational) {
|
if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && IsRelational) {
|
||||||
bool WasArrayIndex;
|
bool WasArrayIndex;
|
||||||
unsigned Mismatch = FindDesignatorMismatch(
|
unsigned Mismatch = FindDesignatorMismatch(
|
||||||
getType(LHSValue.Base), LHSDesignator, RHSDesignator, WasArrayIndex);
|
LHSValue.Base.isNull() ? QualType()
|
||||||
|
: getType(LHSValue.Base).getNonReferenceType(),
|
||||||
|
LHSDesignator, RHSDesignator, WasArrayIndex);
|
||||||
// At the point where the designators diverge, the comparison has a
|
// At the point where the designators diverge, the comparison has a
|
||||||
// specified value if:
|
// specified value if:
|
||||||
// - we are comparing array indices
|
// - we are comparing array indices
|
||||||
@ -14609,7 +14612,7 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
|
|||||||
// compare pointers within the object in question; otherwise, the result
|
// compare pointers within the object in question; otherwise, the result
|
||||||
// depends on where the object is located in memory.
|
// depends on where the object is located in memory.
|
||||||
if (!LHSValue.Base.isNull() && IsRelational) {
|
if (!LHSValue.Base.isNull() && IsRelational) {
|
||||||
QualType BaseTy = getType(LHSValue.Base);
|
QualType BaseTy = getType(LHSValue.Base).getNonReferenceType();
|
||||||
if (BaseTy->isIncompleteType())
|
if (BaseTy->isIncompleteType())
|
||||||
return Error(E);
|
return Error(E);
|
||||||
CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy);
|
CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy);
|
||||||
|
@ -1331,7 +1331,7 @@ void ThreadSafetyAnalyzer::addLock(FactSet &FSet,
|
|||||||
FSet.removeLock(FactMan, NegC);
|
FSet.removeLock(FactMan, NegC);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (inCurrentScope(*Entry) && !Entry->asserted())
|
if (inCurrentScope(*Entry) && !Entry->asserted() && !Entry->reentrant())
|
||||||
Handler.handleNegativeNotHeld(Entry->getKind(), Entry->toString(),
|
Handler.handleNegativeNotHeld(Entry->getKind(), Entry->toString(),
|
||||||
NegC.toString(), Entry->loc());
|
NegC.toString(), Entry->loc());
|
||||||
}
|
}
|
||||||
|
@ -769,6 +769,9 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
|
|||||||
case llvm::Triple::FreeBSD:
|
case llvm::Triple::FreeBSD:
|
||||||
return std::make_unique<FreeBSDTargetInfo<LoongArch64TargetInfo>>(Triple,
|
return std::make_unique<FreeBSDTargetInfo<LoongArch64TargetInfo>>(Triple,
|
||||||
Opts);
|
Opts);
|
||||||
|
case llvm::Triple::OpenBSD:
|
||||||
|
return std::make_unique<OpenBSDTargetInfo<LoongArch64TargetInfo>>(Triple,
|
||||||
|
Opts);
|
||||||
default:
|
default:
|
||||||
return std::make_unique<LoongArch64TargetInfo>(Triple, Opts);
|
return std::make_unique<LoongArch64TargetInfo>(Triple, Opts);
|
||||||
}
|
}
|
||||||
|
@ -461,6 +461,8 @@ LoongArchTargetInfo::parseTargetAttr(StringRef Features) const {
|
|||||||
|
|
||||||
case AttrFeatureKind::Feature:
|
case AttrFeatureKind::Feature:
|
||||||
Ret.Features.push_back("+" + Value.str());
|
Ret.Features.push_back("+" + Value.str());
|
||||||
|
if (Value == "lasx")
|
||||||
|
Ret.Features.push_back("+lsx");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ public:
|
|||||||
LongWidth = LongAlign = 32;
|
LongWidth = LongAlign = 32;
|
||||||
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
|
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
|
||||||
PointerWidth = PointerAlign = 32;
|
PointerWidth = PointerAlign = 32;
|
||||||
PtrDiffType = SignedInt;
|
PtrDiffType = IntPtrType = SignedInt;
|
||||||
SizeType = UnsignedInt;
|
SizeType = UnsignedInt;
|
||||||
SuitableAlign = 64;
|
SuitableAlign = 64;
|
||||||
}
|
}
|
||||||
@ -155,7 +155,7 @@ public:
|
|||||||
IntMaxType = Int64Type;
|
IntMaxType = Int64Type;
|
||||||
LongWidth = LongAlign = 64;
|
LongWidth = LongAlign = 64;
|
||||||
PointerWidth = PointerAlign = 64;
|
PointerWidth = PointerAlign = 64;
|
||||||
PtrDiffType = SignedLong;
|
PtrDiffType = IntPtrType = SignedLong;
|
||||||
SizeType = UnsignedLong;
|
SizeType = UnsignedLong;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +165,7 @@ public:
|
|||||||
IntMaxType = Int64Type;
|
IntMaxType = Int64Type;
|
||||||
LongWidth = LongAlign = 32;
|
LongWidth = LongAlign = 32;
|
||||||
PointerWidth = PointerAlign = 32;
|
PointerWidth = PointerAlign = 32;
|
||||||
PtrDiffType = SignedInt;
|
PtrDiffType = IntPtrType = SignedInt;
|
||||||
SizeType = UnsignedInt;
|
SizeType = UnsignedInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -496,6 +496,7 @@ public:
|
|||||||
case llvm::Triple::sparcv9:
|
case llvm::Triple::sparcv9:
|
||||||
this->MCountName = "_mcount";
|
this->MCountName = "_mcount";
|
||||||
break;
|
break;
|
||||||
|
case llvm::Triple::loongarch64:
|
||||||
case llvm::Triple::riscv64:
|
case llvm::Triple::riscv64:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -176,6 +176,11 @@ public:
|
|||||||
static Address invalid() { return Address(nullptr); }
|
static Address invalid() { return Address(nullptr); }
|
||||||
bool isValid() const { return Pointer.getPointer() != nullptr; }
|
bool isValid() const { return Pointer.getPointer() != nullptr; }
|
||||||
|
|
||||||
|
llvm::Value *getPointerIfNotSigned() const {
|
||||||
|
assert(isValid() && "pointer isn't valid");
|
||||||
|
return !isSigned() ? Pointer.getPointer() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/// This function is used in situations where the caller is doing some sort of
|
/// This function is used in situations where the caller is doing some sort of
|
||||||
/// opaque "laundering" of the pointer.
|
/// opaque "laundering" of the pointer.
|
||||||
void replaceBasePointer(llvm::Value *P) {
|
void replaceBasePointer(llvm::Value *P) {
|
||||||
|
@ -188,13 +188,14 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
|
|||||||
// Optional copy/dispose helpers.
|
// Optional copy/dispose helpers.
|
||||||
bool hasInternalHelper = false;
|
bool hasInternalHelper = false;
|
||||||
if (blockInfo.NeedsCopyDispose) {
|
if (blockInfo.NeedsCopyDispose) {
|
||||||
|
auto &Schema = CGM.getCodeGenOpts().PointerAuth.BlockHelperFunctionPointers;
|
||||||
// copy_func_helper_decl
|
// copy_func_helper_decl
|
||||||
llvm::Constant *copyHelper = buildCopyHelper(CGM, blockInfo);
|
llvm::Constant *copyHelper = buildCopyHelper(CGM, blockInfo);
|
||||||
elements.add(copyHelper);
|
elements.addSignedPointer(copyHelper, Schema, GlobalDecl(), QualType());
|
||||||
|
|
||||||
// destroy_func_decl
|
// destroy_func_decl
|
||||||
llvm::Constant *disposeHelper = buildDisposeHelper(CGM, blockInfo);
|
llvm::Constant *disposeHelper = buildDisposeHelper(CGM, blockInfo);
|
||||||
elements.add(disposeHelper);
|
elements.addSignedPointer(disposeHelper, Schema, GlobalDecl(), QualType());
|
||||||
|
|
||||||
if (cast<llvm::Function>(copyHelper->stripPointerCasts())
|
if (cast<llvm::Function>(copyHelper->stripPointerCasts())
|
||||||
->hasInternalLinkage() ||
|
->hasInternalLinkage() ||
|
||||||
@ -567,9 +568,8 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
|
|||||||
llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
|
llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
|
||||||
info.CanBeGlobal = true;
|
info.CanBeGlobal = true;
|
||||||
return;
|
return;
|
||||||
}
|
} else if (C.getLangOpts().ObjC &&
|
||||||
else if (C.getLangOpts().ObjC &&
|
CGM.getLangOpts().getGC() == LangOptions::NonGC)
|
||||||
CGM.getLangOpts().getGC() == LangOptions::NonGC)
|
|
||||||
info.HasCapturedVariableLayout = true;
|
info.HasCapturedVariableLayout = true;
|
||||||
|
|
||||||
if (block->doesNotEscape())
|
if (block->doesNotEscape())
|
||||||
@ -783,7 +783,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
|
|||||||
|
|
||||||
llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
|
llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
|
||||||
bool IsOpenCL = CGM.getContext().getLangOpts().OpenCL;
|
bool IsOpenCL = CGM.getContext().getLangOpts().OpenCL;
|
||||||
auto GenVoidPtrTy =
|
llvm::PointerType *GenVoidPtrTy =
|
||||||
IsOpenCL ? CGM.getOpenCLRuntime().getGenericVoidPointerType() : VoidPtrTy;
|
IsOpenCL ? CGM.getOpenCLRuntime().getGenericVoidPointerType() : VoidPtrTy;
|
||||||
LangAS GenVoidPtrAddr = IsOpenCL ? LangAS::opencl_generic : LangAS::Default;
|
LangAS GenVoidPtrAddr = IsOpenCL ? LangAS::opencl_generic : LangAS::Default;
|
||||||
auto GenVoidPtrSize = CharUnits::fromQuantity(
|
auto GenVoidPtrSize = CharUnits::fromQuantity(
|
||||||
@ -817,9 +817,6 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
|
|||||||
: CGM.getNSConcreteStackBlock();
|
: CGM.getNSConcreteStackBlock();
|
||||||
isa = blockISA;
|
isa = blockISA;
|
||||||
|
|
||||||
// Build the block descriptor.
|
|
||||||
descriptor = buildBlockDescriptor(CGM, blockInfo);
|
|
||||||
|
|
||||||
// Compute the initial on-stack block flags.
|
// Compute the initial on-stack block flags.
|
||||||
if (!CGM.getCodeGenOpts().DisableBlockSignatureString)
|
if (!CGM.getCodeGenOpts().DisableBlockSignatureString)
|
||||||
flags = BLOCK_HAS_SIGNATURE;
|
flags = BLOCK_HAS_SIGNATURE;
|
||||||
@ -833,6 +830,9 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
|
|||||||
flags |= BLOCK_USE_STRET;
|
flags |= BLOCK_USE_STRET;
|
||||||
if (blockInfo.NoEscape)
|
if (blockInfo.NoEscape)
|
||||||
flags |= BLOCK_IS_NOESCAPE | BLOCK_IS_GLOBAL;
|
flags |= BLOCK_IS_NOESCAPE | BLOCK_IS_GLOBAL;
|
||||||
|
|
||||||
|
// Build the block descriptor.
|
||||||
|
descriptor = buildBlockDescriptor(CGM, blockInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto projectField = [&](unsigned index, const Twine &name) -> Address {
|
auto projectField = [&](unsigned index, const Twine &name) -> Address {
|
||||||
@ -883,11 +883,25 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
|
|||||||
llvm::ConstantInt::get(IntTy, blockInfo.BlockAlign.getQuantity()),
|
llvm::ConstantInt::get(IntTy, blockInfo.BlockAlign.getQuantity()),
|
||||||
getIntSize(), "block.align");
|
getIntSize(), "block.align");
|
||||||
}
|
}
|
||||||
addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
|
|
||||||
if (!IsOpenCL)
|
if (!IsOpenCL) {
|
||||||
addHeaderField(descriptor, getPointerSize(), "block.descriptor");
|
llvm::Value *blockFnPtr =
|
||||||
else if (auto *Helper =
|
llvm::ConstantExpr::getBitCast(InvokeFn, VoidPtrTy);
|
||||||
CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
|
QualType type = blockInfo.getBlockExpr()
|
||||||
|
->getType()
|
||||||
|
->castAs<BlockPointerType>()
|
||||||
|
->getPointeeType();
|
||||||
|
addSignedHeaderField(
|
||||||
|
blockFnPtr,
|
||||||
|
CGM.getCodeGenOpts().PointerAuth.BlockInvocationFunctionPointers,
|
||||||
|
GlobalDecl(), type, getPointerSize(), "block.invoke");
|
||||||
|
|
||||||
|
addSignedHeaderField(
|
||||||
|
descriptor, CGM.getCodeGenOpts().PointerAuth.BlockDescriptorPointers,
|
||||||
|
GlobalDecl(), type, getPointerSize(), "block.descriptor");
|
||||||
|
} else if (auto *Helper =
|
||||||
|
CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
|
||||||
|
addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
|
||||||
for (auto I : Helper->getCustomFieldValues(*this, blockInfo)) {
|
for (auto I : Helper->getCustomFieldValues(*this, blockInfo)) {
|
||||||
addHeaderField(
|
addHeaderField(
|
||||||
I.first,
|
I.first,
|
||||||
@ -895,7 +909,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
|
|||||||
CGM.getDataLayout().getTypeAllocSize(I.first->getType())),
|
CGM.getDataLayout().getTypeAllocSize(I.first->getType())),
|
||||||
I.second);
|
I.second);
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
|
addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, capture all the values into the block.
|
// Finally, capture all the values into the block.
|
||||||
@ -1166,6 +1181,8 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
|
|||||||
ASTContext &Ctx = getContext();
|
ASTContext &Ctx = getContext();
|
||||||
CallArgList Args;
|
CallArgList Args;
|
||||||
|
|
||||||
|
llvm::Value *FuncPtr = nullptr;
|
||||||
|
|
||||||
if (getLangOpts().OpenCL) {
|
if (getLangOpts().OpenCL) {
|
||||||
// For OpenCL, BlockPtr is already casted to generic block literal.
|
// For OpenCL, BlockPtr is already casted to generic block literal.
|
||||||
|
|
||||||
@ -1185,7 +1202,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
|
|||||||
if (!isa<ParmVarDecl>(E->getCalleeDecl()))
|
if (!isa<ParmVarDecl>(E->getCalleeDecl()))
|
||||||
Func = CGM.getOpenCLRuntime().getInvokeFunction(E->getCallee());
|
Func = CGM.getOpenCLRuntime().getInvokeFunction(E->getCallee());
|
||||||
else {
|
else {
|
||||||
llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 2);
|
FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 2);
|
||||||
Func = Builder.CreateAlignedLoad(GenericVoidPtrTy, FuncPtr,
|
Func = Builder.CreateAlignedLoad(GenericVoidPtrTy, FuncPtr,
|
||||||
getPointerAlign());
|
getPointerAlign());
|
||||||
}
|
}
|
||||||
@ -1194,7 +1211,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
|
|||||||
BlockPtr =
|
BlockPtr =
|
||||||
Builder.CreatePointerCast(BlockPtr, UnqualPtrTy, "block.literal");
|
Builder.CreatePointerCast(BlockPtr, UnqualPtrTy, "block.literal");
|
||||||
// Get pointer to the block invoke function
|
// Get pointer to the block invoke function
|
||||||
llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 3);
|
FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 3);
|
||||||
|
|
||||||
// First argument is a block literal casted to a void pointer
|
// First argument is a block literal casted to a void pointer
|
||||||
BlockPtr = Builder.CreatePointerCast(BlockPtr, VoidPtrTy);
|
BlockPtr = Builder.CreatePointerCast(BlockPtr, VoidPtrTy);
|
||||||
@ -1211,7 +1228,15 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
|
|||||||
CGM.getTypes().arrangeBlockFunctionCall(Args, FuncTy);
|
CGM.getTypes().arrangeBlockFunctionCall(Args, FuncTy);
|
||||||
|
|
||||||
// Prepare the callee.
|
// Prepare the callee.
|
||||||
CGCallee Callee(CGCalleeInfo(), Func);
|
CGPointerAuthInfo PointerAuth;
|
||||||
|
if (auto &AuthSchema =
|
||||||
|
CGM.getCodeGenOpts().PointerAuth.BlockInvocationFunctionPointers) {
|
||||||
|
assert(FuncPtr != nullptr && "Missing function pointer for AuthInfo");
|
||||||
|
PointerAuth =
|
||||||
|
EmitPointerAuthInfo(AuthSchema, FuncPtr, GlobalDecl(), FnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
CGCallee Callee(CGCalleeInfo(), Func, PointerAuth);
|
||||||
|
|
||||||
// And call the block.
|
// And call the block.
|
||||||
return EmitCall(FnInfo, Callee, ReturnValue, Args, CallOrInvoke);
|
return EmitCall(FnInfo, Callee, ReturnValue, Args, CallOrInvoke);
|
||||||
@ -1295,14 +1320,15 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
|
|||||||
|
|
||||||
bool IsOpenCL = CGM.getLangOpts().OpenCL;
|
bool IsOpenCL = CGM.getLangOpts().OpenCL;
|
||||||
bool IsWindows = CGM.getTarget().getTriple().isOSWindows();
|
bool IsWindows = CGM.getTarget().getTriple().isOSWindows();
|
||||||
|
auto &CGOPointerAuth = CGM.getCodeGenOpts().PointerAuth;
|
||||||
if (!IsOpenCL) {
|
if (!IsOpenCL) {
|
||||||
// isa
|
// isa
|
||||||
if (IsWindows)
|
if (IsWindows)
|
||||||
fields.addNullPointer(CGM.Int8PtrPtrTy);
|
fields.addNullPointer(CGM.Int8PtrPtrTy);
|
||||||
else
|
else
|
||||||
fields.addSignedPointer(CGM.getNSConcreteGlobalBlock(),
|
fields.addSignedPointer(CGM.getNSConcreteGlobalBlock(),
|
||||||
CGM.getCodeGenOpts().PointerAuth.ObjCIsaPointers,
|
CGOPointerAuth.ObjCIsaPointers, GlobalDecl(),
|
||||||
GlobalDecl(), QualType());
|
QualType());
|
||||||
|
|
||||||
// __flags
|
// __flags
|
||||||
BlockFlags flags = BLOCK_IS_GLOBAL;
|
BlockFlags flags = BLOCK_IS_GLOBAL;
|
||||||
@ -1321,11 +1347,20 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Function
|
// Function
|
||||||
fields.add(blockFn);
|
if (auto &Schema = CGOPointerAuth.BlockInvocationFunctionPointers) {
|
||||||
|
QualType FnType = blockInfo.getBlockExpr()
|
||||||
|
->getType()
|
||||||
|
->castAs<BlockPointerType>()
|
||||||
|
->getPointeeType();
|
||||||
|
fields.addSignedPointer(blockFn, Schema, GlobalDecl(), FnType);
|
||||||
|
} else
|
||||||
|
fields.add(blockFn);
|
||||||
|
|
||||||
if (!IsOpenCL) {
|
if (!IsOpenCL) {
|
||||||
// Descriptor
|
// Descriptor
|
||||||
fields.add(buildBlockDescriptor(CGM, blockInfo));
|
llvm::Constant *Descriptor = buildBlockDescriptor(CGM, blockInfo);
|
||||||
|
fields.addSignedPointer(Descriptor, CGOPointerAuth.BlockDescriptorPointers,
|
||||||
|
GlobalDecl(), QualType());
|
||||||
} else if (auto *Helper =
|
} else if (auto *Helper =
|
||||||
CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
|
CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
|
||||||
for (auto *I : Helper->getCustomFieldValues(CGM, blockInfo)) {
|
for (auto *I : Helper->getCustomFieldValues(CGM, blockInfo)) {
|
||||||
@ -1995,8 +2030,8 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
|
|||||||
// it. It's not quite worth the annoyance to avoid creating it in the
|
// it. It's not quite worth the annoyance to avoid creating it in the
|
||||||
// first place.
|
// first place.
|
||||||
if (!needsEHCleanup(captureType.isDestructedType()))
|
if (!needsEHCleanup(captureType.isDestructedType()))
|
||||||
if (auto *I =
|
if (auto *I = cast_or_null<llvm::Instruction>(
|
||||||
cast_or_null<llvm::Instruction>(dstField.getBasePointer()))
|
dstField.getPointerIfNotSigned()))
|
||||||
I->eraseFromParent();
|
I->eraseFromParent();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2730,8 +2765,16 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
|
|||||||
unsigned nextHeaderIndex = 0;
|
unsigned nextHeaderIndex = 0;
|
||||||
CharUnits nextHeaderOffset;
|
CharUnits nextHeaderOffset;
|
||||||
auto storeHeaderField = [&](llvm::Value *value, CharUnits fieldSize,
|
auto storeHeaderField = [&](llvm::Value *value, CharUnits fieldSize,
|
||||||
const Twine &name) {
|
const Twine &name, bool isFunction = false) {
|
||||||
auto fieldAddr = Builder.CreateStructGEP(addr, nextHeaderIndex, name);
|
auto fieldAddr = Builder.CreateStructGEP(addr, nextHeaderIndex, name);
|
||||||
|
if (isFunction) {
|
||||||
|
if (auto &Schema = CGM.getCodeGenOpts()
|
||||||
|
.PointerAuth.BlockByrefHelperFunctionPointers) {
|
||||||
|
auto PointerAuth = EmitPointerAuthInfo(
|
||||||
|
Schema, fieldAddr.emitRawPointer(*this), GlobalDecl(), QualType());
|
||||||
|
value = EmitPointerAuthSign(PointerAuth, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
Builder.CreateStore(value, fieldAddr);
|
Builder.CreateStore(value, fieldAddr);
|
||||||
|
|
||||||
nextHeaderIndex++;
|
nextHeaderIndex++;
|
||||||
@ -2814,10 +2857,10 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
|
|||||||
storeHeaderField(V, getIntSize(), "byref.size");
|
storeHeaderField(V, getIntSize(), "byref.size");
|
||||||
|
|
||||||
if (helpers) {
|
if (helpers) {
|
||||||
storeHeaderField(helpers->CopyHelper, getPointerSize(),
|
storeHeaderField(helpers->CopyHelper, getPointerSize(), "byref.copyHelper",
|
||||||
"byref.copyHelper");
|
/*isFunction=*/true);
|
||||||
storeHeaderField(helpers->DisposeHelper, getPointerSize(),
|
storeHeaderField(helpers->DisposeHelper, getPointerSize(),
|
||||||
"byref.disposeHelper");
|
"byref.disposeHelper", /*isFunction=*/true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ByRefHasLifetime && HasByrefExtendedLayout) {
|
if (ByRefHasLifetime && HasByrefExtendedLayout) {
|
||||||
|
@ -707,11 +707,15 @@ struct GetReturnObjectManager {
|
|||||||
Builder.CreateStore(Builder.getFalse(), GroActiveFlag);
|
Builder.CreateStore(Builder.getFalse(), GroActiveFlag);
|
||||||
|
|
||||||
GroEmission = CGF.EmitAutoVarAlloca(*GroVarDecl);
|
GroEmission = CGF.EmitAutoVarAlloca(*GroVarDecl);
|
||||||
auto *GroAlloca = dyn_cast_or_null<llvm::AllocaInst>(
|
|
||||||
GroEmission.getOriginalAllocatedAddress().getPointer());
|
if (!GroVarDecl->isNRVOVariable()) {
|
||||||
assert(GroAlloca && "expected alloca to be emitted");
|
// NRVO variables don't have allocas and won't have the same issue.
|
||||||
GroAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame,
|
auto *GroAlloca = dyn_cast_or_null<llvm::AllocaInst>(
|
||||||
llvm::MDNode::get(CGF.CGM.getLLVMContext(), {}));
|
GroEmission.getOriginalAllocatedAddress().getPointer());
|
||||||
|
assert(GroAlloca && "expected alloca to be emitted");
|
||||||
|
GroAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame,
|
||||||
|
llvm::MDNode::get(CGF.CGM.getLLVMContext(), {}));
|
||||||
|
}
|
||||||
|
|
||||||
// Remember the top of EHStack before emitting the cleanup.
|
// Remember the top of EHStack before emitting the cleanup.
|
||||||
auto old_top = CGF.EHStack.stable_begin();
|
auto old_top = CGF.EHStack.stable_begin();
|
||||||
|
@ -170,6 +170,10 @@ void CGDebugInfo::addInstToSpecificSourceAtom(llvm::Instruction *KeyInstruction,
|
|||||||
if (!Group || !CGM.getCodeGenOpts().DebugKeyInstructions)
|
if (!Group || !CGM.getCodeGenOpts().DebugKeyInstructions)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
llvm::DISubprogram *SP = KeyInstruction->getFunction()->getSubprogram();
|
||||||
|
if (!SP || !SP->getKeyInstructionsEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
addInstSourceAtomMetadata(KeyInstruction, Group, /*Rank=*/1);
|
addInstSourceAtomMetadata(KeyInstruction, Group, /*Rank=*/1);
|
||||||
|
|
||||||
llvm::Instruction *BackupI =
|
llvm::Instruction *BackupI =
|
||||||
@ -2641,7 +2645,8 @@ StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
|
|||||||
// existing information in the DWARF. The type is assumed to be 'void *'.
|
// existing information in the DWARF. The type is assumed to be 'void *'.
|
||||||
void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable,
|
void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable,
|
||||||
const CXXRecordDecl *RD) {
|
const CXXRecordDecl *RD) {
|
||||||
if (!CGM.getTarget().getCXXABI().isItaniumFamily())
|
if (!CGM.getTarget().getCXXABI().isItaniumFamily() ||
|
||||||
|
CGM.getTarget().getTriple().isOSBinFormatCOFF())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ASTContext &Context = CGM.getContext();
|
ASTContext &Context = CGM.getContext();
|
||||||
|
@ -2313,7 +2313,8 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr,
|
|||||||
bool IsExact = !IsDynamicCastToVoid &&
|
bool IsExact = !IsDynamicCastToVoid &&
|
||||||
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
|
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
|
||||||
DestRecordTy->getAsCXXRecordDecl()->isEffectivelyFinal() &&
|
DestRecordTy->getAsCXXRecordDecl()->isEffectivelyFinal() &&
|
||||||
CGM.getCXXABI().shouldEmitExactDynamicCast(DestRecordTy);
|
CGM.getCXXABI().shouldEmitExactDynamicCast(DestRecordTy) &&
|
||||||
|
!getLangOpts().PointerAuthCalls;
|
||||||
|
|
||||||
// C++ [expr.dynamic.cast]p4:
|
// C++ [expr.dynamic.cast]p4:
|
||||||
// If the value of v is a null pointer value in the pointer case, the result
|
// If the value of v is a null pointer value in the pointer case, the result
|
||||||
|
@ -846,11 +846,13 @@ void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
|
|||||||
if (HaveInsertPoint())
|
if (HaveInsertPoint())
|
||||||
EmitStopPoint(&S);
|
EmitStopPoint(&S);
|
||||||
|
|
||||||
|
ApplyAtomGroup Grp(getDebugInfo());
|
||||||
EmitBranchThroughCleanup(getJumpDestForLabel(S.getLabel()));
|
EmitBranchThroughCleanup(getJumpDestForLabel(S.getLabel()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
|
void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
|
||||||
|
ApplyAtomGroup Grp(getDebugInfo());
|
||||||
if (const LabelDecl *Target = S.getConstantTarget()) {
|
if (const LabelDecl *Target = S.getConstantTarget()) {
|
||||||
EmitBranchThroughCleanup(getJumpDestForLabel(Target));
|
EmitBranchThroughCleanup(getJumpDestForLabel(Target));
|
||||||
return;
|
return;
|
||||||
@ -869,6 +871,8 @@ void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
|
|||||||
cast<llvm::PHINode>(IndGotoBB->begin())->addIncoming(V, CurBB);
|
cast<llvm::PHINode>(IndGotoBB->begin())->addIncoming(V, CurBB);
|
||||||
|
|
||||||
EmitBranch(IndGotoBB);
|
EmitBranch(IndGotoBB);
|
||||||
|
if (CurBB && CurBB->getTerminator())
|
||||||
|
addInstToCurrentSourceAtom(CurBB->getTerminator(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
|
void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
|
||||||
@ -2672,6 +2676,9 @@ static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect,
|
|||||||
llvm::ConstantAsMetadata::get(Loc)));
|
llvm::ConstantAsMetadata::get(Loc)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make inline-asm calls Key for the debug info feature Key Instructions.
|
||||||
|
CGF.addInstToNewSourceAtom(&Result, nullptr);
|
||||||
|
|
||||||
if (!NoConvergent && CGF.getLangOpts().assumeFunctionsAreConvergent())
|
if (!NoConvergent && CGF.getLangOpts().assumeFunctionsAreConvergent())
|
||||||
// Conservatively, mark all inline asm blocks in CUDA or OpenCL as
|
// Conservatively, mark all inline asm blocks in CUDA or OpenCL as
|
||||||
// convergent (meaning, they may call an intrinsically convergent op, such
|
// convergent (meaning, they may call an intrinsically convergent op, such
|
||||||
@ -2750,6 +2757,7 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ApplyAtomGroup Grp(CGF.getDebugInfo());
|
||||||
LValue Dest = ResultRegDests[i];
|
LValue Dest = ResultRegDests[i];
|
||||||
// ResultTypeRequiresCast elements correspond to the first
|
// ResultTypeRequiresCast elements correspond to the first
|
||||||
// ResultTypeRequiresCast.size() elements of RegResults.
|
// ResultTypeRequiresCast.size() elements of RegResults.
|
||||||
@ -2757,7 +2765,8 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S,
|
|||||||
unsigned Size = CGF.getContext().getTypeSize(ResultRegQualTys[i]);
|
unsigned Size = CGF.getContext().getTypeSize(ResultRegQualTys[i]);
|
||||||
Address A = Dest.getAddress().withElementType(ResultRegTypes[i]);
|
Address A = Dest.getAddress().withElementType(ResultRegTypes[i]);
|
||||||
if (CGF.getTargetHooks().isScalarizableAsmOperand(CGF, TruncTy)) {
|
if (CGF.getTargetHooks().isScalarizableAsmOperand(CGF, TruncTy)) {
|
||||||
Builder.CreateStore(Tmp, A);
|
llvm::StoreInst *S = Builder.CreateStore(Tmp, A);
|
||||||
|
CGF.addInstToCurrentSourceAtom(S, S->getValueOperand());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -837,17 +837,30 @@ void ToolChain::addFortranRuntimeLibs(const ArgList &Args,
|
|||||||
|
|
||||||
void ToolChain::addFortranRuntimeLibraryPath(const llvm::opt::ArgList &Args,
|
void ToolChain::addFortranRuntimeLibraryPath(const llvm::opt::ArgList &Args,
|
||||||
ArgStringList &CmdArgs) const {
|
ArgStringList &CmdArgs) const {
|
||||||
// Default to the <driver-path>/../lib directory. This works fine on the
|
auto AddLibSearchPathIfExists = [&](const Twine &Path) {
|
||||||
// platforms that we have tested so far. We will probably have to re-fine
|
// Linker may emit warnings about non-existing directories
|
||||||
// this in the future. In particular, on some platforms, we may need to use
|
if (!llvm::sys::fs::is_directory(Path))
|
||||||
// lib64 instead of lib.
|
return;
|
||||||
|
|
||||||
|
if (getTriple().isKnownWindowsMSVCEnvironment())
|
||||||
|
CmdArgs.push_back(Args.MakeArgString("-libpath:" + Path));
|
||||||
|
else
|
||||||
|
CmdArgs.push_back(Args.MakeArgString("-L" + Path));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Search for flang_rt.* at the same location as clang_rt.* with
|
||||||
|
// LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=0. On most platforms, flang_rt is
|
||||||
|
// located at the path returned by getRuntimePath() which is already added to
|
||||||
|
// the library search path. This exception is for Apple-Darwin.
|
||||||
|
AddLibSearchPathIfExists(getCompilerRTPath());
|
||||||
|
|
||||||
|
// Fall back to the non-resource directory <driver-path>/../lib. We will
|
||||||
|
// probably have to refine this in the future. In particular, on some
|
||||||
|
// platforms, we may need to use lib64 instead of lib.
|
||||||
SmallString<256> DefaultLibPath =
|
SmallString<256> DefaultLibPath =
|
||||||
llvm::sys::path::parent_path(getDriver().Dir);
|
llvm::sys::path::parent_path(getDriver().Dir);
|
||||||
llvm::sys::path::append(DefaultLibPath, "lib");
|
llvm::sys::path::append(DefaultLibPath, "lib");
|
||||||
if (getTriple().isKnownWindowsMSVCEnvironment())
|
AddLibSearchPathIfExists(DefaultLibPath);
|
||||||
CmdArgs.push_back(Args.MakeArgString("-libpath:" + DefaultLibPath));
|
|
||||||
else
|
|
||||||
CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToolChain::addFlangRTLibPath(const ArgList &Args,
|
void ToolChain::addFlangRTLibPath(const ArgList &Args,
|
||||||
|
@ -467,3 +467,18 @@ void aarch64::setPAuthABIInTriple(const Driver &D, const ArgList &Args,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Is the triple {aarch64.aarch64_be}-none-elf?
|
||||||
|
bool aarch64::isAArch64BareMetal(const llvm::Triple &Triple) {
|
||||||
|
if (Triple.getArch() != llvm::Triple::aarch64 &&
|
||||||
|
Triple.getArch() != llvm::Triple::aarch64_be)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (Triple.getVendor() != llvm::Triple::UnknownVendor)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (Triple.getOS() != llvm::Triple::UnknownOS)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return Triple.getEnvironmentName() == "elf";
|
||||||
|
}
|
||||||
|
@ -30,6 +30,7 @@ std::string getAArch64TargetCPU(const llvm::opt::ArgList &Args,
|
|||||||
|
|
||||||
void setPAuthABIInTriple(const Driver &D, const llvm::opt::ArgList &Args,
|
void setPAuthABIInTriple(const Driver &D, const llvm::opt::ArgList &Args,
|
||||||
llvm::Triple &triple);
|
llvm::Triple &triple);
|
||||||
|
bool isAArch64BareMetal(const llvm::Triple &Triple);
|
||||||
|
|
||||||
} // end namespace aarch64
|
} // end namespace aarch64
|
||||||
} // end namespace target
|
} // end namespace target
|
||||||
|
@ -23,7 +23,9 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name,
|
|||||||
if (Triple.getArch() == llvm::Triple::sparcv9) {
|
if (Triple.getArch() == llvm::Triple::sparcv9) {
|
||||||
const char *DefV9CPU;
|
const char *DefV9CPU;
|
||||||
|
|
||||||
if (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD())
|
if (Triple.isOSSolaris())
|
||||||
|
DefV9CPU = "-Av9b";
|
||||||
|
else if (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD())
|
||||||
DefV9CPU = "-Av9a";
|
DefV9CPU = "-Av9a";
|
||||||
else
|
else
|
||||||
DefV9CPU = "-Av9";
|
DefV9CPU = "-Av9";
|
||||||
@ -35,6 +37,13 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name,
|
|||||||
.Case("niagara4", "-Av9d")
|
.Case("niagara4", "-Av9d")
|
||||||
.Default(DefV9CPU);
|
.Default(DefV9CPU);
|
||||||
} else {
|
} else {
|
||||||
|
const char *DefV8CPU;
|
||||||
|
|
||||||
|
if (Triple.isOSSolaris())
|
||||||
|
DefV8CPU = "-Av8plus";
|
||||||
|
else
|
||||||
|
DefV8CPU = "-Av8";
|
||||||
|
|
||||||
return llvm::StringSwitch<const char *>(Name)
|
return llvm::StringSwitch<const char *>(Name)
|
||||||
.Case("v8", "-Av8")
|
.Case("v8", "-Av8")
|
||||||
.Case("supersparc", "-Av8")
|
.Case("supersparc", "-Av8")
|
||||||
@ -70,7 +79,7 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name,
|
|||||||
.Case("gr712rc", "-Aleon")
|
.Case("gr712rc", "-Aleon")
|
||||||
.Case("leon4", "-Aleon")
|
.Case("leon4", "-Aleon")
|
||||||
.Case("gr740", "-Aleon")
|
.Case("gr740", "-Aleon")
|
||||||
.Default("-Av8");
|
.Default(DefV8CPU);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +139,8 @@ std::string sparc::getSparcTargetCPU(const Driver &D, const ArgList &Args,
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args,
|
void sparc::getSparcTargetFeatures(const Driver &D, const llvm::Triple &Triple,
|
||||||
|
const ArgList &Args,
|
||||||
std::vector<StringRef> &Features) {
|
std::vector<StringRef> &Features) {
|
||||||
sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args);
|
sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args);
|
||||||
if (FloatABI == sparc::FloatABI::Soft)
|
if (FloatABI == sparc::FloatABI::Soft)
|
||||||
@ -150,11 +160,22 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args,
|
|||||||
Features.push_back("-popc");
|
Features.push_back("-popc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Those OSes default to enabling VIS on 64-bit SPARC.
|
||||||
|
// See also the corresponding code for external assemblers in
|
||||||
|
// sparc::getSparcAsmModeForCPU().
|
||||||
|
bool IsSparcV9ATarget =
|
||||||
|
(Triple.getArch() == llvm::Triple::sparcv9) &&
|
||||||
|
(Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD());
|
||||||
|
bool IsSparcV9BTarget = Triple.isOSSolaris();
|
||||||
|
bool IsSparcV8PlusTarget =
|
||||||
|
Triple.getArch() == llvm::Triple::sparc && Triple.isOSSolaris();
|
||||||
if (Arg *A = Args.getLastArg(options::OPT_mvis, options::OPT_mno_vis)) {
|
if (Arg *A = Args.getLastArg(options::OPT_mvis, options::OPT_mno_vis)) {
|
||||||
if (A->getOption().matches(options::OPT_mvis))
|
if (A->getOption().matches(options::OPT_mvis))
|
||||||
Features.push_back("+vis");
|
Features.push_back("+vis");
|
||||||
else
|
else
|
||||||
Features.push_back("-vis");
|
Features.push_back("-vis");
|
||||||
|
} else if (IsSparcV9ATarget) {
|
||||||
|
Features.push_back("+vis");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Arg *A = Args.getLastArg(options::OPT_mvis2, options::OPT_mno_vis2)) {
|
if (Arg *A = Args.getLastArg(options::OPT_mvis2, options::OPT_mno_vis2)) {
|
||||||
@ -162,6 +183,8 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args,
|
|||||||
Features.push_back("+vis2");
|
Features.push_back("+vis2");
|
||||||
else
|
else
|
||||||
Features.push_back("-vis2");
|
Features.push_back("-vis2");
|
||||||
|
} else if (IsSparcV9BTarget) {
|
||||||
|
Features.push_back("+vis2");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Arg *A = Args.getLastArg(options::OPT_mvis3, options::OPT_mno_vis3)) {
|
if (Arg *A = Args.getLastArg(options::OPT_mvis3, options::OPT_mno_vis3)) {
|
||||||
@ -182,6 +205,8 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args,
|
|||||||
if (Arg *A = Args.getLastArg(options::OPT_mv8plus, options::OPT_mno_v8plus)) {
|
if (Arg *A = Args.getLastArg(options::OPT_mv8plus, options::OPT_mno_v8plus)) {
|
||||||
if (A->getOption().matches(options::OPT_mv8plus))
|
if (A->getOption().matches(options::OPT_mv8plus))
|
||||||
Features.push_back("+v8plus");
|
Features.push_back("+v8plus");
|
||||||
|
} else if (IsSparcV8PlusTarget) {
|
||||||
|
Features.push_back("+v8plus");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Args.hasArg(options::OPT_ffixed_g1))
|
if (Args.hasArg(options::OPT_ffixed_g1))
|
||||||
|
@ -31,7 +31,8 @@ FloatABI getSparcFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
|
|||||||
std::string getSparcTargetCPU(const Driver &D, const llvm::opt::ArgList &Args,
|
std::string getSparcTargetCPU(const Driver &D, const llvm::opt::ArgList &Args,
|
||||||
const llvm::Triple &Triple);
|
const llvm::Triple &Triple);
|
||||||
|
|
||||||
void getSparcTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
|
void getSparcTargetFeatures(const Driver &D, const llvm::Triple &Triple,
|
||||||
|
const llvm::opt::ArgList &Args,
|
||||||
std::vector<llvm::StringRef> &Features);
|
std::vector<llvm::StringRef> &Features);
|
||||||
const char *getSparcAsmModeForCPU(llvm::StringRef Name,
|
const char *getSparcAsmModeForCPU(llvm::StringRef Name,
|
||||||
const llvm::Triple &Triple);
|
const llvm::Triple &Triple);
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "clang/Driver/CommonArgs.h"
|
#include "clang/Driver/CommonArgs.h"
|
||||||
#include "clang/Driver/InputInfo.h"
|
#include "clang/Driver/InputInfo.h"
|
||||||
|
|
||||||
|
#include "Arch/AArch64.h"
|
||||||
#include "Arch/ARM.h"
|
#include "Arch/ARM.h"
|
||||||
#include "Arch/RISCV.h"
|
#include "Arch/RISCV.h"
|
||||||
#include "clang/Driver/Compilation.h"
|
#include "clang/Driver/Compilation.h"
|
||||||
@ -31,21 +32,6 @@ using namespace clang::driver;
|
|||||||
using namespace clang::driver::tools;
|
using namespace clang::driver::tools;
|
||||||
using namespace clang::driver::toolchains;
|
using namespace clang::driver::toolchains;
|
||||||
|
|
||||||
/// Is the triple {aarch64.aarch64_be}-none-elf?
|
|
||||||
static bool isAArch64BareMetal(const llvm::Triple &Triple) {
|
|
||||||
if (Triple.getArch() != llvm::Triple::aarch64 &&
|
|
||||||
Triple.getArch() != llvm::Triple::aarch64_be)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (Triple.getVendor() != llvm::Triple::UnknownVendor)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (Triple.getOS() != llvm::Triple::UnknownOS)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return Triple.getEnvironmentName() == "elf";
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isRISCVBareMetal(const llvm::Triple &Triple) {
|
static bool isRISCVBareMetal(const llvm::Triple &Triple) {
|
||||||
if (!Triple.isRISCV())
|
if (!Triple.isRISCV())
|
||||||
return false;
|
return false;
|
||||||
@ -363,8 +349,9 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool BareMetal::handlesTarget(const llvm::Triple &Triple) {
|
bool BareMetal::handlesTarget(const llvm::Triple &Triple) {
|
||||||
return arm::isARMEABIBareMetal(Triple) || isAArch64BareMetal(Triple) ||
|
return arm::isARMEABIBareMetal(Triple) ||
|
||||||
isRISCVBareMetal(Triple) || isPPCBareMetal(Triple);
|
aarch64::isAArch64BareMetal(Triple) || isRISCVBareMetal(Triple) ||
|
||||||
|
isPPCBareMetal(Triple);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tool *BareMetal::buildLinker() const {
|
Tool *BareMetal::buildLinker() const {
|
||||||
@ -694,9 +681,6 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||||||
NeedCRTs)
|
NeedCRTs)
|
||||||
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath(CRTEnd)));
|
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath(CRTEnd)));
|
||||||
|
|
||||||
if (TC.getTriple().isRISCV())
|
|
||||||
CmdArgs.push_back("-X");
|
|
||||||
|
|
||||||
// The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf
|
// The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf
|
||||||
// and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and
|
// and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and
|
||||||
// arm*-*-*bsd).
|
// arm*-*-*bsd).
|
||||||
|
@ -1752,7 +1752,6 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
|
|||||||
options::OPT_fno_ptrauth_objc_interface_sel);
|
options::OPT_fno_ptrauth_objc_interface_sel);
|
||||||
Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_objc_class_ro,
|
Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_objc_class_ro,
|
||||||
options::OPT_fno_ptrauth_objc_class_ro);
|
options::OPT_fno_ptrauth_objc_class_ro);
|
||||||
|
|
||||||
if (Triple.getEnvironment() == llvm::Triple::PAuthTest)
|
if (Triple.getEnvironment() == llvm::Triple::PAuthTest)
|
||||||
handlePAuthABI(Args, CmdArgs);
|
handlePAuthABI(Args, CmdArgs);
|
||||||
|
|
||||||
@ -2731,16 +2730,6 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
|
|||||||
CmdArgs.push_back(MipsTargetFeature);
|
CmdArgs.push_back(MipsTargetFeature);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Those OSes default to enabling VIS on 64-bit SPARC.
|
|
||||||
// See also the corresponding code for external assemblers in
|
|
||||||
// sparc::getSparcAsmModeForCPU().
|
|
||||||
bool IsSparcV9ATarget =
|
|
||||||
(C.getDefaultToolChain().getArch() == llvm::Triple::sparcv9) &&
|
|
||||||
(Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD());
|
|
||||||
if (IsSparcV9ATarget && SparcTargetFeatures.empty()) {
|
|
||||||
CmdArgs.push_back("-target-feature");
|
|
||||||
CmdArgs.push_back("+vis");
|
|
||||||
}
|
|
||||||
for (const char *Feature : SparcTargetFeatures) {
|
for (const char *Feature : SparcTargetFeatures) {
|
||||||
CmdArgs.push_back("-target-feature");
|
CmdArgs.push_back("-target-feature");
|
||||||
CmdArgs.push_back(Feature);
|
CmdArgs.push_back(Feature);
|
||||||
|
@ -547,15 +547,22 @@ const char *tools::getLDMOption(const llvm::Triple &T, const ArgList &Args) {
|
|||||||
case llvm::Triple::aarch64:
|
case llvm::Triple::aarch64:
|
||||||
if (T.isOSManagarm())
|
if (T.isOSManagarm())
|
||||||
return "aarch64managarm";
|
return "aarch64managarm";
|
||||||
|
else if (aarch64::isAArch64BareMetal(T))
|
||||||
|
return "aarch64elf";
|
||||||
return "aarch64linux";
|
return "aarch64linux";
|
||||||
case llvm::Triple::aarch64_be:
|
case llvm::Triple::aarch64_be:
|
||||||
|
if (aarch64::isAArch64BareMetal(T))
|
||||||
|
return "aarch64elfb";
|
||||||
return "aarch64linuxb";
|
return "aarch64linuxb";
|
||||||
case llvm::Triple::arm:
|
case llvm::Triple::arm:
|
||||||
case llvm::Triple::thumb:
|
case llvm::Triple::thumb:
|
||||||
case llvm::Triple::armeb:
|
case llvm::Triple::armeb:
|
||||||
case llvm::Triple::thumbeb:
|
case llvm::Triple::thumbeb: {
|
||||||
return tools::arm::isARMBigEndian(T, Args) ? "armelfb_linux_eabi"
|
bool IsBigEndian = tools::arm::isARMBigEndian(T, Args);
|
||||||
: "armelf_linux_eabi";
|
if (arm::isARMEABIBareMetal(T))
|
||||||
|
return IsBigEndian ? "armelfb" : "armelf";
|
||||||
|
return IsBigEndian ? "armelfb_linux_eabi" : "armelf_linux_eabi";
|
||||||
|
}
|
||||||
case llvm::Triple::m68k:
|
case llvm::Triple::m68k:
|
||||||
return "m68kelf";
|
return "m68kelf";
|
||||||
case llvm::Triple::ppc:
|
case llvm::Triple::ppc:
|
||||||
@ -856,7 +863,7 @@ void tools::getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
|
|||||||
case llvm::Triple::sparc:
|
case llvm::Triple::sparc:
|
||||||
case llvm::Triple::sparcel:
|
case llvm::Triple::sparcel:
|
||||||
case llvm::Triple::sparcv9:
|
case llvm::Triple::sparcv9:
|
||||||
sparc::getSparcTargetFeatures(D, Args, Features);
|
sparc::getSparcTargetFeatures(D, Triple, Args, Features);
|
||||||
break;
|
break;
|
||||||
case llvm::Triple::r600:
|
case llvm::Triple::r600:
|
||||||
case llvm::Triple::amdgcn:
|
case llvm::Triple::amdgcn:
|
||||||
@ -1320,6 +1327,17 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
|
|||||||
if (Args.hasArg(options::OPT_ftime_report))
|
if (Args.hasArg(options::OPT_ftime_report))
|
||||||
CmdArgs.push_back(
|
CmdArgs.push_back(
|
||||||
Args.MakeArgString(Twine(PluginOptPrefix) + "-time-passes"));
|
Args.MakeArgString(Twine(PluginOptPrefix) + "-time-passes"));
|
||||||
|
|
||||||
|
if (Arg *A = Args.getLastArg(options::OPT_fthinlto_distributor_EQ)) {
|
||||||
|
CmdArgs.push_back(
|
||||||
|
Args.MakeArgString("--thinlto-distributor=" + Twine(A->getValue())));
|
||||||
|
CmdArgs.push_back(
|
||||||
|
Args.MakeArgString("--thinlto-remote-compiler=" +
|
||||||
|
Twine(ToolChain.getDriver().getClangProgramPath())));
|
||||||
|
|
||||||
|
for (auto A : Args.getAllArgValues(options::OPT_Xthinlto_distributor_EQ))
|
||||||
|
CmdArgs.push_back(Args.MakeArgString("--thinlto-distributor-arg=" + A));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC,
|
void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC,
|
||||||
|
@ -3187,28 +3187,46 @@ void MachO::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
|
|||||||
|
|
||||||
ToolChain::addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadKind);
|
ToolChain::addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadKind);
|
||||||
|
|
||||||
// On arm64e, enable pointer authentication (for the return address and
|
// On arm64e, we enable all the features required for the Darwin userspace
|
||||||
// indirect calls), as well as usage of the intrinsics.
|
// ABI
|
||||||
if (getArchName() == "arm64e") {
|
if (getTriple().isArm64e()) {
|
||||||
if (!DriverArgs.hasArg(options::OPT_fptrauth_returns,
|
// Core platform ABI
|
||||||
options::OPT_fno_ptrauth_returns))
|
|
||||||
CC1Args.push_back("-fptrauth-returns");
|
|
||||||
|
|
||||||
if (!DriverArgs.hasArg(options::OPT_fptrauth_intrinsics,
|
|
||||||
options::OPT_fno_ptrauth_intrinsics))
|
|
||||||
CC1Args.push_back("-fptrauth-intrinsics");
|
|
||||||
|
|
||||||
if (!DriverArgs.hasArg(options::OPT_fptrauth_calls,
|
if (!DriverArgs.hasArg(options::OPT_fptrauth_calls,
|
||||||
options::OPT_fno_ptrauth_calls))
|
options::OPT_fno_ptrauth_calls))
|
||||||
CC1Args.push_back("-fptrauth-calls");
|
CC1Args.push_back("-fptrauth-calls");
|
||||||
|
if (!DriverArgs.hasArg(options::OPT_fptrauth_returns,
|
||||||
|
options::OPT_fno_ptrauth_returns))
|
||||||
|
CC1Args.push_back("-fptrauth-returns");
|
||||||
|
if (!DriverArgs.hasArg(options::OPT_fptrauth_intrinsics,
|
||||||
|
options::OPT_fno_ptrauth_intrinsics))
|
||||||
|
CC1Args.push_back("-fptrauth-intrinsics");
|
||||||
if (!DriverArgs.hasArg(options::OPT_fptrauth_indirect_gotos,
|
if (!DriverArgs.hasArg(options::OPT_fptrauth_indirect_gotos,
|
||||||
options::OPT_fno_ptrauth_indirect_gotos))
|
options::OPT_fno_ptrauth_indirect_gotos))
|
||||||
CC1Args.push_back("-fptrauth-indirect-gotos");
|
CC1Args.push_back("-fptrauth-indirect-gotos");
|
||||||
|
|
||||||
if (!DriverArgs.hasArg(options::OPT_fptrauth_auth_traps,
|
if (!DriverArgs.hasArg(options::OPT_fptrauth_auth_traps,
|
||||||
options::OPT_fno_ptrauth_auth_traps))
|
options::OPT_fno_ptrauth_auth_traps))
|
||||||
CC1Args.push_back("-fptrauth-auth-traps");
|
CC1Args.push_back("-fptrauth-auth-traps");
|
||||||
|
|
||||||
|
// C++ v-table ABI
|
||||||
|
if (!DriverArgs.hasArg(
|
||||||
|
options::OPT_fptrauth_vtable_pointer_address_discrimination,
|
||||||
|
options::OPT_fno_ptrauth_vtable_pointer_address_discrimination))
|
||||||
|
CC1Args.push_back("-fptrauth-vtable-pointer-address-discrimination");
|
||||||
|
if (!DriverArgs.hasArg(
|
||||||
|
options::OPT_fptrauth_vtable_pointer_type_discrimination,
|
||||||
|
options::OPT_fno_ptrauth_vtable_pointer_type_discrimination))
|
||||||
|
CC1Args.push_back("-fptrauth-vtable-pointer-type-discrimination");
|
||||||
|
|
||||||
|
// Objective-C ABI
|
||||||
|
if (!DriverArgs.hasArg(options::OPT_fptrauth_objc_isa,
|
||||||
|
options::OPT_fno_ptrauth_objc_isa))
|
||||||
|
CC1Args.push_back("-fptrauth-objc-isa");
|
||||||
|
if (!DriverArgs.hasArg(options::OPT_fptrauth_objc_class_ro,
|
||||||
|
options::OPT_fno_ptrauth_objc_class_ro))
|
||||||
|
CC1Args.push_back("-fptrauth-objc-class-ro");
|
||||||
|
if (!DriverArgs.hasArg(options::OPT_fptrauth_objc_interface_sel,
|
||||||
|
options::OPT_fno_ptrauth_objc_interface_sel))
|
||||||
|
CC1Args.push_back("-fptrauth-objc-interface-sel");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,6 +447,7 @@ void Flang::addTargetOptions(const ArgList &Args,
|
|||||||
// Add the target features.
|
// Add the target features.
|
||||||
switch (TC.getArch()) {
|
switch (TC.getArch()) {
|
||||||
default:
|
default:
|
||||||
|
getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);
|
||||||
break;
|
break;
|
||||||
case llvm::Triple::aarch64:
|
case llvm::Triple::aarch64:
|
||||||
getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);
|
getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);
|
||||||
|
@ -85,11 +85,18 @@ void tools::MinGW::Linker::AddLibGCC(const ArgList &Args,
|
|||||||
|
|
||||||
CmdArgs.push_back("-lmoldname");
|
CmdArgs.push_back("-lmoldname");
|
||||||
CmdArgs.push_back("-lmingwex");
|
CmdArgs.push_back("-lmingwex");
|
||||||
for (auto Lib : Args.getAllArgValues(options::OPT_l))
|
for (auto Lib : Args.getAllArgValues(options::OPT_l)) {
|
||||||
if (StringRef(Lib).starts_with("msvcr") ||
|
if (StringRef(Lib).starts_with("msvcr") ||
|
||||||
StringRef(Lib).starts_with("ucrt") ||
|
StringRef(Lib).starts_with("ucrt") ||
|
||||||
StringRef(Lib).starts_with("crtdll"))
|
StringRef(Lib).starts_with("crtdll")) {
|
||||||
|
std::string CRTLib = (llvm::Twine("-l") + Lib).str();
|
||||||
|
// Respect the user's chosen crt variant, but still provide it
|
||||||
|
// again as the last linker argument, because some of the libraries
|
||||||
|
// we added above may depend on it.
|
||||||
|
CmdArgs.push_back(Args.MakeArgStringRef(CRTLib));
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
CmdArgs.push_back("-lmsvcrt");
|
CmdArgs.push_back("-lmsvcrt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||||||
if (Nopie || Profiling)
|
if (Nopie || Profiling)
|
||||||
CmdArgs.push_back("-nopie");
|
CmdArgs.push_back("-nopie");
|
||||||
|
|
||||||
if (Triple.isRISCV64()) {
|
if (Triple.isLoongArch64() || Triple.isRISCV64()) {
|
||||||
CmdArgs.push_back("-X");
|
CmdArgs.push_back("-X");
|
||||||
if (Args.hasArg(options::OPT_mno_relax))
|
if (Args.hasArg(options::OPT_mno_relax))
|
||||||
CmdArgs.push_back("--no-relax");
|
CmdArgs.push_back("--no-relax");
|
||||||
|
@ -628,9 +628,16 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
|
|||||||
// name.
|
// name.
|
||||||
!Style.isJavaScript() && Previous.isNot(tok::kw_template) &&
|
!Style.isJavaScript() && Previous.isNot(tok::kw_template) &&
|
||||||
CurrentState.BreakBeforeParameter) {
|
CurrentState.BreakBeforeParameter) {
|
||||||
for (const auto *Tok = &Previous; Tok; Tok = Tok->Previous)
|
for (const auto *Tok = &Previous; Tok; Tok = Tok->Previous) {
|
||||||
if (Tok->FirstAfterPPLine || Tok->is(TT_LineComment))
|
if (Tok->is(TT_LineComment))
|
||||||
return false;
|
return false;
|
||||||
|
if (Tok->is(TT_TemplateCloser)) {
|
||||||
|
Tok = Tok->MatchingParen;
|
||||||
|
assert(Tok);
|
||||||
|
}
|
||||||
|
if (Tok->FirstAfterPPLine)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -727,6 +727,7 @@ template <> struct MappingTraits<FormatStyle::SpaceBeforeParensCustom> {
|
|||||||
IO.mapOptional("AfterFunctionDeclarationName",
|
IO.mapOptional("AfterFunctionDeclarationName",
|
||||||
Spacing.AfterFunctionDeclarationName);
|
Spacing.AfterFunctionDeclarationName);
|
||||||
IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros);
|
IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros);
|
||||||
|
IO.mapOptional("AfterNot", Spacing.AfterNot);
|
||||||
IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
|
IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
|
||||||
IO.mapOptional("AfterPlacementOperator", Spacing.AfterPlacementOperator);
|
IO.mapOptional("AfterPlacementOperator", Spacing.AfterPlacementOperator);
|
||||||
IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause);
|
IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause);
|
||||||
@ -1748,7 +1749,6 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
|
|||||||
GoogleStyle.AttributeMacros.push_back("absl_nullable");
|
GoogleStyle.AttributeMacros.push_back("absl_nullable");
|
||||||
GoogleStyle.AttributeMacros.push_back("absl_nullability_unknown");
|
GoogleStyle.AttributeMacros.push_back("absl_nullability_unknown");
|
||||||
GoogleStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
|
GoogleStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
|
||||||
GoogleStyle.DerivePointerAlignment = true;
|
|
||||||
GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
|
GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
|
||||||
GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false},
|
GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false},
|
||||||
{"^<.*\\.h>", 1, 0, false},
|
{"^<.*\\.h>", 1, 0, false},
|
||||||
@ -1857,6 +1857,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
|
|||||||
} else if (Language == FormatStyle::LK_ObjC) {
|
} else if (Language == FormatStyle::LK_ObjC) {
|
||||||
GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
|
GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
|
||||||
GoogleStyle.ColumnLimit = 100;
|
GoogleStyle.ColumnLimit = 100;
|
||||||
|
GoogleStyle.DerivePointerAlignment = true;
|
||||||
// "Regroup" doesn't work well for ObjC yet (main header heuristic,
|
// "Regroup" doesn't work well for ObjC yet (main header heuristic,
|
||||||
// relationship between ObjC standard library headers and other heades,
|
// relationship between ObjC standard library headers and other heades,
|
||||||
// #imports, etc.)
|
// #imports, etc.)
|
||||||
|
@ -45,15 +45,18 @@ std::pair<tooling::Replacements, unsigned>
|
|||||||
IntegerLiteralSeparatorFixer::process(const Environment &Env,
|
IntegerLiteralSeparatorFixer::process(const Environment &Env,
|
||||||
const FormatStyle &Style) {
|
const FormatStyle &Style) {
|
||||||
switch (Style.Language) {
|
switch (Style.Language) {
|
||||||
case FormatStyle::LK_Cpp:
|
|
||||||
case FormatStyle::LK_ObjC:
|
|
||||||
Separator = '\'';
|
|
||||||
break;
|
|
||||||
case FormatStyle::LK_CSharp:
|
case FormatStyle::LK_CSharp:
|
||||||
case FormatStyle::LK_Java:
|
case FormatStyle::LK_Java:
|
||||||
case FormatStyle::LK_JavaScript:
|
case FormatStyle::LK_JavaScript:
|
||||||
Separator = '_';
|
Separator = '_';
|
||||||
break;
|
break;
|
||||||
|
case FormatStyle::LK_Cpp:
|
||||||
|
case FormatStyle::LK_ObjC:
|
||||||
|
if (Style.Standard >= FormatStyle::LS_Cpp14) {
|
||||||
|
Separator = '\'';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
[[fallthrough]];
|
||||||
default:
|
default:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -2590,6 +2590,9 @@ private:
|
|||||||
if (!Tok.Previous || Tok.isNot(tok::identifier) || Tok.is(TT_ClassHeadName))
|
if (!Tok.Previous || Tok.isNot(tok::identifier) || Tok.is(TT_ClassHeadName))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (Tok.endsSequence(Keywords.kw_final, TT_ClassHeadName))
|
||||||
|
return false;
|
||||||
|
|
||||||
if ((Style.isJavaScript() || Style.isJava()) && Tok.is(Keywords.kw_extends))
|
if ((Style.isJavaScript() || Style.isJava()) && Tok.is(Keywords.kw_extends))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -2996,14 +2999,18 @@ private:
|
|||||||
const FormatToken *PrevToken = Tok.getPreviousNonComment();
|
const FormatToken *PrevToken = Tok.getPreviousNonComment();
|
||||||
if (!PrevToken)
|
if (!PrevToken)
|
||||||
return TT_UnaryOperator;
|
return TT_UnaryOperator;
|
||||||
if (PrevToken->is(TT_TypeName))
|
if (PrevToken->isTypeName(LangOpts))
|
||||||
return TT_PointerOrReference;
|
return TT_PointerOrReference;
|
||||||
if (PrevToken->isPlacementOperator() && Tok.is(tok::ampamp))
|
if (PrevToken->isPlacementOperator() && Tok.is(tok::ampamp))
|
||||||
return TT_BinaryOperator;
|
return TT_BinaryOperator;
|
||||||
|
|
||||||
const FormatToken *NextToken = Tok.getNextNonComment();
|
auto *NextToken = Tok.getNextNonComment();
|
||||||
if (!NextToken)
|
if (!NextToken)
|
||||||
return TT_PointerOrReference;
|
return TT_PointerOrReference;
|
||||||
|
if (NextToken->is(tok::greater)) {
|
||||||
|
NextToken->setFinalizedType(TT_TemplateCloser);
|
||||||
|
return TT_PointerOrReference;
|
||||||
|
}
|
||||||
|
|
||||||
if (InTemplateArgument && NextToken->is(tok::kw_noexcept))
|
if (InTemplateArgument && NextToken->is(tok::kw_noexcept))
|
||||||
return TT_BinaryOperator;
|
return TT_BinaryOperator;
|
||||||
@ -3112,7 +3119,7 @@ private:
|
|||||||
|
|
||||||
// It's more likely that & represents operator& than an uninitialized
|
// It's more likely that & represents operator& than an uninitialized
|
||||||
// reference.
|
// reference.
|
||||||
if (Tok.is(tok::amp) && PrevToken && PrevToken->Tok.isAnyIdentifier() &&
|
if (Tok.is(tok::amp) && PrevToken->Tok.isAnyIdentifier() &&
|
||||||
IsChainedOperatorAmpOrMember(PrevToken->getPreviousNonComment()) &&
|
IsChainedOperatorAmpOrMember(PrevToken->getPreviousNonComment()) &&
|
||||||
NextToken && NextToken->Tok.isAnyIdentifier()) {
|
NextToken && NextToken->Tok.isAnyIdentifier()) {
|
||||||
if (auto NextNext = NextToken->getNextNonComment();
|
if (auto NextNext = NextToken->getNextNonComment();
|
||||||
@ -5474,7 +5481,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
|
|||||||
if (Left.TokenText == "!")
|
if (Left.TokenText == "!")
|
||||||
return Style.SpaceAfterLogicalNot;
|
return Style.SpaceAfterLogicalNot;
|
||||||
assert(Left.TokenText == "not");
|
assert(Left.TokenText == "not");
|
||||||
return Right.isOneOf(tok::coloncolon, TT_UnaryOperator);
|
return Right.isOneOf(tok::coloncolon, TT_UnaryOperator) ||
|
||||||
|
(Right.is(tok::l_paren) && Style.SpaceBeforeParensOptions.AfterNot);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the next token is a binary operator or a selector name, we have
|
// If the next token is a binary operator or a selector name, we have
|
||||||
@ -6266,7 +6274,8 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Right.is(tok::colon) &&
|
if (Right.is(tok::colon) &&
|
||||||
!Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon)) {
|
!Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon,
|
||||||
|
TT_BitFieldColon)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (Left.is(tok::colon) && Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) {
|
if (Left.is(tok::colon) && Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) {
|
||||||
|
@ -1542,6 +1542,17 @@ void CompilerInvocation::setDefaultPointerAuthOptions(
|
|||||||
Discrimination::Constant, InitFiniPointerConstantDiscriminator);
|
Discrimination::Constant, InitFiniPointerConstantDiscriminator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Opts.BlockInvocationFunctionPointers =
|
||||||
|
PointerAuthSchema(Key::ASIA, true, Discrimination::None);
|
||||||
|
Opts.BlockHelperFunctionPointers =
|
||||||
|
PointerAuthSchema(Key::ASIA, true, Discrimination::None);
|
||||||
|
Opts.BlockByrefHelperFunctionPointers =
|
||||||
|
PointerAuthSchema(Key::ASIA, true, Discrimination::None);
|
||||||
|
if (LangOpts.PointerAuthBlockDescriptorPointers)
|
||||||
|
Opts.BlockDescriptorPointers =
|
||||||
|
PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
|
||||||
|
BlockDescriptorConstantDiscriminator);
|
||||||
|
|
||||||
Opts.ObjCMethodListFunctionPointers =
|
Opts.ObjCMethodListFunctionPointers =
|
||||||
PointerAuthSchema(Key::ASIA, true, Discrimination::None);
|
PointerAuthSchema(Key::ASIA, true, Discrimination::None);
|
||||||
Opts.ObjCMethodListPointer =
|
Opts.ObjCMethodListPointer =
|
||||||
@ -3598,6 +3609,8 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts,
|
|||||||
GenerateArg(Consumer, OPT_fptrauth_objc_interface_sel);
|
GenerateArg(Consumer, OPT_fptrauth_objc_interface_sel);
|
||||||
if (Opts.PointerAuthObjcClassROPointers)
|
if (Opts.PointerAuthObjcClassROPointers)
|
||||||
GenerateArg(Consumer, OPT_fptrauth_objc_class_ro);
|
GenerateArg(Consumer, OPT_fptrauth_objc_class_ro);
|
||||||
|
if (Opts.PointerAuthBlockDescriptorPointers)
|
||||||
|
GenerateArg(Consumer, OPT_fptrauth_block_descriptor_pointers);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
|
static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
|
||||||
@ -3621,7 +3634,8 @@ static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
|
|||||||
Opts.PointerAuthELFGOT = Args.hasArg(OPT_fptrauth_elf_got);
|
Opts.PointerAuthELFGOT = Args.hasArg(OPT_fptrauth_elf_got);
|
||||||
Opts.AArch64JumpTableHardening =
|
Opts.AArch64JumpTableHardening =
|
||||||
Args.hasArg(OPT_faarch64_jump_table_hardening);
|
Args.hasArg(OPT_faarch64_jump_table_hardening);
|
||||||
|
Opts.PointerAuthBlockDescriptorPointers =
|
||||||
|
Args.hasArg(OPT_fptrauth_block_descriptor_pointers);
|
||||||
Opts.PointerAuthObjcIsa = Args.hasArg(OPT_fptrauth_objc_isa);
|
Opts.PointerAuthObjcIsa = Args.hasArg(OPT_fptrauth_objc_isa);
|
||||||
Opts.PointerAuthObjcClassROPointers = Args.hasArg(OPT_fptrauth_objc_class_ro);
|
Opts.PointerAuthObjcClassROPointers = Args.hasArg(OPT_fptrauth_objc_class_ro);
|
||||||
Opts.PointerAuthObjcInterfaceSel =
|
Opts.PointerAuthObjcInterfaceSel =
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user