Skip to content

Commit a1d1633

Browse files
committed
merge main into amd-staging
Change-Id: I20734face33f8ae646677c81f4b292d101edc48d
2 parents 51f90b7 + 643c383 commit a1d1633

File tree

102 files changed

+1968
-237
lines changed

Some content is hidden

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

102 files changed

+1968
-237
lines changed

clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,43 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "StringCompareCheck.h"
10-
#include "../utils/FixItHintUtils.h"
10+
#include "../utils/OptionsUtils.h"
1111
#include "clang/AST/ASTContext.h"
1212
#include "clang/ASTMatchers/ASTMatchFinder.h"
13+
#include "clang/ASTMatchers/ASTMatchers.h"
1314
#include "clang/Tooling/FixIt.h"
15+
#include "llvm/ADT/StringRef.h"
1416

1517
using namespace clang::ast_matchers;
18+
namespace optutils = clang::tidy::utils::options;
1619

1720
namespace clang::tidy::readability {
1821

1922
static const StringRef CompareMessage = "do not use 'compare' to test equality "
2023
"of strings; use the string equality "
2124
"operator instead";
2225

26+
static const StringRef DefaultStringLikeClasses = "::std::basic_string;"
27+
"::std::basic_string_view";
28+
29+
StringCompareCheck::StringCompareCheck(StringRef Name,
30+
ClangTidyContext *Context)
31+
: ClangTidyCheck(Name, Context),
32+
StringLikeClasses(optutils::parseStringList(
33+
Options.get("StringLikeClasses", DefaultStringLikeClasses))) {}
34+
35+
void StringCompareCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
36+
Options.store(Opts, "StringLikeClasses",
37+
optutils::serializeStringList(StringLikeClasses));
38+
}
39+
2340
void StringCompareCheck::registerMatchers(MatchFinder *Finder) {
41+
if (StringLikeClasses.empty()) {
42+
return;
43+
}
2444
const auto StrCompare = cxxMemberCallExpr(
25-
callee(cxxMethodDecl(hasName("compare"),
26-
ofClass(classTemplateSpecializationDecl(
27-
hasName("::std::basic_string"))))),
45+
callee(cxxMethodDecl(hasName("compare"), ofClass(cxxRecordDecl(hasAnyName(
46+
StringLikeClasses))))),
2847
hasArgument(0, expr().bind("str2")), argumentCountIs(1),
2948
callee(memberExpr().bind("str1")));
3049

clang-tools-extra/clang-tidy/readability/StringCompareCheck.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STRINGCOMPARECHECK_H
1111

1212
#include "../ClangTidyCheck.h"
13+
#include <vector>
1314

1415
namespace clang::tidy::readability {
1516

@@ -20,13 +21,18 @@ namespace clang::tidy::readability {
2021
/// http://clang.llvm.org/extra/clang-tidy/checks/readability/string-compare.html
2122
class StringCompareCheck : public ClangTidyCheck {
2223
public:
23-
StringCompareCheck(StringRef Name, ClangTidyContext *Context)
24-
: ClangTidyCheck(Name, Context) {}
24+
StringCompareCheck(StringRef Name, ClangTidyContext *Context);
25+
2526
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
2627
return LangOpts.CPlusPlus;
2728
}
29+
2830
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
2931
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
32+
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
33+
34+
private:
35+
const std::vector<StringRef> StringLikeClasses;
3036
};
3137

3238
} // namespace clang::tidy::readability

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,11 @@ Changes in existing checks
362362
check by resolving fix-it overlaps in template code by disregarding implicit
363363
instances.
364364

365+
- Improved :doc:`readability-string-compare
366+
<clang-tidy/checks/readability/string-compare>` check to also detect
367+
usages of ``std::string_view::compare``. Added a `StringLikeClasses` option
368+
to detect usages of ``compare`` method in custom string-like classes.
369+
365370
Removed checks
366371
^^^^^^^^^^^^^^
367372

clang-tools-extra/docs/clang-tidy/checks/readability/string-compare.rst

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ recommended to avoid the risk of incorrect interpretation of the return value
1414
and to simplify the code. The string equality and inequality operators can
1515
also be faster than the ``compare`` method due to early termination.
1616

17-
Examples:
17+
Example
18+
-------
1819

1920
.. code-block:: c++
2021

22+
// The same rules apply to std::string_view.
2123
std::string str1{"a"};
2224
std::string str2{"b"};
2325

@@ -50,5 +52,36 @@ Examples:
5052
}
5153

