Skip to content

Commit f039005

Browse files
SC llvm teamSC llvm team
SC llvm team
authored and
SC llvm team
committed
Merged main:ff843c00ce1d into amd-gfx:8bf801a67373
Local branch amd-gfx 8bf801a Merged main:8b356f496b18 into amd-gfx:d7a064a92fb5 Remote branch main ff843c0 [libc++] Bump the clang version the clang-tidy checks are based on (llvm#68318)
2 parents 8bf801a + ff843c0 commit f039005

File tree

46 files changed

+1288
-524
lines changed

Some content is hidden

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

46 files changed

+1288
-524
lines changed

clang/include/clang/Analysis/Analyses/ThreadSafety.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,13 @@ enum ProtectedOperationKind {
4747
POK_PassByRef,
4848

4949
/// Passing a pt-guarded variable by reference.
50-
POK_PtPassByRef
50+
POK_PtPassByRef,
51+
52+
/// Returning a guarded variable by reference.
53+
POK_ReturnByRef,
54+
55+
/// Returning a pt-guarded variable by reference.
56+
POK_PtReturnByRef,
5157
};
5258

5359
/// This enum distinguishes between different kinds of lock actions. For

clang/include/clang/Basic/DiagnosticSemaKinds.td

+9-1
Original file line numberDiff line numberDiff line change
@@ -3864,7 +3864,7 @@ def warn_fun_requires_negative_cap : Warning<
38643864
"calling function %0 requires negative capability '%1'">,
38653865
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
38663866

3867-
// Thread safety warnings on pass by reference
3867+
// Thread safety warnings on pass/return by reference
38683868
def warn_guarded_pass_by_reference : Warning<
38693869
"passing variable %1 by reference requires holding %0 "
38703870
"%select{'%2'|'%2' exclusively}3">,
@@ -3873,6 +3873,14 @@ def warn_pt_guarded_pass_by_reference : Warning<
38733873
"passing the value that %1 points to by reference requires holding %0 "
38743874
"%select{'%2'|'%2' exclusively}3">,
38753875
InGroup<ThreadSafetyReference>, DefaultIgnore;
3876+
def warn_guarded_return_by_reference : Warning<
3877+
"returning variable %1 by reference requires holding %0 "
3878+
"%select{'%2'|'%2' exclusively}3">,
3879+
InGroup<ThreadSafetyReference>, DefaultIgnore;
3880+
def warn_pt_guarded_return_by_reference : Warning<
3881+
"returning the value that %1 points to by reference requires holding %0 "
3882+
"%select{'%2'|'%2' exclusively}3">,
3883+
InGroup<ThreadSafetyReference>, DefaultIgnore;
38763884

38773885
// Imprecise thread safety warnings
38783886
def warn_variable_requires_lock : Warning<

clang/lib/Analysis/ThreadSafety.cpp

+54-26
Original file line numberDiff line numberDiff line change
@@ -1008,7 +1008,7 @@ class ThreadSafetyAnalyzer {
10081008
threadSafety::SExprBuilder SxBuilder;
10091009

10101010
ThreadSafetyHandler &Handler;
1011-
const CXXMethodDecl *CurrentMethod = nullptr;
1011+
const FunctionDecl *CurrentFunction;
10121012
LocalVariableMap LocalVarMap;
10131013
FactManager FactMan;
10141014
std::vector<CFGBlockInfo> BlockInfo;
@@ -1243,10 +1243,10 @@ bool ThreadSafetyAnalyzer::inCurrentScope(const CapabilityExpr &CapE) {
12431243

12441244
// Members are in scope from methods of the same class.
12451245
if (const auto *P = dyn_cast<til::Project>(SExp)) {
1246-
if (!CurrentMethod)
1246+
if (!isa_and_nonnull<CXXMethodDecl>(CurrentFunction))
12471247
return false;
12481248
const ValueDecl *VD = P->clangDecl();
1249-
return VD->getDeclContext() == CurrentMethod->getDeclContext();
1249+
return VD->getDeclContext() == CurrentFunction->getDeclContext();
12501250
}
12511251

12521252
return false;
@@ -1541,6 +1541,8 @@ class BuildLockset : public ConstStmtVisitor<BuildLockset> {
15411541

15421542
ThreadSafetyAnalyzer *Analyzer;
15431543
FactSet FSet;
1544+
// The fact set for the function on exit.
1545+
const FactSet &FunctionExitFSet;
15441546
/// Maps constructed objects to `this` placeholder prior to initialization.
15451547
llvm::SmallDenseMap<const Expr *, til::LiteralPtr *> ConstructedObjects;
15461548
LocalVariableMap::Context LVarCtx;
@@ -1566,9 +1568,11 @@ class BuildLockset : public ConstStmtVisitor<BuildLockset> {
15661568
bool SkipFirstParam = false);
15671569

15681570
public:
1569-
BuildLockset(ThreadSafetyAnalyzer *Anlzr, CFGBlockInfo &Info)
1571+
BuildLockset(ThreadSafetyAnalyzer *Anlzr, CFGBlockInfo &Info,
1572+
const FactSet &FunctionExitFSet)
15701573
: ConstStmtVisitor<BuildLockset>(), Analyzer(Anlzr), FSet(Info.EntrySet),
1571-
LVarCtx(Info.EntryContext), CtxIndex(Info.EntryIndex) {}
1574+
FunctionExitFSet(FunctionExitFSet), LVarCtx(Info.EntryContext),
1575+
CtxIndex(Info.EntryIndex) {}
15721576

15731577
void VisitUnaryOperator(const UnaryOperator *UO);
15741578
void VisitBinaryOperator(const BinaryOperator *BO);
@@ -1577,6 +1581,7 @@ class BuildLockset : public ConstStmtVisitor<BuildLockset> {
15771581
void VisitCXXConstructExpr(const CXXConstructExpr *Exp);
15781582
void VisitDeclStmt(const DeclStmt *S);
15791583
void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Exp);
1584+
void VisitReturnStmt(const ReturnStmt *S);
15801585
};
15811586

15821587
} // namespace
@@ -1758,6 +1763,8 @@ void ThreadSafetyAnalyzer::checkPtAccess(const FactSet &FSet, const Expr *Exp,
17581763
// Pass by reference warnings are under a different flag.
17591764
ProtectedOperationKind PtPOK = POK_VarDereference;
17601765
if (POK == POK_PassByRef) PtPOK = POK_PtPassByRef;
1766+
if (POK == POK_ReturnByRef)
1767+
PtPOK = POK_PtReturnByRef;
17611768

17621769
const ValueDecl *D = getValueDecl(Exp);
17631770
if (!D || !D->hasAttrs())
@@ -2142,6 +2149,25 @@ void BuildLockset::VisitMaterializeTemporaryExpr(
21422149
}
21432150
}
21442151

2152+
void BuildLockset::VisitReturnStmt(const ReturnStmt *S) {
2153+
if (Analyzer->CurrentFunction == nullptr)
2154+
return;
2155+
const Expr *RetVal = S->getRetValue();
2156+
if (!RetVal)
2157+
return;
2158+
2159+
// If returning by reference, check that the function requires the appropriate
2160+
// capabilities.
2161+
const QualType ReturnType =
2162+
Analyzer->CurrentFunction->getReturnType().getCanonicalType();
2163+
if (ReturnType->isLValueReferenceType()) {
2164+
Analyzer->checkAccess(
2165+
FunctionExitFSet, RetVal,
2166+
ReturnType->getPointeeType().isConstQualified() ? AK_Read : AK_Written,
2167+
POK_ReturnByRef);
2168+
}
2169+
}
2170+
21452171
/// Given two facts merging on a join point, possibly warn and decide whether to
21462172
/// keep or replace.
21472173
///
@@ -2251,8 +2277,7 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
22512277

22522278
CFG *CFGraph = walker.getGraph();
22532279
const NamedDecl *D = walker.getDecl();
2254-
const auto *CurrentFunction = dyn_cast<FunctionDecl>(D);
2255-
CurrentMethod = dyn_cast<CXXMethodDecl>(D);
2280+
CurrentFunction = dyn_cast<FunctionDecl>(D);
22562281

22572282
if (D->hasAttr<NoThreadSafetyAnalysisAttr>())
22582283
return;
@@ -2278,7 +2303,7 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
22782303
PostOrderCFGView::CFGBlockSet VisitedBlocks(CFGraph);
22792304

22802305
CFGBlockInfo &Initial = BlockInfo[CFGraph->getEntry().getBlockID()];
2281-
CFGBlockInfo &Final = BlockInfo[CFGraph->getExit().getBlockID()];
2306+
CFGBlockInfo &Final = BlockInfo[CFGraph->getExit().getBlockID()];
22822307

22832308
// Mark entry block as reachable
22842309
Initial.Reachable = true;
@@ -2348,6 +2373,25 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
23482373
}
23492374
}
23502375

