Skip to content

Commit 0226cb0

Browse files
committed
Merge remote-tracking branch 'origin/main' into vplan-narrow-interleave
2 parents b79c14c + 0d3ba08 commit 0226cb0

File tree

105 files changed

+960
-1791
lines changed

Some content is hidden

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

105 files changed

+960
-1791
lines changed

clang-tools-extra/clang-tidy/modernize/UseStartsEndsWithCheck.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,21 +113,33 @@ void UseStartsEndsWithCheck::registerMatchers(MatchFinder *Finder) {
113113
const auto OnClassWithEndsWithFunction = ClassTypeWithMethod(
114114
"ends_with_fun", "ends_with", "endsWith", "endswith", "EndsWith");
115115

116-
// Case 1: X.find(Y) [!=]= 0 -> starts_with.
116+
// Case 1: X.find(Y, [0], [LEN(Y)]) [!=]= 0 -> starts_with.
117117
const auto FindExpr = cxxMemberCallExpr(
118-
anyOf(argumentCountIs(1), hasArgument(1, ZeroLiteral)),
119118
callee(
120119
cxxMethodDecl(hasName("find"), ofClass(OnClassWithStartsWithFunction))
121120
.bind("find_fun")),
122-
hasArgument(0, expr().bind("needle")));
123-
124-
// Case 2: X.rfind(Y, 0) [!=]= 0 -> starts_with.
121+
hasArgument(0, expr().bind("needle")),
122+
anyOf(
123+
// Detect the expression: X.find(Y);
124+
argumentCountIs(1),
125+
// Detect the expression: X.find(Y, 0);
126+
allOf(argumentCountIs(2), hasArgument(1, ZeroLiteral)),
127+
// Detect the expression: X.find(Y, 0, LEN(Y));
128+
allOf(argumentCountIs(3), hasArgument(1, ZeroLiteral),
129+
hasArgument(2, lengthExprForStringNode("needle")))));
130+
131+
// Case 2: X.rfind(Y, 0, [LEN(Y)]) [!=]= 0 -> starts_with.
125132
const auto RFindExpr = cxxMemberCallExpr(
126-
hasArgument(1, ZeroLiteral),
127133
callee(cxxMethodDecl(hasName("rfind"),
128134
ofClass(OnClassWithStartsWithFunction))
129135
.bind("find_fun")),
130-
hasArgument(0, expr().bind("needle")));
136+
hasArgument(0, expr().bind("needle")),
137+
anyOf(
138+
// Detect the expression: X.rfind(Y, 0);
139+
allOf(argumentCountIs(2), hasArgument(1, ZeroLiteral)),
140+
// Detect the expression: X.rfind(Y, 0, LEN(Y));
141+
allOf(argumentCountIs(3), hasArgument(1, ZeroLiteral),
142+
hasArgument(2, lengthExprForStringNode("needle")))));
131143