5254
The above code examples show the list of if-statements that this check will
53-
give a warning for. All of them uses ``compare`` to check if equality or
55+
give a warning for. All of them use ``compare`` to check equality or
5456
inequality of two strings instead of using the correct operators.
57+
58+
Options
59+
-------
60+
61+
.. option:: StringLikeClasses
62+
63+
A string containing semicolon-separated names of string-like classes.
64+
By default contains only ``::std::basic_string``
65+
and ``::std::basic_string_view``. If a class from this list has
66+
a ``compare`` method similar to that of ``std::string``, it will be checked
67+
in the same way.
68+
69+
Example
70+
^^^^^^^
71+
72+
.. code-block:: c++
73+
74+
struct CustomString {
75+
public:
76+
int compare (const CustomString& other) const;
77+
}
78+
79+
CustomString str1;
80+
CustomString str2;
81+
82+
// use str1 != str2 instead.
83+
if (str1.compare(str2)) {
84+
}
85+
86+
If `StringLikeClasses` contains ``CustomString``, the check will suggest
87+
replacing ``compare`` with equality operator.

clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ struct basic_string_view {
108108
constexpr bool starts_with(C ch) const noexcept;
109109
constexpr bool starts_with(const C* s) const;
110110

111+
constexpr int compare(basic_string_view sv) const noexcept;
112+
111113
static constexpr size_t npos = -1;
112114
};
113115

@@ -132,6 +134,14 @@ bool operator==(const std::wstring&, const std::wstring&);
132134
bool operator==(const std::wstring&, const wchar_t*);
133135
bool operator==(const wchar_t*, const std::wstring&);
134136

137+
bool operator==(const std::string_view&, const std::string_view&);
138+
bool operator==(const std::string_view&, const char*);
139+
bool operator==(const char*, const std::string_view&);
140+
141+
bool operator!=(const std::string_view&, const std::string_view&);
142+
bool operator!=(const std::string_view&, const char*);
143+
bool operator!=(const char*, const std::string_view&);
144+
135145
size_t strlen(const char* str);
136146
}
137147

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %check_clang_tidy %s readability-string-compare %t -- -config='{CheckOptions: {readability-string-compare.StringLikeClasses: "CustomStringTemplateBase;CustomStringNonTemplateBase"}}' -- -isystem %clang_tidy_headers
2+
#include <string>
3+
4+
struct CustomStringNonTemplateBase {
5+
int compare(const CustomStringNonTemplateBase& Other) const {
6+
return 123; // value is not important for check
7+
}
8+
};
9+
10+
template <typename T>
11+
struct CustomStringTemplateBase {
12+
int compare(const CustomStringTemplateBase& Other) const {
13+
return 123;
14+
}
15+
};
16+
17+
struct CustomString1 : CustomStringNonTemplateBase {};
18+
struct CustomString2 : CustomStringTemplateBase<char> {};
19+
20+
void CustomStringClasses() {
21+
std::string_view sv1("a");
22+
std::string_view sv2("b");
23+
if (sv1.compare(sv2)) { // No warning - if a std class is not listed in StringLikeClasses, it won't be checked.
24+
}
25+
26+
CustomString1 custom1;
27+
if (custom1.compare(custom1)) {
28+
}
29+
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings; use the string equality operator instead [readability-string-compare]
30+
31+
CustomString2 custom2;
32+
if (custom2.compare(custom2)) {
33+
}
34+
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings; use the string equality operator instead [readability-string-compare]
35+
}

clang-tools-extra/test/clang-tidy/checkers/readability/string-compare.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,27 @@ void Test() {
6767
if (str1.compare(comp())) {
6868
}
6969
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings;
70+
71+
std::string_view sv1("a");
72+
std::string_view sv2("b");
73+
if (sv1.compare(sv2)) {
74+
}
75+
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings; use the string equality operator instead [readability-string-compare]
76+
}
77+
78+
struct DerivedFromStdString : std::string {};
79+
80+
void TestDerivedClass() {
81+
DerivedFromStdString derived;
82+
if (derived.compare(derived)) {
83+
}
84+
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: do not use 'compare' to test equality of strings; use the string equality operator instead [readability-string-compare]
7085
}
7186

