Skip to content

Commit b1fe77f

Browse files
authored
Merge branch 'main' into clang-tidy-infra
2 parents 0164682 + cc5b07c commit b1fe77f

File tree

158 files changed

+7549
-1367
lines changed

Some content is hidden

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

158 files changed

+7549
-1367
lines changed

.github/CODEOWNERS

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,9 @@
9393
/mlir/lib/Dialect/Linalg/Transforms/DecomposeLinalgOps.cpp @MaheshRavishankar @nicolasvasilache
9494
/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp @dcaballe @MaheshRavishankar @nicolasvasilache
9595
/mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp @MaheshRavishankar @nicolasvasilache
96-
/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp @hanhanW @nicolasvasilache
97-
/mlir/lib/Dialect/Linalg/Transforms/Transforms.cpp @dcaballe @hanhanW @nicolasvasilache
98-
/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp @banach-space @dcaballe @hanhanW @nicolasvasilache @Groverkss
96+
/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp @nicolasvasilache
97+
/mlir/lib/Dialect/Linalg/Transforms/Transforms.cpp @dcaballe @nicolasvasilache
98+
/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp @banach-space @dcaballe @nicolasvasilache @Groverkss
9999

100100
# MemRef Dialect in MLIR.
101101
/mlir/lib/Dialect/MemRef/Transforms/EmulateNarrowType.cpp @MaheshRavishankar @nicolasvasilache
@@ -112,16 +112,16 @@
112112
/mlir/include/mlir/Dialect/Vector @banach-space @dcaballe @nicolasvasilache @Groverkss
113113
/mlir/include/mlir/Dialect/Vector/IR @kuhar
114114
/mlir/lib/Dialect/Vector @banach-space @dcaballe @nicolasvasilache @Groverkss
115-
/mlir/lib/Dialect/Vector/Transforms/* @banach-space @dcaballe @hanhanW @nicolasvasilache
115+
/mlir/lib/Dialect/Vector/Transforms/* @banach-space @dcaballe @nicolasvasilache
116116
/mlir/lib/Dialect/Vector/Transforms/VectorEmulateNarrowType.cpp @banach-space @dcaballe @MaheshRavishankar @nicolasvasilache
117-
/mlir/**/*EmulateNarrowType* @dcaballe @hanhanW
117+
/mlir/**/*EmulateNarrowType* @dcaballe
118118

119119
# Presburger library in MLIR
120120
/mlir/**/*Presburger* @Groverkss @Superty
121121

