================
@@ -408,41 +420,53 @@ static void emitDiagnostic(const Expr *MovingCall, const 
DeclRefExpr *MoveArg,
   const SourceLocation UseLoc = Use.DeclRef->getExprLoc();
   const SourceLocation MoveLoc = MovingCall->getExprLoc();
 
-  const bool IsMove = (Type == MoveType::Move);
-
-  Check->diag(UseLoc, "'%0' used after it was %select{forwarded|moved}1")
-      << MoveArg->getDecl()->getName() << IsMove;
-  Check->diag(MoveLoc, "%select{forward|move}0 occurred here",
+  Check->diag(UseLoc,
+              "'%0' used after it was %select{forwarded|moved|invalidated}1")
+      << MoveArg->getDecl()->getName() << Type;
+  Check->diag(MoveLoc, "%select{forward|move|invalidation}0 occurred here",
               DiagnosticIDs::Note)
-      << IsMove;
+      << Type;
   if (Use.EvaluationOrderUndefined) {
     Check->diag(
         UseLoc,
-        "the use and %select{forward|move}0 are unsequenced, i.e. "
+        "the use and %select{forward|move|invalidation}0 are unsequenced, i.e. 
"
         "there is no guarantee about the order in which they are evaluated",
         DiagnosticIDs::Note)
-        << IsMove;
+        << Type;
   } else if (Use.UseHappensInLaterLoopIteration) {
     Check->diag(UseLoc,
                 "the use happens in a later loop iteration than the "
-                "%select{forward|move}0",
+                "%select{forward|move|invalidation}0",
                 DiagnosticIDs::Note)
-        << IsMove;
+        << Type;
   }
 }
 
+UseAfterMoveCheck::UseAfterMoveCheck(StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      InvalidationFunctions(utils::options::parseStringList(
+          Options.get("InvalidationFunctions", ""))) {}
+
+void UseAfterMoveCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "InvalidationFunctions",
+                utils::options::serializeStringList(InvalidationFunctions));
+}
+
 void UseAfterMoveCheck::registerMatchers(MatchFinder *Finder) {
   // try_emplace is a common maybe-moving function that returns a
   // bool to tell callers whether it moved. Ignore std::move inside
   // try_emplace to avoid false positives as we don't track uses of
   // the bool.
   auto TryEmplaceMatcher =
       cxxMemberCallExpr(callee(cxxMethodDecl(hasName("try_emplace"))));
+  auto Arg = declRefExpr().bind("arg");
+  auto IsMemberCallee = callee(functionDecl(unless(isStaticStorageClass())));
   auto CallMoveMatcher =
-      callExpr(argumentCountIs(1),
-               callee(functionDecl(hasAnyName("::std::move", "::std::forward"))
+      callExpr(callee(functionDecl(getNameMatcher(InvalidationFunctions))
                           .bind("move-decl")),
-               hasArgument(0, declRefExpr().bind("arg")),
+               anyOf(cxxMemberCallExpr(IsMemberCallee, on(Arg)),
+                     callExpr(unless(cxxMemberCallExpr(IsMemberCallee)),
+                              hasArgument(0, Arg))),
----------------
5chmidti wrote:

Given the invalidated object o to detect, you are matching
```c++
o.destroy();
destroy(o);
Class::destroy(o);
```
but not
```c++
shredder.destroy(o);
```

But I see why it's not supported: is `this` or the first arg the things that is 
getting invalidated.

One solution would be to have a separate option list for either case, but that 
might confuse people. I think the cases you do match are the ones that are more 
likely to happen, so it might be fine. Just wanted to point this out if others 
think we should support the one that is currently not matched.

https://github.com/llvm/llvm-project/pull/170346
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to