132144
// Case 3: X.compare(0, LEN(Y), Y) [!=]= 0 -> starts_with.
133145
const auto CompareExpr = cxxMemberCallExpr(

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@ Changes in existing checks
175175
<clang-tidy/checks/modernize/use-ranges>` check by updating suppress
176176
warnings logic for ``nullptr`` in ``std::find``.
177177

178+
- Improved :doc:`modernize-use-starts-ends-with
179+
<clang-tidy/checks/modernize/use-starts-ends-with>` check by adding more
180+
matched scenarios of ``find`` and ``rfind`` methods and fixing false
181+
positives when those methods were called with 3 arguments.
182+
178183
- Improved :doc:`modernize-use-std-numbers
179184
<clang-tidy/checks/modernize/use-std-numbers>` check to support math
180185
functions of different precisions.

clang-tools-extra/docs/clang-tidy/checks/modernize/use-starts-ends-with.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ Covered scenarios:
1313
Expression Replacement
1414
---------------------------------------------------- ---------------------
1515
``u.find(v) == 0`` ``u.starts_with(v)``
16+
``u.find(v, 0) == 0`` ``u.starts_with(v)``
17+
``u.find(v, 0, v.size()) == 0`` ``u.starts_with(v)``
1618
``u.rfind(v, 0) != 0`` ``!u.starts_with(v)``
19+
``u.rfind(v, 0, v.size()) != 0`` ``!u.starts_with(v)``
1720
``u.compare(0, v.size(), v) == 0`` ``u.starts_with(v)``
1821
``u.substr(0, v.size()) == v`` ``u.starts_with(v)``
1922
``v != u.substr(0, v.size())`` ``!u.starts_with(v)``

clang-tools-extra/test/clang-tidy/checkers/modernize/use-starts-ends-with.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,42 @@ void test(std::string s, std::string_view sv, sub_string ss, sub_sub_string sss,
236236
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
237237
// CHECK-FIXES: s.ends_with(suffix);
238238

239+
s.find("a", 0) == 0;
240+
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
241+
// CHECK-FIXES: s.starts_with("a");
242+
243+
s.find(s, ZERO) == 0;
244+
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
245+
// CHECK-FIXES: s.starts_with(s);
246+
247+
s.find(s, 0) == ZERO;
248+
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
249+
// CHECK-FIXES: s.starts_with(s);
250+
251+
s.find("aaa", 0, 3) == 0;
252+
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
253+
// CHECK-FIXES: s.starts_with("aaa");
254+
255+
s.find("aaa", ZERO, 3) == 0;
256+
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
257+
// CHECK-FIXES: s.starts_with("aaa");
258+
259+
s.find("aaa", ZERO, strlen(("aaa"))) == ZERO;
260+
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
261+
// CHECK-FIXES: s.starts_with("aaa");
262+
263+
s.rfind("aaa", 0, 3) != 0;
264+
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
265+
// CHECK-FIXES: !s.starts_with("aaa");
266+
267+
s.rfind("aaa", ZERO, 3) != 0;
268+
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
269+
// CHECK-FIXES: !s.starts_with("aaa");
270+
271+
s.rfind("aaa", ZERO, strlen(("aaa"))) == ZERO;
272+
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
273+
// CHECK-FIXES: s.starts_with("aaa");
274+
239275
struct S {
240276
std::string s;
241277
} t;
@@ -261,6 +297,12 @@ void test(std::string s, std::string_view sv, sub_string ss, sub_sub_string sss,
261297

262298
#define STRING s
263299
if (0 == STRING.find("ala")) { /* do something */}
300+
301+
// Cases when literal-size and size parameters are different are not being matched.
302+
s.find("aaa", 0, 2) == 0;
303+
s.find("aaa", 0, strlen("aa")) == 0;
304+
s.rfind("aaa", 0, 2) == 0;
305+
s.rfind("aaa", 0, strlen("aa")) == 0;
264306
}
265307

266308
void test_substr() {

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1005,7 +1005,9 @@ DEF_TRAVERSE_TYPE(RValueReferenceType,
10051005

10061006
DEF_TRAVERSE_TYPE(MemberPointerType, {
10071007
TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
1008-
TRY_TO(TraverseDecl(T->getMostRecentCXXRecordDecl()));
1008+
if (T->isSugared())
1009+
TRY_TO(TraverseType(
1010+
QualType(T->getMostRecentCXXRecordDecl()->getTypeForDecl(), 0)));
10091011
TRY_TO(TraverseType(T->getPointeeType()));
10101012
})
10111013

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12620,6 +12620,10 @@ class Sema final : public SemaBase {
1262012620
void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
1262112621
bool OnlyDeduced, unsigned Depth,
1262212622
llvm::SmallBitVector &Used);
12623+
12624+
void MarkUsedTemplateParameters(ArrayRef<TemplateArgument> TemplateArgs,
12625+
unsigned Depth, llvm::SmallBitVector &Used);
12626+
1262312627
void
1262412628
MarkDeducedTemplateParameters(const FunctionTemplateDecl *FunctionTemplate,
1262512629
llvm::SmallBitVector &Deduced) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ class ExplodedNodeSet {
485485
if (empty())
486486
Impl = S.Impl;
487487
else
488-
Impl.insert(S.begin(), S.end());
488+
Impl.insert_range(S);
489489
}
490490

491491
iterator begin() { return Impl.begin(); }

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3356,7 +3356,8 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
33563356
if (E->isArray())
33573357
Desc = nullptr; // We're not going to use it in this case.
33583358
else
3359-
Desc = P.createDescriptor(E, *ElemT, Descriptor::InlineDescMD,
3359+
Desc = P.createDescriptor(E, *ElemT, /*SourceTy=*/nullptr,
3360+
Descriptor::InlineDescMD,
33603361
/*IsConst=*/false, /*IsTemporary=*/false,
33613362
/*IsMutable=*/false);
33623363
} else {
@@ -3517,7 +3518,7 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
35173518
// ++Iter;
35183519
if (!this->emitGetPtrLocal(Iter, E))
35193520
return false;
3520-
if (!this->emitIncPop(SizeT, E))
3521+
if (!this->emitIncPop(SizeT, false, E))
35213522
return false;
35223523

35233524
if (!this->jump(StartLabel))
@@ -4260,8 +4261,8 @@ unsigned Compiler<Emitter>::allocateLocalPrimitive(
42604261
// FIXME: There are cases where Src.is<Expr*>() is wrong, e.g.
42614262
// (int){12} in C. Consider using Expr::isTemporaryObject() instead
42624263
// or isa<MaterializeTemporaryExpr>().
4263-
Descriptor *D = P.createDescriptor(Src, Ty, Descriptor::InlineDescMD, IsConst,
4264-
isa<const Expr *>(Src));
4264+
Descriptor *D = P.createDescriptor(Src, Ty, nullptr, Descriptor::InlineDescMD,
4265+
IsConst, isa<const Expr *>(Src));
42654266
Scope::Local Local = this->createLocal(D);
42664267
if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>()))
42674268
Locals.insert({VD, Local});
@@ -5956,7 +5957,8 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
59565957
: this->emitIncf(getFPOptions(E), E);
59575958
}
59585959

5959-
return DiscardResult ? this->emitIncPop(*T, E) : this->emitInc(*T, E);
5960+
return DiscardResult ? this->emitIncPop(*T, E->canOverflow(), E)
5961+
: this->emitInc(*T, E->canOverflow(), E);
59605962
}
59615963
case UO_PostDec: { // x--
59625964
if (!Ctx.getLangOpts().CPlusPlus14)
@@ -5979,7 +5981,8 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
59795981
: this->emitDecf(getFPOptions(E), E);
59805982
}
59815983

5982-
return DiscardResult ? this->emitDecPop(*T, E) : this->emitDec(*T, E);
5984+
return DiscardResult ? this->emitDecPop(*T, E->canOverflow(), E)
5985+
: this->emitDec(*T, E->canOverflow(), E);
59835986
}
59845987
case UO_PreInc: { // ++x
59855988
if (!Ctx.getLangOpts().CPlusPlus14)
@@ -6004,7 +6007,7 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
60046007
if (DiscardResult) {
60056008
if (T == PT_Float)
60066009
return this->emitIncfPop(getFPOptions(E), E);
6007-
return this->emitIncPop(*T, E);
6010+
return this->emitIncPop(*T, E->canOverflow(), E);
60086011
}
60096012

60106013
if (T == PT_Float) {
@@ -6019,13 +6022,7 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
60196022
return false;
60206023
} else {
60216024
assert(isIntegralType(*T));
6022-
if (!this->emitLoad(*T, E))
6023-
return false;
6024-
if (!this->emitConst(1, E))
6025-
return false;
6026-
if (!this->emitAdd(*T, E))
6027-
return false;
6028-
if (!this->emitStore(*T, E))
6025+
if (!this->emitPreInc(*T, E->canOverflow(), E))
60296026
return false;
60306027
}
60316028
return E->isGLValue() || this->emitLoadPop(*T, E);
@@ -6053,7 +6050,7 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
60536050
if (DiscardResult) {
60546051
if (T == PT_Float)
60556052
return this->emitDecfPop(getFPOptions(E), E);
6056-
return this->emitDecPop(*T, E);
6053+
return this->emitDecPop(*T, E->canOverflow(), E);
60576054
}
60586055

60596056
if (T == PT_Float) {
@@ -6068,13 +6065,7 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
60686065
return false;
60696066
} else {
60706067
assert(isIntegralType(*T));
6071-
if (!this->emitLoad(*T, E))
6072-
return false;
6073-
if (!this->emitConst(1, E))
6074-
return false;
6075-
if (!this->emitSub(*T, E))
6076-
return false;
6077-
if (!this->emitStore(*T, E))
6068+
if (!this->emitPreDec(*T, E->canOverflow(), E))
60786069
return false;
60796070
}
60806071
return E->isGLValue() || this->emitLoadPop(*T, E);

clang/lib/AST/ByteCode/Descriptor.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -329,9 +329,10 @@ static BlockMoveFn getMoveArrayPrim(PrimType Type) {
329329
}
330330

331331
/// Primitives.
332-
Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD,
333-
bool IsConst, bool IsTemporary, bool IsMutable)
334-
: Source(D), ElemSize(primSize(Type)), Size(ElemSize),
332+
Descriptor::Descriptor(const DeclTy &D, const Type *SourceTy, PrimType Type,
333+
MetadataSize MD, bool IsConst, bool IsTemporary,
334+
bool IsMutable)
335+
: Source(D), SourceType(SourceTy), ElemSize(primSize(Type)), Size(ElemSize),
335336
MDSize(MD.value_or(0)), AllocSize(align(Size + MDSize)), PrimT(Type),
336337
IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary),
337338
CtorFn(getCtorPrim(Type)), DtorFn(getDtorPrim(Type)),

clang/lib/AST/ByteCode/Descriptor.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,8 @@ struct Descriptor final {
175175
const BlockMoveFn MoveFn = nullptr;
176176

177177
/// Allocates a descriptor for a primitive.
178-
Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, bool IsConst,
179-
bool IsTemporary, bool IsMutable);
178+
Descriptor(const DeclTy &D, const Type *SourceTy, PrimType Type,
179+
MetadataSize MD, bool IsConst, bool IsTemporary, bool IsMutable);
180180

181181
/// Allocates a descriptor for an array of primitives.
182182
Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, size_t NumElems,

clang/lib/AST/ByteCode/Interp.h

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,8 @@ enum class IncDecOp {
765765
};
766766

767767
template <typename T, IncDecOp Op, PushVal DoPush>
768-
bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
768+
bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
769+
bool CanOverflow) {
769770
assert(!Ptr.isDummy());
770771

771772
if constexpr (std::is_same_v<T, Boolean>) {
@@ -780,16 +781,17 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
780781
S.Stk.push<T>(Value);
781782

782783
if constexpr (Op == IncDecOp::Inc) {
783-
if (!T::increment(Value, &Result)) {
784+
if (!T::increment(Value, &Result) || !CanOverflow) {
784785
Ptr.deref<T>() = Result;
785786
return true;
786787
}
787788
} else {
788-
if (!T::decrement(Value, &Result)) {
789+
if (!T::decrement(Value, &Result) || !CanOverflow) {
789790
Ptr.deref<T>() = Result;
790791
return true;
791792
}
792793
}
794+
assert(CanOverflow);
793795

794796
// Something went wrong with the previous operation. Compute the
795797
// result with another bit of precision.
@@ -812,7 +814,6 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
812814
<< Trunc << Type << E->getSourceRange();
813815
return true;
814816
}
815-
816817
return handleOverflow(S, OpPC, APResult);
817818
}
818819

@@ -821,49 +822,69 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
821822
/// 3) Writes the value increased by one back to the pointer
822823
/// 4) Pushes the original (pre-inc) value on the stack.
823824
template <PrimType Name, class T = typename PrimConv<Name>::T>
824-
bool Inc(InterpState &S, CodePtr OpPC) {
825+
bool Inc(InterpState &S, CodePtr OpPC, bool CanOverflow) {
825826
const Pointer &Ptr = S.Stk.pop<Pointer>();
826827
if (!CheckLoad(S, OpPC, Ptr, AK_Increment))
827828
return false;
828829

829-
return IncDecHelper<T, IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr);
830+
return IncDecHelper<T, IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr,
831+
CanOverflow);
830832
}
831833

832834
/// 1) Pops a pointer from the stack
833835
/// 2) Load the value from the pointer
834836
/// 3) Writes the value increased by one back to the pointer
835837
template <PrimType Name, class T = typename PrimConv<Name>::T>
836-
bool IncPop(InterpState &S, CodePtr OpPC) {
838+
bool IncPop(InterpState &S, CodePtr OpPC, bool CanOverflow) {
837839
const Pointer &Ptr = S.Stk.pop<Pointer>();
838840
if (!CheckLoad(S, OpPC, Ptr, AK_Increment))
839841
return false;
840842

841-
return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr);
843+
return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, CanOverflow);
844+
}
845+
846+
template <PrimType Name, class T = typename PrimConv<Name>::T>
847+
bool PreInc(InterpState &S, CodePtr OpPC, bool CanOverflow) {
848+
const Pointer &Ptr = S.Stk.peek<Pointer>();
849+
if (!CheckLoad(S, OpPC, Ptr, AK_Increment))
850+
return false;
851+
852+
return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, CanOverflow);
842853
}
843854

844855
/// 1) Pops a pointer from the stack
845856
/// 2) Load the value from the pointer
846857
/// 3) Writes the value decreased by one back to the pointer
847858
/// 4) Pushes the original (pre-dec) value on the stack.
848859
template <PrimType Name, class T = typename PrimConv<Name>::T>
849-
bool Dec(InterpState &S, CodePtr OpPC) {
860+
bool Dec(InterpState &S, CodePtr OpPC, bool CanOverflow) {
850861
const Pointer &Ptr = S.Stk.pop<Pointer>();
851862
if (!CheckLoad(S, OpPC, Ptr, AK_Decrement))
852863
return false;
853864

854-
return IncDecHelper<T, IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr);
865+
return IncDecHelper<T, IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr,
866+
CanOverflow);
855867
}
856868

857869
/// 1) Pops a pointer from the stack
858870
/// 2) Load the value from the pointer
859871
/// 3) Writes the value decreased by one back to the pointer
860872
template <PrimType Name, class T = typename PrimConv<Name>::T>
861-
bool DecPop(InterpState &S, CodePtr OpPC) {
873+
bool DecPop(InterpState &S, CodePtr OpPC, bool CanOverflow) {
862874
const Pointer &Ptr = S.Stk.pop<Pointer>();
863875
if (!CheckLoad(S, OpPC, Ptr, AK_Decrement))
864876
return false;
865877

866-
return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr);
878+
return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, CanOverflow);
879+
}
880+
881+
template <PrimType Name, class T = typename PrimConv<Name>::T>
882+
bool PreDec(InterpState &S, CodePtr OpPC, bool CanOverflow) {
883+
const Pointer &Ptr = S.Stk.peek<Pointer>();
884+
if (!CheckLoad(S, OpPC, Ptr, AK_Decrement))
885+
return false;
886+
887+
return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, CanOverflow);
867888
}
868889

869890
template <IncDecOp Op, PushVal DoPush>

0 commit comments

Comments
 (0)