Skip to content

Commit b54f57d

Browse files
authored
Merge branch 'main' into readonly
2 parents c8d3ab8 + 18d4da2 commit b54f57d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1536
-91
lines changed

clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,19 @@ CoroutineHostileRAIICheck::CoroutineHostileRAIICheck(StringRef Name,
7373
RAIITypesList(utils::options::parseStringList(
7474
Options.get("RAIITypesList", "std::lock_guard;std::scoped_lock"))),
7575
AllowedAwaitablesList(utils::options::parseStringList(
76-
Options.get("AllowedAwaitablesList", ""))) {}
76+
Options.get("AllowedAwaitablesList", ""))),
77+
AllowedCallees(
78+
utils::options::parseStringList(Options.get("AllowedCallees", ""))) {}
7779

7880
void CoroutineHostileRAIICheck::registerMatchers(MatchFinder *Finder) {
7981
// A suspension happens with co_await or co_yield.
8082
auto ScopedLockable = varDecl(hasType(hasCanonicalType(hasDeclaration(
8183
hasAttr(attr::Kind::ScopedLockable)))))
8284
.bind("scoped-lockable");
8385
auto OtherRAII = varDecl(typeWithNameIn(RAIITypesList)).bind("raii");
84-
auto AllowedSuspend = awaitable(typeWithNameIn(AllowedAwaitablesList));
86+
auto AllowedSuspend = awaitable(
87+
anyOf(typeWithNameIn(AllowedAwaitablesList),
88+
callExpr(callee(functionDecl(hasAnyName(AllowedCallees))))));
8589
Finder->addMatcher(
8690
expr(anyOf(coawaitExpr(unless(AllowedSuspend)), coyieldExpr()),
8791
forEachPrevStmt(
@@ -111,5 +115,7 @@ void CoroutineHostileRAIICheck::storeOptions(
111115
utils::options::serializeStringList(RAIITypesList));
112116
Options.store(Opts, "SafeAwaitableList",
113117
utils::options::serializeStringList(AllowedAwaitablesList));
118+
Options.store(Opts, "SafeCallees",
119+
utils::options::serializeStringList(AllowedCallees));
114120
}
115121
} // namespace clang::tidy::misc

clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ class CoroutineHostileRAIICheck : public ClangTidyCheck {
4646
// List of fully qualified awaitable types which are considered safe to
4747
// co_await.
4848
std::vector<StringRef> AllowedAwaitablesList;
49+
// List of callees whose return values are considered safe to directly
50+
// co_await.
51+
std::vector<StringRef> AllowedCallees;
4952
};
5053

5154
} // namespace clang::tidy::misc

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,11 @@ Changes in existing checks
423423
positives on return of non-const pointer and fix false positives on
424424
pointer-to-member operator.
425425

426+
- Improved :doc:`misc-coroutine-hostile-raii
427+
<clang-tidy/checks/misc/coroutine-hostile-raii>` check by adding the option
428+
`AllowedCallees`, that allows exempting safely awaitable callees from the
429+
check.
430+
426431
- Improved :doc:`misc-header-include-cycle
427432
<clang-tidy/checks/misc/header-include-cycle>` check performance.
428433

clang-tools-extra/docs/clang-tidy/checks/misc/coroutine-hostile-raii.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,23 @@ Options
8181
Eg: `my::safe::awaitable;other::awaitable`
8282
Default is an empty string.
8383

84+
.. option:: AllowedCallees
85+
86+
A semicolon-separated list of callee function names which can
87+
be safely awaited while having hostile RAII objects in scope.
88+
Example usage:
89+
90+
.. code-block:: c++
91+
92+
// Consider option AllowedCallees = "noop"
93+
task noop() { co_return; }
94+
95+
task coro() {
96+
// This persists across the co_await but is not flagged
97+
// because the awaitable is considered safe to await on.
98+
const std::lock_guard l(&mu_);
99+
co_await noop();
100+
}
101+
102+
Eg: `my::safe::await;other::await`
103+
Default is an empty string.

clang-tools-extra/test/clang-tidy/checkers/misc/coroutine-hostile-raii.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// RUN: %check_clang_tidy -std=c++20 %s misc-coroutine-hostile-raii %t \
22
// RUN: -config="{CheckOptions: {\
33
// RUN: misc-coroutine-hostile-raii.RAIITypesList: 'my::Mutex; ::my::other::Mutex', \
4-
// RUN: misc-coroutine-hostile-raii.AllowedAwaitablesList: 'safe::awaitable; ::transformable::awaitable' \
4+
// RUN: misc-coroutine-hostile-raii.AllowedAwaitablesList: 'safe::awaitable; ::transformable::awaitable', \
5+
// RUN: misc-coroutine-hostile-raii.AllowedCallees: 'safe::AwaitFunc; ::safe::Obj::AwaitMethod' \
56
// RUN: }}"
67

78
namespace std {
@@ -145,12 +146,18 @@ namespace safe {
145146
void await_suspend(std::coroutine_handle<>) noexcept {}
146147
void await_resume() noexcept {}
147148
};
149+
std::suspend_always AwaitFunc();
150+
struct Obj {
151+
std::suspend_always AwaitMethod();
152+
};
148153
} // namespace safe
149154
ReturnObject RAIISafeSuspendTest() {
150155
absl::Mutex a;
151156
co_await safe::awaitable{};
152157
using other = safe::awaitable;
153158
co_await other{};
159+
co_await safe::AwaitFunc();
160+
co_await safe::Obj().AwaitMethod();
154161
}
155162

156163
// ================================================================================

compiler-rt/test/lit.common.cfg.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -195,16 +195,14 @@ def push_dynamic_library_lookup_path(config, new_path):
195195
# Normalize the path for comparison
196196
if test_cc_resource_dir is not None:
197197
test_cc_resource_dir = os.path.realpath(test_cc_resource_dir)
198-
if lit_config.debug:
199-
lit_config.note(f"Resource dir for {config.clang} is {test_cc_resource_dir}")
198+
lit_config.dbg(f"Resource dir for {config.clang} is {test_cc_resource_dir}")
200199
local_build_resource_dir = os.path.realpath(config.compiler_rt_output_dir)
201200
if test_cc_resource_dir != local_build_resource_dir and config.test_standalone_build_libs:
202201
if config.compiler_id == "Clang":
203-
if lit_config.debug:
204-
lit_config.note(
205-
f"Overriding test compiler resource dir to use "
206-
f'libraries in "{config.compiler_rt_libdir}"'
207-
)
202+
lit_config.dbg(
203+
f"Overriding test compiler resource dir to use "
204+
f'libraries in "{config.compiler_rt_libdir}"'
205+
)
208206
# Ensure that we use the just-built static libraries when linking by
209207
# overriding the Clang resource directory. Additionally, we want to use
210208
# the builtin headers shipped with clang (e.g. stdint.h), so we

libcxx/test/selftest/dsl/dsl.sh.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def setUp(self):
6161
self.litConfig = lit.LitConfig.LitConfig(
6262
progname="lit",
6363
path=[],
64-
quiet=False,
64+
diagnostic_level="note",
6565
useValgrind=False,
6666
valgrindLeakCheck=False,
6767
valgrindArgs=[],

libcxx/utils/libcxx/test/config.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ def _appendToSubstitution(substitutions, key, value):
2222

2323
def configure(parameters, features, config, lit_config):
2424
note = lambda s: lit_config.note("({}) {}".format(config.name, s))
25+
debug = lambda s: lit_config.dbg("({}) {}".format(config.name, s))
2526
config.environment = dict(os.environ)
2627

2728
# Apply the actions supplied by parameters to the configuration first, since
@@ -31,25 +32,23 @@ def configure(parameters, features, config, lit_config):
3132
actions = param.getActions(config, lit_config.params)
3233
for action in actions:
3334
action.applyTo(config)
34-
if lit_config.debug:
35-
note(
36-
"Applied '{}' as a result of parameter '{}'".format(
37-
action.pretty(config, lit_config.params),
38-
param.pretty(config, lit_config.params),
39-
)
35+
debug(
36+
"Applied '{}' as a result of parameter '{}'".format(
37+
action.pretty(config, lit_config.params),
38+
param.pretty(config, lit_config.params),
4039
)
40+
)
4141

4242
# Then, apply the automatically-detected features.
4343
for feature in features:
4444
actions = feature.getActions(config)
4545
for action in actions:
4646
action.applyTo(config)
47-
if lit_config.debug:
48-
note(
49-
"Applied '{}' as a result of implicitly detected feature '{}'".format(
50-
action.pretty(config, lit_config.params), feature.pretty(config)
51-
)
47+
debug(
48+
"Applied '{}' as a result of implicitly detected feature '{}'".format(
49+
action.pretty(config, lit_config.params), feature.pretty(config)
5250
)
51+
)
5352

5453
# Print the basic substitutions
5554
for sub in ("%{cxx}", "%{flags}", "%{compile_flags}", "%{link_flags}", "%{benchmark_flags}", "%{exec}"):

libcxx/utils/libcxx/test/dsl.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def _executeWithFakeConfig(test, commands):
8888
litConfig = lit.LitConfig.LitConfig(
8989
progname="lit",
9090
path=[],
91-
quiet=False,
91+
diagnostic_level="note",
9292
useValgrind=False,
9393
valgrindLeakCheck=False,
9494
valgrindArgs=[],

llvm/lib/Target/ARM/ARMISelLowering.cpp

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2510,9 +2510,44 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
25102510

25112511
if (isTailCall && VA.isMemLoc() && !AfterFormalArgLoads) {
25122512
Chain = DAG.getStackArgumentTokenFactor(Chain);
2513-
if (ByValTempChain)
2513+
if (ByValTempChain) {
2514+
// In case of large byval copies, re-using the stackframe for tail-calls
2515+
// can lead to overwriting incoming arguments on the stack. Force
2516+
// loading these stack arguments before the copy to avoid that.
2517+
SmallVector<SDValue, 8> IncomingLoad;
2518+
for (unsigned I = 0; I < OutVals.size(); ++I) {
2519+
if (Outs[I].Flags.isByVal())
2520+
continue;
2521+
2522+
SDValue OutVal = OutVals[I];
2523+
LoadSDNode *OutLN = dyn_cast_or_null<LoadSDNode>(OutVal);
2524+
if (!OutLN)
2525+
continue;
2526+
2527+
FrameIndexSDNode *FIN =
2528+
dyn_cast_or_null<FrameIndexSDNode>(OutLN->getBasePtr());
2529+
if (!FIN)
2530+
continue;
2531+
2532+
if (!MFI.isFixedObjectIndex(FIN->getIndex()))
2533+
continue;
2534+
2535+
for (const CCValAssign &VA : ArgLocs) {
2536+
if (VA.isMemLoc())
2537+
IncomingLoad.push_back(OutVal.getValue(1));
2538+
}
2539+
}
2540+
2541+
// Update the chain to force loads for potentially clobbered argument
2542+
// loads to happen before the byval copy.
2543+
if (!IncomingLoad.empty()) {
2544+
IncomingLoad.push_back(Chain);
2545+
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, IncomingLoad);
2546+
}
2547+
25142548
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chain,
25152549
ByValTempChain);
2550+
}
25162551
AfterFormalArgLoads = true;
25172552
}
25182553

0 commit comments

Comments
 (0)