2376+
// Compute the expected exit set.
2377+
// By default, we expect all locks held on entry to be held on exit.
2378+
FactSet ExpectedFunctionExitSet = Initial.EntrySet;
2379+
2380+
// Adjust the expected exit set by adding or removing locks, as declared
2381+
// by *-LOCK_FUNCTION and UNLOCK_FUNCTION. The intersect below will then
2382+
// issue the appropriate warning.
2383+
// FIXME: the location here is not quite right.
2384+
for (const auto &Lock : ExclusiveLocksAcquired)
2385+
ExpectedFunctionExitSet.addLock(
2386+
FactMan, std::make_unique<LockableFactEntry>(Lock, LK_Exclusive,
2387+
D->getLocation()));
2388+
for (const auto &Lock : SharedLocksAcquired)
2389+
ExpectedFunctionExitSet.addLock(
2390+
FactMan,
2391+
std::make_unique<LockableFactEntry>(Lock, LK_Shared, D->getLocation()));
2392+
for (const auto &Lock : LocksReleased)
2393+
ExpectedFunctionExitSet.removeLock(FactMan, Lock);
2394+
23512395
for (const auto *CurrBlock : *SortedGraph) {
23522396
unsigned CurrBlockID = CurrBlock->getBlockID();
23532397
CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlockID];
@@ -2407,7 +2451,7 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
24072451
if (!CurrBlockInfo->Reachable)
24082452
continue;
24092453