122122
# Tensor Dialect in MLIR.
123-
/mlir/lib/Dialect/Tensor/IR/TensorTilingInterfaceImpl.cpp @hanhanW @nicolasvasilache
124-
/mlir/lib/Dialect/Tensor/Transforms/* @hanhanW @nicolasvasilache
123+
/mlir/lib/Dialect/Tensor/IR/TensorTilingInterfaceImpl.cpp @nicolasvasilache
124+
/mlir/lib/Dialect/Tensor/Transforms/* @nicolasvasilache
125125

126126
# Transform Dialect in MLIR.
127127
/mlir/include/mlir/Dialect/Transform/* @ftynse @nicolasvasilache @rolfmorel

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

Lines changed: 50 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "../utils/ExprSequence.h"
2121
#include "../utils/Matchers.h"
22+
#include "../utils/OptionsUtils.h"
2223
#include <optional>
2324

2425
using namespace clang::ast_matchers;
@@ -48,7 +49,8 @@ struct UseAfterMove {
4849
/// various internal helper functions).
4950
class UseAfterMoveFinder {
5051
public:
51-
UseAfterMoveFinder(ASTContext *TheContext);
52+
UseAfterMoveFinder(ASTContext *TheContext,
53+
llvm::ArrayRef<StringRef> InvalidationFunctions);
5254

5355
// Within the given code block, finds the first use of 'MovedVariable' that
5456
// occurs after 'MovingCall' (the expression that performs the move). If a
@@ -71,13 +73,19 @@ class UseAfterMoveFinder {
7173
llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs);
7274

7375
ASTContext *Context;
76+
llvm::ArrayRef<StringRef> InvalidationFunctions;
7477
std::unique_ptr<ExprSequence> Sequence;
7578
std::unique_ptr<StmtToBlockMap> BlockMap;
7679
llvm::SmallPtrSet<const CFGBlock *, 8> Visited;
7780
};
7881

7982
} // namespace
8083

84+
static auto getNameMatcher(llvm::ArrayRef<StringRef> InvalidationFunctions) {
85+
return anyOf(hasAnyName("::std::move", "::std::forward"),
86+
matchers::matchesAnyListedName(InvalidationFunctions));
87+
}
88+
8189
// Matches nodes that are
8290
// - Part of a decltype argument or class template argument (we check this by
8391
// seeing if they are children of a TypeLoc), or
@@ -92,8 +100,9 @@ static StatementMatcher inDecltypeOrTemplateArg() {
92100
hasAncestor(expr(hasUnevaluatedContext())));
93101
}
94102

95-
UseAfterMoveFinder::UseAfterMoveFinder(ASTContext *TheContext)
96-
: Context(TheContext) {}
103+
UseAfterMoveFinder::UseAfterMoveFinder(
104+
ASTContext *TheContext, llvm::ArrayRef<StringRef> InvalidationFunctions)
105+
: Context(TheContext), InvalidationFunctions(InvalidationFunctions) {}
97106

98107
std::optional<UseAfterMove>
99108
UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
@@ -359,7 +368,7 @@ void UseAfterMoveFinder::getReinits(
359368
unless(parmVarDecl(hasType(
360369
references(qualType(isConstQualified())))))),
361370
unless(callee(functionDecl(
362-
hasAnyName("::std::move", "::std::forward")))))))
371+
getNameMatcher(InvalidationFunctions)))))))
363372
.bind("reinit");
364373

365374
Stmts->clear();
@@ -388,18 +397,21 @@ void UseAfterMoveFinder::getReinits(
388397
}
389398
}
390399

391-
enum class MoveType {
392-
Move, // std::move
393-
Forward, // std::forward
400+
enum MoveType {
401+
Forward = 0, // std::forward
402+
Move = 1, // std::move
403+
Invalidation = 2, // other
394404
};
395405

396406
static MoveType determineMoveType(const FunctionDecl *FuncDecl) {
397-
if (FuncDecl->getName() == "move")
398-
return MoveType::Move;
399-
if (FuncDecl->getName() == "forward")
400-
return MoveType::Forward;
407+
if (FuncDecl->isInStdNamespace()) {
408+
if (FuncDecl->getName() == "move")
409+
return MoveType::Move;
410+
if (FuncDecl->getName() == "forward")
411+
return MoveType::Forward;
412+
}
401413

402-
llvm_unreachable("Invalid move type");
414+
return MoveType::Invalidation;
403415
}
404416

405417
static void emitDiagnostic(const Expr *MovingCall, const DeclRefExpr *MoveArg,
@@ -408,41 +420,53 @@ static void emitDiagnostic(const Expr *MovingCall, const DeclRefExpr *MoveArg,
408420
const SourceLocation UseLoc = Use.DeclRef->getExprLoc();
409421
const SourceLocation MoveLoc = MovingCall->getExprLoc();
410422

411-
const bool IsMove = (Type == MoveType::Move);
412-
413-
Check->diag(UseLoc, "'%0' used after it was %select{forwarded|moved}1")
414-
<< MoveArg->getDecl()->getName() << IsMove;
415-
Check->diag(MoveLoc, "%select{forward|move}0 occurred here",
423+
Check->diag(UseLoc,
424+
"'%0' used after it was %select{forwarded|moved|invalidated}1")
425+
<< MoveArg->getDecl()->getName() << Type;
426+
Check->diag(MoveLoc, "%select{forward|move|invalidation}0 occurred here",
416427
DiagnosticIDs::Note)
417-
<< IsMove;
428+
<< Type;
418429
if (Use.EvaluationOrderUndefined) {
419430
Check->diag(
420431
UseLoc,
421-
"the use and %select{forward|move}0 are unsequenced, i.e. "
432+
"the use and %select{forward|move|invalidation}0 are unsequenced, i.e. "
422433
"there is no guarantee about the order in which they are evaluated",
423434
DiagnosticIDs::Note)
424-
<< IsMove;
435+
<< Type;
425436
} else if (Use.UseHappensInLaterLoopIteration) {
426437
Check->diag(UseLoc,
427438
"the use happens in a later loop iteration than the "
428-
"%select{forward|move}0",
439+
"%select{forward|move|invalidation}0",
429440
DiagnosticIDs::Note)
430-
<< IsMove;
441+
<< Type;
431442
}
432443
}
433444

445+
UseAfterMoveCheck::UseAfterMoveCheck(StringRef Name, ClangTidyContext *Context)
446+
: ClangTidyCheck(Name, Context),
447+
InvalidationFunctions(utils::options::parseStringList(
448+
Options.get("InvalidationFunctions", ""))) {}
449+
450+
void UseAfterMoveCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
451+
Options.store(Opts, "InvalidationFunctions",
452+
utils::options::serializeStringList(InvalidationFunctions));
453+
}
454+
434455
void UseAfterMoveCheck::registerMatchers(MatchFinder *Finder) {
435456
// try_emplace is a common maybe-moving function that returns a
436457
// bool to tell callers whether it moved. Ignore std::move inside
437458
// try_emplace to avoid false positives as we don't track uses of
438459
// the bool.
439460
auto TryEmplaceMatcher =
440461
cxxMemberCallExpr(callee(cxxMethodDecl(hasName("try_emplace"))));
462+
auto Arg = declRefExpr().bind("arg");
463+
auto IsMemberCallee = callee(functionDecl(unless(isStaticStorageClass())));
441464
auto CallMoveMatcher =
442-
callExpr(argumentCountIs(1),
443-
callee(functionDecl(hasAnyName("::std::move", "::std::forward"))
465+
callExpr(callee(functionDecl(getNameMatcher(InvalidationFunctions))
444466
.bind("move-decl")),
445-
hasArgument(0, declRefExpr().bind("arg")),
467+
anyOf(cxxMemberCallExpr(IsMemberCallee, on(Arg)),
468+
callExpr(unless(cxxMemberCallExpr(IsMemberCallee)),
469+
hasArgument(0, Arg))),
446470
unless(inDecltypeOrTemplateArg()),
447471
unless(hasParent(TryEmplaceMatcher)), expr().bind("call-move"),
448472
anyOf(hasAncestor(compoundStmt(
@@ -521,7 +545,7 @@ void UseAfterMoveCheck::check(const MatchFinder::MatchResult &Result) {
521545
}
522546

523547
for (Stmt *CodeBlock : CodeBlocks) {
524-
UseAfterMoveFinder Finder(Result.Context);
548+
UseAfterMoveFinder Finder(Result.Context, InvalidationFunctions);
525549
if (auto Use = Finder.find(CodeBlock, MovingCall, Arg))
526550
emitDiagnostic(MovingCall, Arg, *Use, this, Result.Context,
527551
determineMoveType(MoveDecl));

clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,16 @@ namespace clang::tidy::bugprone {
2020
/// https://clang.llvm.org/extra/clang-tidy/checks/bugprone/use-after-move.html
2121
class UseAfterMoveCheck : public ClangTidyCheck {
2222
public:
23-
UseAfterMoveCheck(StringRef Name, ClangTidyContext *Context)
24-
: ClangTidyCheck(Name, Context) {}
23+
UseAfterMoveCheck(StringRef Name, ClangTidyContext *Context);
24+
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
2525
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
2626
return LangOpts.CPlusPlus11;
2727
}
2828
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
2929
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
30+
31+
private:
32+
std::vector<StringRef> InvalidationFunctions;
3033
};
3134

3235
} // namespace clang::tidy::bugprone

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

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,11 @@ static QualType getReplacementCastType(const Expr *CondLhs, const Expr *CondRhs,
9696
return GlobalImplicitCastType;
9797
}
9898

99-
static std::string createReplacement(const Expr *CondLhs, const Expr *CondRhs,
100-
const Expr *AssignLhs,
101-
const SourceManager &Source,
102-
const LangOptions &LO,
103-
StringRef FunctionName,
104-
const BinaryOperator *BO) {
99+
static std::string
100+
createReplacement(const Expr *CondLhs, const Expr *CondRhs,
101+
const Expr *AssignLhs, const SourceManager &Source,
102+
const LangOptions &LO, StringRef FunctionName,
103+
const BinaryOperator *BO, StringRef Comment = "") {
105104
const llvm::StringRef CondLhsStr = Lexer::getSourceText(
106105
Source.getExpansionRange(CondLhs->getSourceRange()), Source, LO);
107106
const llvm::StringRef CondRhsStr = Lexer::getSourceText(
@@ -116,7 +115,8 @@ static std::string createReplacement(const Expr *CondLhs, const Expr *CondRhs,
116115
(!GlobalImplicitCastType.isNull()
117116
? "<" + GlobalImplicitCastType.getAsString() + ">("
118117
: "(") +
119-
CondLhsStr + ", " + CondRhsStr + ");")
118+
CondLhsStr + ", " + CondRhsStr + ");" + (Comment.empty() ? "" : " ") +
119+
Comment)
120120
.str();
121121
}
122122

@@ -172,13 +172,65 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
172172

173173
auto ReplaceAndDiagnose = [&](const llvm::StringRef FunctionName) {
174174
const SourceManager &Source = *Result.SourceManager;
175+
llvm::SmallString<64> Comment;
176+
177+
const auto AppendNormalized = [&](llvm::StringRef Text) {
178+
Text = Text.ltrim();
179+
if (!Text.empty()) {
180+
if (!Comment.empty())
181+
Comment += " ";
182+
Comment += Text;
183+
}
184+
};
185+
186+
const auto GetSourceText = [&](SourceLocation StartLoc,
187+
SourceLocation EndLoc) {
188+
return Lexer::getSourceText(
189+
CharSourceRange::getCharRange(
190+
Lexer::getLocForEndOfToken(StartLoc, 0, Source, LO), EndLoc),
191+
Source, LO);
192+
};
193+
194+
// Captures:
195+
// if (cond) // Comment A
196+
// if (cond) /* Comment A */ { ... }
197+
// if (cond) /* Comment A */ x = y;
198+
AppendNormalized(
199+
GetSourceText(If->getRParenLoc(), If->getThen()->getBeginLoc()));
200+
201+
if (const auto *CS = dyn_cast<CompoundStmt>(If->getThen())) {
202+
const Stmt *Inner = CS->body_front();
203+
204+
// Captures:
205+
// if (cond) { // Comment B
206+
// ...
207+
// }
208+
// if (cond) { /* Comment B */ x = y; }
209+
AppendNormalized(GetSourceText(CS->getBeginLoc(), Inner->getBeginLoc()));
210+
211+
// Captures:
212+
// if (cond) { x = y; // Comment C }
213+
// if (cond) { x = y; /* Comment C */ }
214+
llvm::StringRef PostInner =
215+
GetSourceText(Inner->getEndLoc(), CS->getEndLoc());
216+
217+
// Strip the trailing semicolon to avoid fixes like:
218+
// x = std::min(x, y);; // comment
219+
const size_t Semi = PostInner.find(';');
220+
if (Semi != llvm::StringRef::npos &&
221+
PostInner.take_front(Semi).trim().empty()) {
222+
PostInner = PostInner.drop_front(Semi + 1);
223+
}
224+
AppendNormalized(PostInner);
225+
}
226+
175227
diag(IfLocation, "use `%0` instead of `%1`")
176228
<< FunctionName << BinaryOp->getOpcodeStr()
177229
<< FixItHint::CreateReplacement(
178230
SourceRange(IfLocation, Lexer::getLocForEndOfToken(
179231
ThenLocation, 0, Source, LO)),
180232
createReplacement(CondLhs, CondRhs, AssignLhs, Source, LO,
181-
FunctionName, BinaryOp))
233+
FunctionName, BinaryOp, Comment))
182234
<< IncludeInserter.createIncludeInsertion(
183235
Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
184236
};

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,10 @@ Changes in existing checks
408408
suffix when the reason starts with the character `>` in the `CustomFunctions`
409409
option.
410410