7287
void Valid() {
7388
std::string str1("a", 1);
7489
std::string str2("b", 1);
90+
7591
if (str1 == str2) {
7692
}
7793
if (str1 != str2) {
@@ -96,4 +112,11 @@ void Valid() {
96112
}
97113
if (str1.compare(str2) == -1) {
98114
}
115+
116+
std::string_view sv1("a");
117+
std::string_view sv2("b");
118+
if (sv1 == sv2) {
119+
}
120+
if (sv1.compare(sv2) > 0) {
121+
}
99122
}

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,10 @@ Bug Fixes to C++ Support
692692
performed incorrectly when checking constraints. Fixes (#GH90349).
693693
- Clang now allows constrained member functions to be explicitly specialized for an implicit instantiation
694694
of a class template.
695+
- Fix a C++23 bug in implementation of P2564R3 which evaluates immediate invocations in place
696+
within initializers for variables that are usable in constant expressions or are constant
697+
initialized, rather than evaluating them as a part of the larger manifestly constant evaluated
698+
expression.
695699

696700
Bug Fixes to AST Handling
697701
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Basic/TargetInfo.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ struct TransferrableTargetInfo {
9797
unsigned char LongLongWidth, LongLongAlign;
9898
unsigned char Int128Align;
9999

100+
// This is an optional parameter for targets that
101+
// don't use 'LongLongAlign' for '_BitInt' max alignment
102+
std::optional<unsigned> BitIntMaxAlign;
103+
100104
// Fixed point bit widths
101105
unsigned char ShortAccumWidth, ShortAccumAlign;
102106
unsigned char AccumWidth, AccumAlign;
@@ -518,6 +522,22 @@ class TargetInfo : public TransferrableTargetInfo,
518522
/// getInt128Align() - Returns the alignment of Int128.
519523
unsigned getInt128Align() const { return Int128Align; }
520524

525+
/// getBitIntMaxAlign() - Returns the maximum possible alignment of
526+
/// '_BitInt' and 'unsigned _BitInt'.
527+
unsigned getBitIntMaxAlign() const {
528+
return BitIntMaxAlign.value_or(LongLongAlign);
529+
}
530+
531+
/// getBitIntAlign/Width - Return aligned size of '_BitInt' and
532+
/// 'unsigned _BitInt' for this target, in bits.
533+
unsigned getBitIntWidth(unsigned NumBits) const {
534+
return llvm::alignTo(NumBits, getBitIntAlign(NumBits));
535+
}
536+
unsigned getBitIntAlign(unsigned NumBits) const {
537+
return std::clamp<unsigned>(llvm::PowerOf2Ceil(NumBits), getCharWidth(),
538+
getBitIntMaxAlign());
539+
}
540+
521541
/// getShortAccumWidth/Align - Return the size of 'signed short _Accum' and
522542
/// 'unsigned short _Accum' for this target, in bits.
523543
unsigned getShortAccumWidth() const { return ShortAccumWidth; }

clang/include/clang/Sema/Sema.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10210,7 +10210,9 @@ class Sema final : public SemaBase {
1021010210
S.ExprEvalContexts.back().InImmediateFunctionContext =
1021110211
FD->isImmediateFunction() ||
1021210212
S.ExprEvalContexts[S.ExprEvalContexts.size() - 2]
10213-
.isConstantEvaluated();
10213+
.isConstantEvaluated() ||
10214+
S.ExprEvalContexts[S.ExprEvalContexts.size() - 2]
10215+
.isImmediateFunctionContext();
1021410216
S.ExprEvalContexts.back().InImmediateEscalatingFunctionContext =
1021510217
S.getLangOpts().CPlusPlus20 && FD->isImmediateEscalating();
1021610218
} else

clang/lib/AST/ASTContext.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,9 +2258,8 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
22582258
}
22592259
case Type::BitInt: {
22602260
const auto *EIT = cast<BitIntType>(T);
2261-
Align = std::clamp<unsigned>(llvm::PowerOf2Ceil(EIT->getNumBits()),
2262-
getCharWidth(), Target->getLongLongAlign());
2263-
Width = llvm::alignTo(EIT->getNumBits(), Align);
2261+
Align = Target->getBitIntAlign(EIT->getNumBits());
2262+
Width = Target->getBitIntWidth(EIT->getNumBits());
22642263
break;
22652264
}
22662265
case Type::Record:

clang/lib/Basic/Targets/AArch64.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
153153
else
154154
LongWidth = LongAlign = PointerWidth = PointerAlign = 32;
155155

156+
BitIntMaxAlign = 128;
156157
MaxVectorAlign = 128;
157158
MaxAtomicInlineWidth = 128;
158159
MaxAtomicPromoteWidth = 128;

clang/lib/Parse/ParseDecl.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2587,25 +2587,30 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
25872587
Parser &P;
25882588
Declarator &D;
25892589
Decl *ThisDecl;
2590+
bool Entered;
25902591

25912592
InitializerScopeRAII(Parser &P, Declarator &D, Decl *ThisDecl)
2592-
: P(P), D(D), ThisDecl(ThisDecl) {
2593+
: P(P), D(D), ThisDecl(ThisDecl), Entered(false) {
25932594
if (ThisDecl && P.getLangOpts().CPlusPlus) {
25942595
Scope *S = nullptr;
25952596
if (D.getCXXScopeSpec().isSet()) {
25962597
P.EnterScope(0);
25972598
S = P.getCurScope();
25982599
}
2599-
P.Actions.ActOnCXXEnterDeclInitializer(S, ThisDecl);
2600+
if (ThisDecl && !ThisDecl->isInvalidDecl()) {
2601+
P.Actions.ActOnCXXEnterDeclInitializer(S, ThisDecl);
2602+
Entered = true;
2603+
}
26002604
}
26012605
}
2602-
~InitializerScopeRAII() { pop(); }
2603-
void pop() {
2606+
~InitializerScopeRAII() {
26042607
if (ThisDecl && P.getLangOpts().CPlusPlus) {
26052608
Scope *S = nullptr;
26062609
if (D.getCXXScopeSpec().isSet())
26072610
S = P.getCurScope();
2608-
P.Actions.ActOnCXXExitDeclInitializer(S, ThisDecl);
2611+
2612+
if (Entered)
2613+
P.Actions.ActOnCXXExitDeclInitializer(S, ThisDecl);
26092614
if (S)
26102615
P.ExitScope();
26112616
}
@@ -2736,8 +2741,6 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
27362741
FRI->RangeExpr = Init;
27372742
}
27382743

2739-
InitScope.pop();
2740-
27412744
if (Init.isInvalid()) {
27422745
SmallVector<tok::TokenKind, 2> StopTokens;
27432746
StopTokens.push_back(tok::comma);
@@ -2785,8 +2788,6 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
27852788

27862789
bool SawError = ParseExpressionList(Exprs, ExpressionStarts);
27872790

2788-
InitScope.pop();
2789-
27902791
if (SawError) {
27912792
if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) {
27922793
Actions.ProduceConstructorSignatureHelp(
@@ -2818,8 +2819,6 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
28182819
PreferredType.enterVariableInit(Tok.getLocation(), ThisDecl);
28192820
ExprResult Init(ParseBraceInitializer());
28202821

2821-
InitScope.pop();
2822-
28232822
if (Init.isInvalid()) {
28242823
Actions.ActOnInitializerError(ThisDecl);
28252824
} else

clang/lib/Sema/SemaChecking.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16573,11 +16573,10 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
1657316573
std::string PrettySourceValue = toString(Value, 10);
1657416574
std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange);
1657516575

16576-
S.DiagRuntimeBehavior(
16577-
E->getExprLoc(), E,
16578-
S.PDiag(diag::warn_impcast_integer_precision_constant)
16579-
<< PrettySourceValue << PrettyTargetValue << E->getType() << T
16580-
<< E->getSourceRange() << SourceRange(CC));
16576+
S.Diag(E->getExprLoc(),
16577+
S.PDiag(diag::warn_impcast_integer_precision_constant)
16578+
<< PrettySourceValue << PrettyTargetValue << E->getType()
16579+
<< T << E->getSourceRange() << SourceRange(CC));
1658116580
return;
1658216581
}
1658316582
}

0 commit comments

Comments
 (0)