2410-
BuildLockset LocksetBuilder(this, *CurrBlockInfo);
2454+
BuildLockset LocksetBuilder(this, *CurrBlockInfo, ExpectedFunctionExitSet);
24112455

24122456
// Visit all the statements in the basic block.
24132457
for (const auto &BI : *CurrBlock) {
@@ -2483,24 +2527,8 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
24832527
if (!Final.Reachable)
24842528
return;
24852529

2486-
// By default, we expect all locks held on entry to be held on exit.
2487-
FactSet ExpectedExitSet = Initial.EntrySet;
2488-
2489-
// Adjust the expected exit set by adding or removing locks, as declared
2490-
// by *-LOCK_FUNCTION and UNLOCK_FUNCTION. The intersect below will then
2491-
// issue the appropriate warning.
2492-
// FIXME: the location here is not quite right.
2493-
for (const auto &Lock : ExclusiveLocksAcquired)
2494-
ExpectedExitSet.addLock(FactMan, std::make_unique<LockableFactEntry>(
2495-
Lock, LK_Exclusive, D->getLocation()));
2496-
for (const auto &Lock : SharedLocksAcquired)
2497-
ExpectedExitSet.addLock(FactMan, std::make_unique<LockableFactEntry>(
2498-
Lock, LK_Shared, D->getLocation()));
2499-
for (const auto &Lock : LocksReleased)
2500-
ExpectedExitSet.removeLock(FactMan, Lock);
2501-
25022530
// FIXME: Should we call this function for all blocks which exit the function?
2503-
intersectAndWarn(ExpectedExitSet, Final.ExitSet, Final.ExitLoc,
2531+
intersectAndWarn(ExpectedFunctionExitSet, Final.ExitSet, Final.ExitLoc,
25042532
LEK_LockedAtEndOfFunction, LEK_NotLockedAtEndOfFunction);
25052533

25062534
Handler.leaveFunction(CurrentFunction);

clang/lib/Sema/AnalysisBasedWarnings.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -1983,6 +1983,12 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
19831983
case POK_PtPassByRef:
19841984
DiagID = diag::warn_pt_guarded_pass_by_reference;
19851985
break;
1986+
case POK_ReturnByRef:
1987+
DiagID = diag::warn_guarded_return_by_reference;
1988+
break;
1989+
case POK_PtReturnByRef:
1990+
DiagID = diag::warn_pt_guarded_return_by_reference;
1991+
break;
19861992
}
19871993
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
19881994
<< D
@@ -2013,6 +2019,12 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
20132019
case POK_PtPassByRef:
20142020
DiagID = diag::warn_pt_guarded_pass_by_reference;
20152021
break;
2022+
case POK_ReturnByRef:
2023+
DiagID = diag::warn_guarded_return_by_reference;
2024+
break;
2025+
case POK_PtReturnByRef:
2026+
DiagID = diag::warn_pt_guarded_return_by_reference;
2027+
break;
20162028
}
20172029
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
20182030
<< D

