Skip to content

Commit ccd2249

Browse files
committed
Merge from 'main' to 'sycl-web' (27 commits)
CONFLICT (content): Merge conflict in llvm/include/llvm/LinkAllPasses.h
2 parents 1dfbaa8 + f992ae4 commit ccd2249

File tree

118 files changed

+2590
-837
lines changed

Some content is hidden

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

118 files changed

+2590
-837
lines changed

clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,28 @@ void UnhandledSelfAssignmentCheck::registerMatchers(MatchFinder *Finder) {
6969
cxxMethodDecl(unless(hasDescendant(cxxMemberCallExpr(callee(cxxMethodDecl(
7070
hasName("operator="), ofClass(equalsBoundNode("class"))))))));
7171

72+
// Checking that some kind of constructor is called and followed by a `swap`:
73+
// T& operator=(const T& other) {
74+
// T tmp{this->internal_data(), some, other, args};
75+
// swap(tmp);
76+
// return *this;
77+
// }
78+
const auto HasCopyAndSwap = cxxMethodDecl(
79+
ofClass(cxxRecordDecl()),
80+
hasBody(compoundStmt(
81+
hasDescendant(
82+
varDecl(hasType(cxxRecordDecl(equalsBoundNode("class"))))
83+
.bind("tmp_var")),
84+
hasDescendant(stmt(anyOf(
85+
cxxMemberCallExpr(hasArgument(
86+
0, declRefExpr(to(varDecl(equalsBoundNode("tmp_var")))))),
87+
callExpr(
88+
callee(functionDecl(hasName("swap"))), argumentCountIs(2),
89+
hasAnyArgument(
90+
declRefExpr(to(varDecl(equalsBoundNode("tmp_var"))))),
91+
hasAnyArgument(unaryOperator(has(cxxThisExpr()),
92+
hasOperatorName("*"))))))))));
93+
7294
DeclarationMatcher AdditionalMatcher = cxxMethodDecl();
7395
if (WarnOnlyIfThisHasSuspiciousField) {
7496
// Matcher for standard smart pointers.
@@ -89,14 +111,14 @@ void UnhandledSelfAssignmentCheck::registerMatchers(MatchFinder *Finder) {
89111
hasType(arrayType())))))));
90112
}
91113

92-
Finder->addMatcher(cxxMethodDecl(ofClass(cxxRecordDecl().bind("class")),
93-
isCopyAssignmentOperator(), IsUserDefined,
94-
HasReferenceParam, HasNoSelfCheck,
95-
unless(HasNonTemplateSelfCopy),
96-
unless(HasTemplateSelfCopy),
97-
HasNoNestedSelfAssign, AdditionalMatcher)
98-
.bind("copyAssignmentOperator"),
99-
this);
114+
Finder->addMatcher(
115+
cxxMethodDecl(
116+
ofClass(cxxRecordDecl().bind("class")), isCopyAssignmentOperator(),
117+
IsUserDefined, HasReferenceParam, HasNoSelfCheck,
118+
unless(HasNonTemplateSelfCopy), unless(HasTemplateSelfCopy),
119+
unless(HasCopyAndSwap), HasNoNestedSelfAssign, AdditionalMatcher)
120+
.bind("copyAssignmentOperator"),
121+
this);
100122
}
101123