411+
- Improved :doc:`bugprone-use-after-move
412+
<clang-tidy/checks/bugprone/use-after-move>` check by adding
413+
`InvalidationFunctions` option to support custom invalidation functions.
414+
411415
- Improved :doc:`cppcoreguidelines-avoid-non-const-global-variables
412416
<clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables>` check
413417
by adding a new option `AllowThreadLocal` that suppresses warnings on
@@ -579,6 +583,11 @@ Changes in existing checks
579583
<clang-tidy/checks/readability/use-concise-preprocessor-directives>` check to
580584
generate correct fix-its for forms without a space after the directive.
581585

586+
- Improved :doc:`readability-use-std-min-max
587+
<clang-tidy/checks/readability/use-std-min-max>` check by ensuring that
588+
comments between the ``if`` condition and the ``then`` block are preserved
589+
when applying the fix.
590+
582591
Removed checks
583592
^^^^^^^^^^^^^^
584593

clang-tools-extra/docs/clang-tidy/checks/bugprone/use-after-move.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,3 +253,13 @@ For example, if an additional member variable is added to ``S``, it is easy to
253253
forget to add the reinitialization for this additional member. Instead, it is
254254
safer to assign to the entire struct in one go, and this will also avoid the
255255
use-after-move warning.
256+
257+
Options
258+
-------
259+
260+
.. option:: InvalidationFunctions
261+
262+
A semicolon-separated list of names of functions that cause their first
263+
arguments to be invalidated (e.g., closing a handle).
264+
For member functions, the first argument is considered to be the implicit
265+
object argument (``this``). Default value is an empty string.

0 commit comments

Comments
 (0)