clang/lib/Sema/Sema.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -2071,7 +2071,7 @@ void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) {
20712071
targetDiag(D->getLocation(), diag::note_defined_here, FD) << D;
20722072
}
20732073

2074-
if (Ty->isRVVType())
2074+
if (TI.hasRISCVVTypes() && Ty->isRVVType())
20752075
checkRVVTypeSupport(Ty, Loc, D);
20762076

20772077
// Don't allow SVE types in functions without a SVE target.

clang/test/SemaCXX/warn-thread-safety-analysis.cpp

+79
Original file line numberDiff line numberDiff line change
@@ -5580,6 +5580,85 @@ class Bar {
55805580
}
55815581
};
55825582

5583+
class Return {
5584+
Mutex mu;
5585+
Foo foo GUARDED_BY(mu);
5586+
Foo* foo_ptr PT_GUARDED_BY(mu);
5587+
5588+
Foo returns_value_locked() {
5589+
MutexLock lock(&mu);
5590+
return foo;
5591+
}
5592+
5593+
Foo returns_value_locks_required() EXCLUSIVE_LOCKS_REQUIRED(mu) {
5594+
return foo;
5595+
}
5596+
5597+
Foo returns_value_releases_lock_after_return() UNLOCK_FUNCTION(mu) {
5598+
MutexLock lock(&mu, true);
5599+
return foo;
5600+
}
5601+
5602+
Foo returns_value_aquires_lock() EXCLUSIVE_LOCK_FUNCTION(mu) {
5603+
mu.Lock();
5604+
return foo;
5605+
}
5606+
5607+
Foo returns_value_not_locked() {
5608+
return foo; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
5609+
}
5610+
5611+
Foo returns_value_releases_lock_before_return() UNLOCK_FUNCTION(mu) {
5612+
mu.Unlock();
5613+
return foo; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
5614+
}
5615+
5616+
Foo &returns_ref_not_locked() {
5617+
return foo; // expected-warning {{returning variable 'foo' by reference requires holding mutex 'mu'}}
5618+
}
5619+
5620+
Foo &returns_ref_locked() {
5621+
MutexLock lock(&mu);
5622+
return foo; // expected-warning {{returning variable 'foo' by reference requires holding mutex 'mu'}}
5623+
}
5624+
5625+
Foo &returns_ref_shared_locks_required() SHARED_LOCKS_REQUIRED(mu) {
5626+
return foo; // expected-warning {{returning variable 'foo' by reference requires holding mutex 'mu' exclusively}}
5627+
}
5628+
5629+
Foo &returns_ref_exclusive_locks_required() EXCLUSIVE_LOCKS_REQUIRED(mu) {
5630+
return foo;
5631+
}
5632+
5633+
Foo &returns_ref_releases_lock_after_return() UNLOCK_FUNCTION(mu) {
5634+
MutexLock lock(&mu, true);
5635+
return foo; // expected-warning {{returning variable 'foo' by reference requires holding mutex 'mu' exclusively}}
5636+
}
5637+
5638+
Foo& returns_ref_releases_lock_before_return() UNLOCK_FUNCTION(mu) {
5639+
mu.Unlock();
5640+
return foo; // // expected-warning {{returning variable 'foo' by reference requires holding mutex 'mu' exclusively}}
5641+
}
5642+
5643+
Foo &returns_ref_aquires_lock() EXCLUSIVE_LOCK_FUNCTION(mu) {
5644+
mu.Lock();
5645+
return foo;
5646+
}
5647+
5648+
const Foo &returns_constref_shared_locks_required() SHARED_LOCKS_REQUIRED(mu) {
5649+
return foo;
5650+
}
5651+
5652+
Foo *returns_ptr() {
5653+
return &foo; // FIXME -- Do we want to warn on this ?
5654+
}
5655+
5656+
Foo &returns_ref2() {
5657+
return *foo_ptr; // expected-warning {{returning the value that 'foo_ptr' points to by reference requires holding mutex 'mu' exclusively}}
5658+
}
5659+
5660+
};
5661+
55835662

55845663
} // end namespace PassByRefTest
55855664

