Skip to content

Commit f89e205

Browse files
author
Jenkins
committed
merge main into amd-stg-open
Change-Id: Iad8bd30ae767ce015d6d39987c7e8e4b07d186df
2 parents 2074f32 + 89471d5 commit f89e205

File tree

33 files changed

+2970
-813
lines changed

33 files changed

+2970
-813
lines changed

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

Lines changed: 32 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ ast_matchers::internal::Matcher<Stmt> handleFromTemporaryValue(
3636
// If a ternary operator returns a temporary value, then both branches hold a
3737
// temporary value. If one of them is not a temporary then it must be copied
3838
// into one to satisfy the type of the operator.
39-
const auto TemporaryTernary =
40-
conditionalOperator(hasTrueExpression(cxxBindTemporaryExpr()),
41-
hasFalseExpression(cxxBindTemporaryExpr()));
39+
const auto TemporaryTernary = conditionalOperator(
40+
hasTrueExpression(ignoringParenImpCasts(cxxBindTemporaryExpr())),
41+
hasFalseExpression(ignoringParenImpCasts(cxxBindTemporaryExpr())));
4242

4343
return handleFrom(IsAHandle, anyOf(cxxBindTemporaryExpr(), TemporaryTernary));
4444
}
@@ -103,26 +103,17 @@ void DanglingHandleCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
103103
void DanglingHandleCheck::registerMatchersForVariables(MatchFinder *Finder) {
104104
const auto ConvertedHandle = handleFromTemporaryValue(IsAHandle);
105105

106-
// Find 'Handle foo(ReturnsAValue());'
106+
// Find 'Handle foo(ReturnsAValue());', 'Handle foo = ReturnsAValue();'
107107
Finder->addMatcher(
108108
varDecl(hasType(hasUnqualifiedDesugaredType(
109109
recordType(hasDeclaration(cxxRecordDecl(IsAHandle))))),
110+
unless(parmVarDecl()),
110111
hasInitializer(
111-
exprWithCleanups(has(ignoringParenImpCasts(ConvertedHandle)))
112+
exprWithCleanups(ignoringElidableConstructorCall(has(
113+
ignoringParenImpCasts(ConvertedHandle))))
112114
.bind("bad_stmt"))),
113115
this);
114116

115-
// Find 'Handle foo = ReturnsAValue();'
116-
Finder->addMatcher(
117-
traverse(TK_AsIs,
118-
varDecl(hasType(hasUnqualifiedDesugaredType(recordType(
119-
hasDeclaration(cxxRecordDecl(IsAHandle))))),
120-
unless(parmVarDecl()),
121-
hasInitializer(exprWithCleanups(
122-
has(ignoringParenImpCasts(handleFrom(
123-
IsAHandle, ConvertedHandle))))
124-
.bind("bad_stmt")))),
125-
this);
126117
// Find 'foo = ReturnsAValue(); // foo is Handle'
127118
Finder->addMatcher(
128119
traverse(TK_AsIs,
@@ -141,36 +132,35 @@ void DanglingHandleCheck::registerMatchersForVariables(MatchFinder *Finder) {
141132
void DanglingHandleCheck::registerMatchersForReturn(MatchFinder *Finder) {
142133
// Return a local.
143134
Finder->addMatcher(
144-
traverse(
145-
TK_AsIs,
146-
returnStmt(
147-
// The AST contains two constructor calls:
148-
// 1. Value to Handle conversion.
149-
// 2. Handle copy construction.
150-
// We have to match both.
151-
has(ignoringImplicit(handleFrom(
152-
IsAHandle,
153-
handleFrom(IsAHandle,
154-
declRefExpr(to(varDecl(
155-
// Is function scope ...
156-
hasAutomaticStorageDuration(),
157-
// ... and it is a local array or Value.
158-
anyOf(hasType(arrayType()),
159-
hasType(hasUnqualifiedDesugaredType(
160-
recordType(hasDeclaration(recordDecl(
161-
unless(IsAHandle)))))))))))))),
162-
// Temporary fix for false positives inside lambdas.
163-
unless(hasAncestor(lambdaExpr())))
164-
.bind("bad_stmt")),
135+
traverse(TK_AsIs,
136+
returnStmt(
137+
// The AST contains two constructor calls:
138+
// 1. Value to Handle conversion.
139+
// 2. Handle copy construction (elided in C++17+).
140+
// We have to match both.
141+
has(ignoringImplicit(ignoringElidableConstructorCall(
142+
ignoringImplicit(handleFrom(
143+
IsAHandle,
144+
declRefExpr(to(varDecl(
145+
// Is function scope ...
146+
hasAutomaticStorageDuration(),
147+
// ... and it is a local array or Value.
148+
anyOf(hasType(arrayType()),
149+
hasType(hasUnqualifiedDesugaredType(
150+
recordType(hasDeclaration(recordDecl(
151+
unless(IsAHandle))))))))))))))),
152+
// Temporary fix for false positives inside lambdas.
153+
unless(hasAncestor(lambdaExpr())))
154+
.bind("bad_stmt")),
165155
this);
166156

167157
// Return a temporary.
168158
Finder->addMatcher(
169-
traverse(
170-
TK_AsIs,
171-
returnStmt(has(exprWithCleanups(has(ignoringParenImpCasts(handleFrom(
172-
IsAHandle, handleFromTemporaryValue(IsAHandle)))))))
173-
.bind("bad_stmt")),
159+
traverse(TK_AsIs,
160+
returnStmt(has(exprWithCleanups(ignoringElidableConstructorCall(
161+
has(ignoringParenImpCasts(
162+
handleFromTemporaryValue(IsAHandle)))))))
163+
.bind("bad_stmt")),
174164
this);
175165
}
176166

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

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "UseNullptrCheck.h"
10+
#include "../utils/Matchers.h"
11+
#include "../utils/OptionsUtils.h"
1012
#include "clang/AST/ASTContext.h"
1113
#include "clang/AST/RecursiveASTVisitor.h"
1214
#include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -33,11 +35,13 @@ AST_MATCHER(Type, sugaredNullptrType) {
3335
/// to null within.
3436
/// Finding sequences of explicit casts is necessary so that an entire sequence
3537
/// can be replaced instead of just the inner-most implicit cast.
36-
StatementMatcher makeCastSequenceMatcher() {
37-
StatementMatcher ImplicitCastToNull = implicitCastExpr(
38+
StatementMatcher makeCastSequenceMatcher(llvm::ArrayRef<StringRef> NameList) {
39+
auto ImplicitCastToNull = implicitCastExpr(
3840
anyOf(hasCastKind(CK_NullToPointer), hasCastKind(CK_NullToMemberPointer)),
3941
unless(hasImplicitDestinationType(qualType(substTemplateTypeParmType()))),
40-
unless(hasSourceExpression(hasType(sugaredNullptrType()))));
42+
unless(hasSourceExpression(hasType(sugaredNullptrType()))),
43+
unless(hasImplicitDestinationType(
44+
qualType(matchers::matchesAnyListedTypeName(NameList)))));
4145

4246
auto IsOrHasDescendant = [](auto InnerMatcher) {
4347
return anyOf(InnerMatcher, hasDescendant(InnerMatcher));
@@ -477,16 +481,21 @@ class CastSequenceVisitor : public RecursiveASTVisitor<CastSequenceVisitor> {
477481

478482
UseNullptrCheck::UseNullptrCheck(StringRef Name, ClangTidyContext *Context)
479483
: ClangTidyCheck(Name, Context),
480-
NullMacrosStr(Options.get("NullMacros", "NULL")) {
484+
NullMacrosStr(Options.get("NullMacros", "NULL")),
485+
IgnoredTypes(utils::options::parseStringList(Options.get(
486+
"IgnoredTypes",
487+
"std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec"))) {
481488
StringRef(NullMacrosStr).split(NullMacros, ",");
482489
}
483490

484491
void UseNullptrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
485492
Options.store(Opts, "NullMacros", NullMacrosStr);
493+
Options.store(Opts, "IgnoredTypes",
494+
utils::options::serializeStringList(IgnoredTypes));
486495
}
487496

488497
void UseNullptrCheck::registerMatchers(MatchFinder *Finder) {
489-
Finder->addMatcher(makeCastSequenceMatcher(), this);
498+
Finder->addMatcher(makeCastSequenceMatcher(IgnoredTypes), this);
490499
}
491500

492501
void UseNullptrCheck::check(const MatchFinder::MatchResult &Result) {

clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class UseNullptrCheck : public ClangTidyCheck {
2828
private:
2929
const StringRef NullMacrosStr;
3030
SmallVector<StringRef, 1> NullMacros;
31+
std::vector<StringRef> IgnoredTypes;
3132
};
3233

3334
} // namespace clang::tidy::modernize

clang-tools-extra/clang-tidy/utils/Matchers.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,32 @@ bool NotIdenticalStatementsPredicate::operator()(
1717
Nodes.getNodeAs<Stmt>(ID), *Context);
1818
}
1919

20+
MatchesAnyListedTypeNameMatcher::MatchesAnyListedTypeNameMatcher(
21+
llvm::ArrayRef<StringRef> NameList)
22+
: NameMatchers(NameList.begin(), NameList.end()) {}
23+
24+
MatchesAnyListedTypeNameMatcher::~MatchesAnyListedTypeNameMatcher() = default;
25+
26+
bool MatchesAnyListedTypeNameMatcher::matches(
27+
const QualType &Node, ast_matchers::internal::ASTMatchFinder *Finder,
28+
ast_matchers::internal::BoundNodesTreeBuilder *Builder) const {
29+
30+
if (NameMatchers.empty())
31+
return false;
32+
33+
PrintingPolicy PrintingPolicyWithSuppressedTag(
34+
Finder->getASTContext().getLangOpts());
35+
PrintingPolicyWithSuppressedTag.PrintCanonicalTypes = true;
36+
PrintingPolicyWithSuppressedTag.SuppressElaboration = true;
37+
PrintingPolicyWithSuppressedTag.SuppressScope = false;
38+
PrintingPolicyWithSuppressedTag.SuppressTagKeyword = true;
39+
PrintingPolicyWithSuppressedTag.SuppressUnwrittenScope = true;
40+
std::string TypeName =
41+
Node.getUnqualifiedType().getAsString(PrintingPolicyWithSuppressedTag);
42+
43+
return llvm::any_of(NameMatchers, [&TypeName](const llvm::Regex &NM) {
44+
return NM.isValid() && NM.match(TypeName);
45+
});
46+
}
47+
2048
} // namespace clang::tidy::matchers

clang-tools-extra/clang-tidy/utils/Matchers.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,28 @@ AST_MATCHER_P(Stmt, isStatementIdenticalToBoundNode, std::string, ID) {
158158
return Builder->removeBindings(Predicate);
159159
}
160160

161+
// A matcher implementation that matches a list of type name regular expressions
162+
// against a QualType.
163+
class MatchesAnyListedTypeNameMatcher
164+
: public ast_matchers::internal::MatcherInterface<QualType> {
165+
public:
166+
explicit MatchesAnyListedTypeNameMatcher(llvm::ArrayRef<StringRef> NameList);
167+
~MatchesAnyListedTypeNameMatcher() override;
168+
bool matches(
169+
const QualType &Node, ast_matchers::internal::ASTMatchFinder *Finder,
170+
ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override;
171+
172+
private:
173+
std::vector<llvm::Regex> NameMatchers;
174+
};
175+
176+
// Returns a matcher that matches QualType against a list of provided regular.
177+
inline ::clang::ast_matchers::internal::Matcher<QualType>
178+
matchesAnyListedTypeName(llvm::ArrayRef<StringRef> NameList) {
179+
return ::clang::ast_matchers::internal::makeMatcher(
180+
new MatchesAnyListedTypeNameMatcher(NameList));
181+
}
182+
161183
} // namespace clang::tidy::matchers
162184

163185
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H

clang-tools-extra/clangd/InlayHints.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -586,11 +586,13 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
586586
if (!Cfg.InlayHints.Parameters)
587587
return true;
588588

589-
// Do not show parameter hints for operator calls written using operator
590-
// syntax or user-defined literals. (Among other reasons, the resulting
589+
bool IsFunctor = isFunctionObjectCallExpr(E);
590+
// Do not show parameter hints for user-defined literals or
591+
// operator calls except for operator(). (Among other reasons, the resulting
591592
// hints can look awkward, e.g. the expression can itself be a function
592593
// argument and then we'd get two hints side by side).
593-
if (isa<CXXOperatorCallExpr>(E) || isa<UserDefinedLiteral>(E))
594+
if ((isa<CXXOperatorCallExpr>(E) && !IsFunctor) ||
595+
isa<UserDefinedLiteral>(E))
594596
return true;
595597

596598
auto CalleeDecls = Resolver->resolveCalleeOfCallExpr(E);
@@ -607,7 +609,22 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
607609
else
608610
return true;
609611

610-
processCall(Callee, {E->getArgs(), E->getNumArgs()});
612+
// N4868 [over.call.object]p3 says,
613+
// The argument list submitted to overload resolution consists of the
614+
// argument expressions present in the function call syntax preceded by the
615+
// implied object argument (E).
616+
//
617+
// However, we don't have the implied object argument for static
618+
// operator() per clang::Sema::BuildCallToObjectOfClassType.
619+
llvm::ArrayRef<const Expr *> Args = {E->getArgs(), E->getNumArgs()};
620+
if (IsFunctor)
621+
// We don't have the implied object argument through
622+
// a function pointer either.
623+
if (const CXXMethodDecl *Method =
624+
dyn_cast_or_null<CXXMethodDecl>(Callee.Decl);
625+
Method && Method->isInstance())
626+
Args = Args.drop_front(1);
627+
processCall(Callee, Args);
611628
return true;
612629
}
613630

@@ -1203,6 +1220,12 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
12031220
return Range{HintStart, HintEnd};
12041221
}
12051222

1223+
static bool isFunctionObjectCallExpr(CallExpr *E) noexcept {
1224+
if (auto *CallExpr = dyn_cast<CXXOperatorCallExpr>(E))
1225+
return CallExpr->getOperator() == OverloadedOperatorKind::OO_Call;
1226+
return false;
1227+
}
1228+
12061229
std::vector<InlayHint> &Results;
12071230
ASTContext &AST;
12081231
const syntax::TokenBuffer &Tokens;

clang-tools-extra/clangd/unittests/InlayHintTests.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ void assertHintsWithHeader(InlayHintKind Kind, llvm::StringRef AnnotatedSource,
8989
ExpectedHints... Expected) {
9090
Annotations Source(AnnotatedSource);
9191
TestTU TU = TestTU::withCode(Source.code());
92-
TU.ExtraArgs.push_back("-std=c++20");
92+
TU.ExtraArgs.push_back("-std=c++23");
9393
TU.HeaderCode = HeaderContent;
9494
auto AST = TU.build();
9595

@@ -807,6 +807,42 @@ TEST(ParameterHints, Operator) {
807807
)cpp");
808808
}
809809

810+
TEST(ParameterHints, FunctionCallOperator) {
811+
assertParameterHints(R"cpp(
812+
struct W {
813+
void operator()(int x);
814+
};
815+
struct S : W {
816+
using W::operator();
817+
static void operator()(int x, int y);
818+
};
819+
void bar() {
820+
auto l1 = [](int x) {};
821+
auto l2 = [](int x) static {};
822+
823+
S s;
824+
s($1[[1]]);
825+
s.operator()($2[[1]]);
826+
s.operator()($3[[1]], $4[[2]]);
827+
S::operator()($5[[1]], $6[[2]]);
828+
829+
l1($7[[1]]);
830+
l1.operator()($8[[1]]);
831+
l2($9[[1]]);
832+
l2.operator()($10[[1]]);
833+
834+
void (*ptr)(int a, int b) = &S::operator();
835+
ptr($11[[1]], $12[[2]]);
836+
}
837+
)cpp",
838+
ExpectedHint{"x: ", "1"}, ExpectedHint{"x: ", "2"},
839+
ExpectedHint{"x: ", "3"}, ExpectedHint{"y: ", "4"},
840+
ExpectedHint{"x: ", "5"}, ExpectedHint{"y: ", "6"},
841+
ExpectedHint{"x: ", "7"}, ExpectedHint{"x: ", "8"},
842+
ExpectedHint{"x: ", "9"}, ExpectedHint{"x: ", "10"},
843+
ExpectedHint{"a: ", "11"}, ExpectedHint{"b: ", "12"});
844+
}
845+
810846
TEST(ParameterHints, Macros) {
811847
// Handling of macros depends on where the call's argument list comes from.
812848

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ Changes in existing checks
227227
`DeduplicateFindings` to output one finding per symbol occurrence.
228228

229229
- Improved :doc:`misc-include-cleaner
230-
<clang-tidy/checks/misc/include-cleaner>` check to avoid fixes insert
230+
<clang-tidy/checks/misc/include-cleaner>` check to avoid fixes insert
231231
same include header multiple times.
232232

233233
- Improved :doc:`misc-redundant-expression
@@ -242,6 +242,10 @@ Changes in existing checks
242242
<clang-tidy/checks/modernize/use-equals-delete>` check to ignore
243243
false-positives when special member function is actually used or implicit.
244244

245+
- Improved :doc:`modernize-use-nullptr
246+
<clang-tidy/checks/modernize/use-nullptr>` check by adding option
247+
`IgnoredTypes` that can be used to exclude some pointer types.
248+
245249
- Improved :doc:`modernize-use-std-print
246250
<clang-tidy/checks/modernize/use-std-print>` check to accurately generate
247251
fixes for reordering arguments.

clang-tools-extra/docs/clang-tidy/checks/modernize/use-nullptr.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ transforms to:
3939
Options
4040
-------
4141

42+
.. option:: IgnoredTypes
43+
44+
Semicolon-separated list of regular expressions to match pointer types for
45+
which implicit casts will be ignored. Default value:
46+
`std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec`.
47+
4248
.. option:: NullMacros
4349

4450
Comma-separated list of macro names that will be transformed along with

0 commit comments

Comments
 (0)