102124
void UnhandledSelfAssignmentCheck::check(

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ Changes in existing checks
114114
<clang-tidy/checks/bugprone/infinite-loop>` check by adding detection for
115115
variables introduced by structured bindings.
116116

117+
- Improved :doc:`bugprone-unhandled-self-assignment
118+
<clang-tidy/checks/bugprone/unhandled-self-assignment>` check by adding
119+
an additional matcher that generalizes the copy-and-swap idiom pattern
120+
detection.
121+
117122
Removed checks
118123
^^^^^^^^^^^^^^
119124

clang-tools-extra/test/clang-tidy/checkers/bugprone/unhandled-self-assignment.cpp

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ template <class T>
2828
class auto_ptr {
2929
};
3030

31+
namespace pmr {
32+
template <typename TYPE = void>
33+
class allocator {};
34+
}
35+
36+
struct allocator_arg_t {} allocator_arg;
37+
3138
} // namespace std
3239

3340
void assert(int expression){};
@@ -229,6 +236,122 @@ bool operator!=(Foo2 &, Foo2 &) {
229236
};
230237
}
231238

239+
// Missing call to `swap` function
240+
class AllocatorAwareClassNoSwap {
241+
// pointer member to trigger bugprone-unhandled-self-assignment
242+
void *foo = nullptr;
243+
244+
public:
245+
using allocator_type = std::pmr::allocator<>;
246+
247+
AllocatorAwareClassNoSwap(const AllocatorAwareClassNoSwap& other) {
248+
}
249+
250+
AllocatorAwareClassNoSwap(const AllocatorAwareClassNoSwap& other, const allocator_type& alloc) {
251+
}
252+
253+
AllocatorAwareClassNoSwap& operator=(const AllocatorAwareClassNoSwap& other) {
254+
// CHECK-MESSAGES: [[@LINE-1]]:32: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
255+
AllocatorAwareClassNoSwap tmp(other, get_allocator());
256+
return *this;
257+
}
258+
259+
allocator_type get_allocator() const {
260+
return allocator_type();
261+
}
262+
};
263+
264+
// "Wrong" type is passed to member `swap` function
265+
class AllocatorAwareClassSwapWrongArgType {
266+
// pointer member to trigger bugprone-unhandled-self-assignment
267+
void *foo = nullptr;
268+
269+
public:
270+
using allocator_type = std::pmr::allocator<>;
271+
272+
AllocatorAwareClassSwapWrongArgType(const AllocatorAwareClassSwapWrongArgType& other) {
273+
}
274+
275+
AllocatorAwareClassSwapWrongArgType(const AllocatorAwareClassSwapWrongArgType& other, const allocator_type& alloc) {
276+
}
277+
278+
AllocatorAwareClassSwapWrongArgType& operator=(const AllocatorAwareClassSwapWrongArgType& other) {
279+
// CHECK-MESSAGES: [[@LINE-1]]:42: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
280+
int tmp = 0;
281+
swap(tmp);
282+
283+
return *this;
284+
}
285+
286+
void swap(int&) noexcept {
287+
}
288+
289+
allocator_type get_allocator() const {
290+
return allocator_type();
291+
}
292+
};
293+
294+
295+
// Making ADL `swap` call but with wrong argument type
296+
class AllocatorAwareClassAdlSwapWrongArgType {
297+
// pointer member to trigger bugprone-unhandled-self-assignment
298+
void *foo = nullptr;
299+
300+
public:
301+
using allocator_type = std::pmr::allocator<>;
302+
303+
AllocatorAwareClassAdlSwapWrongArgType(const AllocatorAwareClassAdlSwapWrongArgType& other) {
304+
}
305+
306+
AllocatorAwareClassAdlSwapWrongArgType(const AllocatorAwareClassAdlSwapWrongArgType& other, const allocator_type& alloc) {
307+
}
308+
309+
AllocatorAwareClassAdlSwapWrongArgType& operator=(const AllocatorAwareClassAdlSwapWrongArgType& other) {
310+
// CHECK-MESSAGES: [[@LINE-1]]:45: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
311+
int tmp = 0;
312+
swap(*this, tmp);
313+
314+
return *this;
315+
}
316+
317+
allocator_type get_allocator() const {
318+
return allocator_type();
319+
}
320+
321+
friend void swap(AllocatorAwareClassAdlSwapWrongArgType&, int&) {
322+
}
323+
};
324+
325+
// `this` isn't passed to `swap`
326+
class AllocatorAwareClassAdlSwapWrongArgs {
327+
// pointer member to trigger bugprone-unhandled-self-assignment
328+
void *foo = nullptr;
329+
330+
public:
331+
using allocator_type = std::pmr::allocator<>;
332+
333+
AllocatorAwareClassAdlSwapWrongArgs(const AllocatorAwareClassAdlSwapWrongArgs& other) {
334+
}
335+
336+
AllocatorAwareClassAdlSwapWrongArgs(const AllocatorAwareClassAdlSwapWrongArgs& other, const allocator_type& alloc) {
337+
}
338+
339+
AllocatorAwareClassAdlSwapWrongArgs& operator=(const AllocatorAwareClassAdlSwapWrongArgs& other) {
340+
// CHECK-MESSAGES: [[@LINE-1]]:42: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
341+
AllocatorAwareClassAdlSwapWrongArgs tmp1(other, get_allocator());
342+
AllocatorAwareClassAdlSwapWrongArgs tmp2(*this, get_allocator());
343+
swap(tmp1, tmp2);
344+
return *this;
345+
}
346+
347+
allocator_type get_allocator() const {
348+
return allocator_type();
349+
}
350+
351+
friend void swap(AllocatorAwareClassAdlSwapWrongArgs&, AllocatorAwareClassAdlSwapWrongArgs&) {
352+
}
353+
};
354+
232355
///////////////////////////////////////////////////////////////////
233356
/// Test cases correctly ignored by the check.
234357

@@ -540,6 +663,89 @@ class NotACopyAssignmentOperator {
540663
Uy *getUy() const { return Ptr2; }
541664
};
542665

666+
// Support "extended" copy/move constructors
667+
class AllocatorAwareClass {
668+
// pointer member to trigger bugprone-unhandled-self-assignment
669+
void *foo = nullptr;
670+
671+
public:
672+
using allocator_type = std::pmr::allocator<>;
673+
674+
AllocatorAwareClass(const AllocatorAwareClass& other) {
675+
}
676+
677+
AllocatorAwareClass(const AllocatorAwareClass& other, const allocator_type& alloc) {
678+
}
679+
680+
AllocatorAwareClass& operator=(const AllocatorAwareClass& other) {
681+
AllocatorAwareClass tmp(other, get_allocator());
682+
swap(tmp);
683+
return *this;
684+
}
685+
686+
void swap(AllocatorAwareClass& other) noexcept {
687+
}
688+
689+
allocator_type get_allocator() const {
690+
return allocator_type();
691+
}
692+
};
693+
694+
// Support "extended" copy/move constructors + std::swap
695+
class AllocatorAwareClassStdSwap {
696+
// pointer member to trigger bugprone-unhandled-self-assignment
697+
void *foo = nullptr;
698+
699+
public:
700+
using allocator_type = std::pmr::allocator<>;
701+
702+
AllocatorAwareClassStdSwap(const AllocatorAwareClassStdSwap& other) {
703+
}
704+
705+
AllocatorAwareClassStdSwap(const AllocatorAwareClassStdSwap& other, const allocator_type& alloc) {
706+
}
707+
708+
AllocatorAwareClassStdSwap& operator=(const AllocatorAwareClassStdSwap& other) {
709+
using std::swap;
710+
711+
AllocatorAwareClassStdSwap tmp(other, get_allocator());
712+
swap(*this, tmp);
713+
return *this;
714+
}
715+
716+
allocator_type get_allocator() const {
717+
return allocator_type();
718+
}
719+
};
720+
721+
// Support "extended" copy/move constructors + ADL swap
722+
class AllocatorAwareClassAdlSwap {
723+
// pointer member to trigger bugprone-unhandled-self-assignment
724+
void *foo = nullptr;
725+
726+
public:
727+
using allocator_type = std::pmr::allocator<>;
728+
729+
AllocatorAwareClassAdlSwap(const AllocatorAwareClassAdlSwap& other) {
730+
}
731+
732+
AllocatorAwareClassAdlSwap(const AllocatorAwareClassAdlSwap& other, const allocator_type& alloc) {
733+
}
734+
735+
AllocatorAwareClassAdlSwap& operator=(const AllocatorAwareClassAdlSwap& other) {
736+
AllocatorAwareClassAdlSwap tmp(other, get_allocator());
737+
swap(*this, tmp);
738+
return *this;
739+
}
740+
741+
allocator_type get_allocator() const {
742+
return allocator_type();
743+
}
744+
745+
friend void swap(AllocatorAwareClassAdlSwap&, AllocatorAwareClassAdlSwap&) {
746+
}
747+
};
748+
543749
///////////////////////////////////////////////////////////////////
544750
/// Test cases which should be caught by the check.
545751

clang/include/clang/Analysis/Analyses/LifetimeSafety.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ namespace internal {
3333
class Fact;
3434
class FactManager;
3535
class LoanPropagationAnalysis;
36+
class ExpiredLoansAnalysis;
3637
struct LifetimeFactory;
3738

3839
/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
@@ -52,6 +53,10 @@ template <typename Tag> struct ID {
5253
IDBuilder.AddInteger(Value);
5354
}
5455
};
56+
template <typename Tag>
57+
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID<Tag> ID) {
58+
return OS << ID.Value;
59+
}
5560

5661
using LoanID = ID<struct LoanTag>;
5762
using OriginID = ID<struct OriginTag>;
@@ -81,6 +86,9 @@ class LifetimeSafetyAnalysis {
8186
/// Returns the set of loans an origin holds at a specific program point.
8287
LoanSet getLoansAtPoint(OriginID OID, ProgramPoint PP) const;
8388

89+
/// Returns the set of loans that have expired at a specific program point.
90+
LoanSet getExpiredLoansAtPoint(ProgramPoint PP) const;
91+
8492
/// Finds the OriginID for a given declaration.
8593
/// Returns a null optional if not found.
8694
std::optional<OriginID> getOriginIDForDecl(const ValueDecl *D) const;
@@ -105,6 +113,7 @@ class LifetimeSafetyAnalysis {
105113
std::unique_ptr<LifetimeFactory> Factory;
106114
std::unique_ptr<FactManager> FactMgr;
107115
std::unique_ptr<LoanPropagationAnalysis> LoanPropagation;
116+
std::unique_ptr<ExpiredLoansAnalysis> ExpiredLoans;
108117
};
109118
} // namespace internal
110119
} // namespace clang::lifetimes

clang/include/clang/Basic/TargetInfo.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,8 +1551,8 @@ class TargetInfo : public TransferrableTargetInfo,
15511551

15521552
// Return the target-specific priority for features/cpus/vendors so
15531553
// that they can be properly sorted for checking.
1554-
virtual uint64_t getFMVPriority(ArrayRef<StringRef> Features) const {
1555-
return 0;
1554+
virtual llvm::APInt getFMVPriority(ArrayRef<StringRef> Features) const {
1555+
return llvm::APInt::getZero(32);
15561556
}
15571557

15581558
// Validate the contents of the __builtin_cpu_is(const char*)

0 commit comments

Comments
 (0)