Skip to content

Commit 4ce515f

Browse files
SC llvm teamSC llvm team
authored andcommitted
Merged main:69c43468d3f21df6232fda0530f03f18b0f40345 into amd-gfx:45ac84d24a03
Local branch amd-gfx 45ac84d Merged main:902b2a26ab9e1e78dfb66b52fba4512c91472e09 into amd-gfx:9b007be77fcd Remote branch main 69c4346 [LoopUnrollAnalyzer] Dont simplify signed pointer comparison
2 parents 45ac84d + 69c4346 commit 4ce515f

File tree

113 files changed

+1635
-1267
lines changed

Some content is hidden

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

113 files changed

+1635
-1267
lines changed

clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88
//
9-
// This file defines CheckerVisitor.
9+
// This file defines various utilities used by checkers.
1010
//
1111
//===----------------------------------------------------------------------===//
1212

@@ -114,6 +114,10 @@ OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK,
114114

115115
std::optional<SVal> getPointeeVal(SVal PtrSVal, ProgramStateRef State);
116116

117+
/// Returns true if declaration \p D is in std namespace or any nested namespace
118+
/// or class scope.
119+
bool isWithinStdNamespace(const Decl *D);
120+
117121
} // namespace ento
118122

119123
} // namespace clang

clang/lib/CodeGen/CGBuilder.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include "CodeGenTypeCache.h"
1515
#include "llvm/Analysis/Utils/Local.h"
1616
#include "llvm/IR/DataLayout.h"
17-
#include "llvm/IR/GEPNoWrapFlags.h"
1817
#include "llvm/IR/IRBuilder.h"
1918
#include "llvm/IR/Type.h"
2019