compiler-rt/include/fuzzer/FuzzedDataProvider.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ FuzzedDataProvider::ConsumeRandomLengthString(size_t max_length) {
158158
// picking its contents.
159159
std::string result;
160160

161-
// Reserve the anticipated capaticity to prevent several reallocations.
161+
// Reserve the anticipated capacity to prevent several reallocations.
162162
result.reserve(std::min(max_length, remaining_bytes_));
163163
for (size_t i = 0; i < max_length && remaining_bytes_ != 0; ++i) {
164164
char next = ConvertUnsignedToSigned<char>(data_ptr_[0]);

libcxx/docs/ReleaseNotes/18.rst

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ Implemented Papers
5252
- P2697R1 - Interfacing ``bitset`` with ``string_view``
5353
- P2443R1 - ``views::chunk_by``
5454
- P2538R1 - ADL-proof ``std::projected``
55+
- P2614R2 - Deprecate ``numeric_limits::has_denorm``
5556

5657

5758
Improvements and New Features

libcxx/docs/Status/Cxx23Papers.csv

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
"`P2655R3 <https://wg21.link/P2655R3>`__","LWG", "``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type","February 2023","","",""
118118
"`P2652R2 <https://wg21.link/P2652R2>`__","LWG", "Disallow User Specialization of ``allocator_traits``","February 2023","","",""
119119
"`P2787R1 <https://wg21.link/P2787R1>`__","LWG", "``pmr::generator`` - Promise Types are not Values","February 2023","","",""
120-
"`P2614R2 <https://wg21.link/P2614R2>`__","LWG", "Deprecate ``numeric_limits::has_denorm``","February 2023","","",""
120+
"`P2614R2 <https://wg21.link/P2614R2>`__","LWG", "Deprecate ``numeric_limits::has_denorm``","February 2023","|Complete|","18.0",""
121121
"`P2588R3 <https://wg21.link/P2588R3>`__","LWG", "``barrier``’s phase completion guarantees","February 2023","","",""
122122
"`P2763R1 <https://wg21.link/P2763R1>`__","LWG", "``layout_stride`` static extents default constructor fix","February 2023","","",""
123123
"`P2736R2 <https://wg21.link/P2736R2>`__","CWG","Referencing The Unicode Standard","February 2023","","","|format|"

libcxx/include/__availability

+17
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,17 @@
179179
// # define _LIBCPP_AVAILABILITY_HAS_NO_TZDB
180180
# define _LIBCPP_AVAILABILITY_TZDB
181181

182+
// Enable additional explicit instantiations of iostreams components. This
183+
// reduces the number of weak definitions generated in programs that use
184+
// iostreams by providing a single strong definition in the shared library.
185+
//
186+
// TODO: Enable additional explicit instantiations on GCC once it supports exclude_from_explicit_instantiation,
187+
// or once libc++ doesn't use the attribute anymore.
188+
// TODO: Enable them on Windows once https://llvm.org/PR41018 has been fixed.
189+
#if defined(_LIBCPP_COMPILER_GCC) || defined(_WIN32)
190+
# define _LIBCPP_AVAILABILITY_HAS_NO_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1
191+
#endif
192+
182193
#elif defined(__APPLE__)
183194

184195
// shared_mutex and shared_timed_mutex
@@ -356,6 +367,12 @@
356367
# define _LIBCPP_AVAILABILITY_HAS_NO_TZDB
357368
# define _LIBCPP_AVAILABILITY_TZDB __attribute__((unavailable))
358369

370+
# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 120000) || \
371+
(defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 150000) || \
372+
(defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 150000) || \
373+
(defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 80000)
374+
# define _LIBCPP_AVAILABILITY_HAS_NO_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1
375+
# endif
359376
#else
360377

361378
// ...New vendors can add availability markup here...

libcxx/include/__config

-5
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,6 @@
193193
# endif
194194

195195
# if defined(_LIBCPP_BUILDING_LIBRARY) || _LIBCPP_ABI_VERSION >= 2
196-
// Enable additional explicit instantiations of iostreams components. This
197-
// reduces the number of weak definitions generated in programs that use
198-
// iostreams by providing a single strong definition in the shared library.
199-
# define _LIBCPP_ABI_ENABLE_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1
200-
201196
// Define a key function for `bad_function_call` in the library, to centralize
202197
// its vtable and typeinfo to libc++ rather than having all other libraries
203198
// using that class define their own copies.

0 commit comments

Comments
 (0)