@@ -335,10 +334,9 @@ class CGBuilderTy : public CGBuilderBaseTy {
335334

336335
Address CreateGEP(Address Addr, ArrayRef<llvm::Value *> IdxList,
337336
llvm::Type *ElementType, CharUnits Align,
338-
const Twine &Name = "",
339-
llvm::GEPNoWrapFlags NW = llvm::GEPNoWrapFlags::none()) {
337+
const Twine &Name = "") {
340338
llvm::Value *Ptr = emitRawPointerFromAddress(Addr);
341-
return RawAddress(CreateGEP(Addr.getElementType(), Ptr, IdxList, Name, NW),
339+
return RawAddress(CreateGEP(Addr.getElementType(), Ptr, IdxList, Name),
342340
ElementType, Align);
343341
}
344342

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
#include "llvm/IR/DerivedTypes.h"
3737
#include "llvm/IR/FixedPointBuilder.h"
3838
#include "llvm/IR/Function.h"
39-
#include "llvm/IR/GEPNoWrapFlags.h"
4039
#include "llvm/IR/GetElementPtrTypeIterator.h"
4140
#include "llvm/IR/GlobalVariable.h"
4241
#include "llvm/IR/Intrinsics.h"
@@ -5757,12 +5756,7 @@ CodeGenFunction::EmitCheckedInBoundsGEP(llvm::Type *ElemTy, Value *Ptr,
57575756
bool SignedIndices, bool IsSubtraction,
57585757
SourceLocation Loc, const Twine &Name) {
57595758
llvm::Type *PtrTy = Ptr->getType();
5760-
5761-
llvm::GEPNoWrapFlags NWFlags = llvm::GEPNoWrapFlags::inBounds();
5762-
if (!SignedIndices && !IsSubtraction)
5763-
NWFlags |= llvm::GEPNoWrapFlags::noUnsignedWrap();
5764-
5765-
Value *GEPVal = Builder.CreateGEP(ElemTy, Ptr, IdxList, Name, NWFlags);
5759+
Value *GEPVal = Builder.CreateInBoundsGEP(ElemTy, Ptr, IdxList, Name);
57665760

57675761
// If the pointer overflow sanitizer isn't enabled, do nothing.
57685762
if (!SanOpts.has(SanitizerKind::PointerOverflow))
@@ -5877,13 +5871,8 @@ Address CodeGenFunction::EmitCheckedInBoundsGEP(
58775871
Address Addr, ArrayRef<Value *> IdxList, llvm::Type *elementType,
58785872
bool SignedIndices, bool IsSubtraction, SourceLocation Loc, CharUnits Align,
58795873
const Twine &Name) {
5880-
if (!SanOpts.has(SanitizerKind::PointerOverflow)) {
5881-
llvm::GEPNoWrapFlags NWFlags = llvm::GEPNoWrapFlags::inBounds();
5882-
if (!SignedIndices && !IsSubtraction)
5883-
NWFlags |= llvm::GEPNoWrapFlags::noUnsignedWrap();
5884-
5885-
return Builder.CreateGEP(Addr, IdxList, elementType, Align, Name, NWFlags);
5886-
}
5874+
if (!SanOpts.has(SanitizerKind::PointerOverflow))
5875+
return Builder.CreateInBoundsGEP(Addr, IdxList, elementType, Align, Name);
58875876

58885877
return RawAddress(
58895878
EmitCheckedInBoundsGEP(Addr.getElementType(), Addr.emitRawPointer(*this),

clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
2121
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
2222
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
23+
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
2324
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
2425
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
2526
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
@@ -241,12 +242,22 @@ BlockInCriticalSectionChecker::checkDescriptorMatch(const CallEvent &Call,
241242
return std::nullopt;
242243
}
243244

245+
static const MemRegion *skipStdBaseClassRegion(const MemRegion *Reg) {
246+
while (Reg) {
247+
const auto *BaseClassRegion = dyn_cast<CXXBaseObjectRegion>(Reg);
248+
if (!BaseClassRegion || !isWithinStdNamespace(BaseClassRegion->getDecl()))
249+
break;
250+
Reg = BaseClassRegion->getSuperRegion();
251+
}
252+
return Reg;
253+
}
254+
244255
static const MemRegion *getRegion(const CallEvent &Call,
245256
const MutexDescriptor &Descriptor,
246257
bool IsLock) {
247258
return std::visit(
248-
[&Call, IsLock](auto &&Descriptor) {
249-
return Descriptor.getRegion(Call, IsLock);
259+
[&Call, IsLock](auto &Descr) -> const MemRegion * {
260+
return skipStdBaseClassRegion(Descr.getRegion(Call, IsLock));
250261
},
251262
Descriptor);
252263
}

clang/lib/StaticAnalyzer/Core/CallEvent.cpp

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "clang/CrossTU/CrossTranslationUnit.h"
3939
#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
4040
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
41+
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
4142
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h"
4243
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h"
4344
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
@@ -923,17 +924,6 @@ SVal AnyCXXConstructorCall::getCXXThisVal() const {
923924
return UnknownVal();
924925
}
925926

926-
static bool isWithinStdNamespace(const Decl *D) {
927-
const DeclContext *DC = D->getDeclContext();
928-
while (DC) {
929-
if (const auto *NS = dyn_cast<NamespaceDecl>(DC);
930-
NS && NS->isStdNamespace())
931-
return true;
932-
DC = DC->getParent();
933-
}
934-
return false;
935-
}
936-
937927
void AnyCXXConstructorCall::getExtraInvalidatedValues(ValueList &Values,
938928
RegionAndSymbolInvalidationTraits *ETraits) const {
939929
SVal V = getCXXThisVal();

clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,5 +190,16 @@ std::optional<SVal> getPointeeVal(SVal PtrSVal, ProgramStateRef State) {
190190
return std::nullopt;
191191
}
192192

193+
bool isWithinStdNamespace(const Decl *D) {
194+
const DeclContext *DC = D->getDeclContext();
195+
while (DC) {
196+
if (const auto *NS = dyn_cast<NamespaceDecl>(DC);
197+
NS && NS->isStdNamespace())
198+
return true;
199+
DC = DC->getParent();
200+
}
201+
return false;
202+
}
203+
193204
} // namespace ento
194205
} // namespace clang

clang/test/Analysis/block-in-critical-section-inheritance.cpp

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,168 @@ void gh_99628() {
2929
// expected-note@-2 {{Call to blocking function 'sleep' inside of critical section}}
3030
m.unlock();
3131
}
32+
33+
void no_false_positive_gh_104241() {
34+
std::mutex m;
35+
m.lock();
36+
// If inheritance not handled properly, this unlock might not match the lock
37+
// above because technically they act on different memory regions:
38+
// __mutex_base and mutex.
39+
m.unlock();
40+
sleep(10); // no-warning
41+
}
42+
43+
struct TwoMutexes {
44+
std::mutex m1;
45+
std::mutex m2;
46+
};
47+
48+
void two_mutexes_no_false_negative(TwoMutexes &tm) {
49+
tm.m1.lock();
50+
// expected-note@-1 {{Entering critical section here}}
51+
tm.m2.unlock();
52+
sleep(10);
53+
// expected-warning@-1 {{Call to blocking function 'sleep' inside of critical section}}
54+
// expected-note@-2 {{Call to blocking function 'sleep' inside of critical section}}
55+
tm.m1.unlock();
56+
}
57+
58+
struct MyMutexBase1 : std::mutex {
59+
void lock1() { lock(); }
60+
// expected-note@-1 {{Entering critical section here}}
61+
void unlock1() { unlock(); }
62+
};
63+
struct MyMutexBase2 : std::mutex {
64+
void lock2() { lock(); }
65+
void unlock2() { unlock(); }
66+
};
67+
struct MyMutex : MyMutexBase1, MyMutexBase2 {};
68+
// MyMutex has two distinct std::mutex as base classes
69+
70+
void custom_mutex_tp(MyMutexBase1 &mb) {
71+
mb.lock();
72+
// expected-note@-1 {{Entering critical section here}}
73+
sleep(10);
74+
// expected-warning@-1 {{Call to blocking function 'sleep' inside of critical section}}
75+
// expected-note@-2 {{Call to blocking function 'sleep' inside of critical section}}
76+
mb.unlock();
77+
}
78+
79+
void custom_mutex_tn(MyMutexBase1 &mb) {
80+
mb.lock();
81+
mb.unlock();
82+
sleep(10);
83+
}
84+
85+
void custom_mutex_cast_tp(MyMutexBase1 &mb) {
86+
static_cast<std::mutex&>(mb).lock();
87+
// expected-note@-1 {{Entering critical section here}}
88+
sleep(10);
89+
// expected-warning@-1 {{Call to blocking function 'sleep' inside of critical section}}
90+
// expected-note@-2 {{Call to blocking function 'sleep' inside of critical section}}
91+
static_cast<std::mutex&>(mb).unlock();
92+
}
93+
94+
void custom_mutex_cast_tn(MyMutexBase1 &mb) {
95+
static_cast<std::mutex&>(mb).lock();
96+
static_cast<std::mutex&>(mb).unlock();
97+
sleep(10);
98+
}
99+
100+
void two_custom_mutex_bases_tp(MyMutex &m) {
101+
m.lock1();
102+
// expected-note@-1 {{Calling 'MyMutexBase1::lock1'}}
103+
// expected-note@-2 {{Returning from 'MyMutexBase1::lock1'}}
104+
m.unlock2();
105+
sleep(10);
106+
// expected-warning@-1 {{Call to blocking function 'sleep' inside of critical section}}
107+
// expected-note@-2 {{Call to blocking function 'sleep' inside of critical section}}
108+
m.unlock1();
109+
}
110+
111+
void two_custom_mutex_bases_tn(MyMutex &m) {
112+
m.lock1();
113+
m.unlock1();
114+
sleep(10);
115+
}
116+
117+
void two_custom_mutex_bases_casts_tp(MyMutex &m) {
118+
static_cast<MyMutexBase1&>(m).lock();
119+
// expected-note@-1 {{Entering critical section here}}
120+
static_cast<MyMutexBase2&>(m).unlock();
121+
sleep(10);
122+
// expected-warning@-1 {{Call to blocking function 'sleep' inside of critical section}}
123+
// expected-note@-2 {{Call to blocking function 'sleep' inside of critical section}}
124+
static_cast<MyMutexBase1&>(m).unlock();
125+
}
126+
127+
void two_custom_mutex_bases_casts_tn(MyMutex &m) {
128+
static_cast<MyMutexBase1&>(m).lock();
129+
static_cast<MyMutexBase1&>(m).unlock();
130+
sleep(10);
131+
}
132+
133+
struct MutexVirtBase1 : virtual std::mutex {
134+
void lock1() { lock(); }
135+
// expected-note@-1 {{Entering critical section here}}
136+
void unlock1() { unlock(); }
137+
};
138+
139+
struct MutexVirtBase2 : virtual std::mutex {
140+
void lock2() { lock(); }
141+
void unlock2() { unlock(); }
142+
};
143+
144+
struct CombinedVirtMutex : MutexVirtBase1, MutexVirtBase2 {};
145+
146+
void virt_inherited_mutexes_same_base_tn1(CombinedVirtMutex &cvt) {
147+
cvt.lock1();
148+
cvt.unlock1();
149+
sleep(10);
150+
}
151+
152+
void virt_inherited_mutexes_different_bases_tn(CombinedVirtMutex &cvt) {
153+
cvt.lock1();
154+
cvt.unlock2(); // Despite a different name, unlock2 acts on the same mutex as lock1
155+
sleep(10);
156+
}
157+
158+
void virt_inherited_mutexes_different_bases_tp(CombinedVirtMutex &cvt) {
159+
cvt.lock1();
160+
// expected-note@-1 {{Calling 'MutexVirtBase1::lock1'}}
161+
// expected-note@-2 {{Returning from 'MutexVirtBase1::lock1'}}
162+
sleep(10);
163+
// expected-warning@-1 {{Call to blocking function 'sleep' inside of critical section}}
164+
// expected-note@-2 {{Call to blocking function 'sleep' inside of critical section}}
165+
cvt.unlock1();
166+
}
167+
168+
namespace std {
169+
template <class... MutexTypes> struct scoped_lock {
170+
explicit scoped_lock(MutexTypes&... m);
171+
~scoped_lock();
172+
};
173+
template <class MutexType> class scoped_lock<MutexType> {
174+
public:
175+
explicit scoped_lock(MutexType& m) : m(m) { m.lock(); }
176+
~scoped_lock() { m.unlock(); }
177+
private:
178+
MutexType& m;
179+
};
180+
} // namespace std
181+
182+
namespace gh_104241 {
183+
int magic_number;
184+
std::mutex m;
185+
186+
void fixed() {
187+
int current;
188+
for (int items_processed = 0; items_processed < 100; ++items_processed) {
189+
{
190+
std::scoped_lock<std::mutex> guard(m);
191+
current = magic_number;
192+
}
193+
sleep(current); // expected no warning
194+
}
195+
}
196+
} // namespace gh_104241
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
2+
// RUN: %clang_analyze_cc1 \
3+
// RUN: -analyzer-checker=unix.BlockInCriticalSection \
4+
// RUN: -std=c++11 \
5+
// RUN: -analyzer-output text \
6+
// RUN: -verify %s
7+
8+
unsigned int sleep(unsigned int seconds) {return 0;}
9+
namespace std {
10+
namespace __detail {
11+
class __mutex_base {
12+
public:
13+
void lock();
14+
};
15+
} // namespace __detail
16+
17+
class mutex : public __detail::__mutex_base{
18+
public:
19+
void unlock();
20+
bool try_lock();
21+
};
22+
} // namespace std
23+
24+
void gh_99628() {
25+
std::mutex m;
26+
m.lock();
27+
// expected-note@-1 {{Entering critical section here}}
28+
sleep(10);
29+
// expected-warning@-1 {{Call to blocking function 'sleep' inside of critical section}}
30+
// expected-note@-2 {{Call to blocking function 'sleep' inside of critical section}}
31+
m.unlock();
32+
}
33+
34+
void no_false_positive_gh_104241() {
35+
std::mutex m;
36+
m.lock();
37+
// If inheritance not handled properly, this unlock might not match the lock
38+
// above because technically they act on different memory regions:
39+
// __mutex_base and mutex.
40+
m.unlock();
41+
sleep(10); // no-warning
42+
}

clang/test/CXX/drs/cwg29xx.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// RUN: %clang_cc1 -std=c++23 -pedantic-errors -verify=expected %s
77
// RUN: %clang_cc1 -std=c++2c -pedantic-errors -verify=expected %s
88

9-
namespace cwg2917 { // cwg2917: 20 open 2024-07-30
9+
namespace cwg2917 { // cwg2917: 20 review 2024-07-30
1010
template <typename>
1111
class Foo;
1212

@@ -33,7 +33,7 @@ void *operator new(std::size_t, void *p) { return p; }
3333
void* operator new[] (std::size_t, void* p) {return p;}
3434

3535

36-
namespace cwg2922 { // cwg2922: 20 open 2024-07-10
36+
namespace cwg2922 { // cwg2922: 20 tentatively ready 2024-07-10
3737
union U { int a, b; };
3838
constexpr U nondeterministic(bool i) {
3939
if(i) {

clang/test/CodeGen/2005-01-02-ConstantInits.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-globals --global-value-regex "[A-Za-z].*"
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-globals --global-value-regex "@.+"
22
// RUN: %clang_cc1 -triple=x86_64-unknown-linux %s -emit-llvm -o - | FileCheck %s
33

44
// This tests all kinds of hard cases with initializers and
@@ -51,7 +51,7 @@ int foo(int i) { return bar(&Arr[49])+bar(&Arr[i]); }
5151
// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4
5252
// CHECK-NEXT: store ptr @Arr, ptr [[P]], align 8
5353
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8
54-
// CHECK-NEXT: [[INCDEC_PTR:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP0]], i32 1
54+
// CHECK-NEXT: [[INCDEC_PTR:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i32 1
5555
// CHECK-NEXT: store ptr [[INCDEC_PTR]], ptr [[P]], align 8
5656
// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[I_ADDR]], align 4
5757
// CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[TMP1]] to i64

0 commit comments

Comments
 (0)