This is an archive of the discontinued LLVM Phabricator instance.

[clang-tidy] Add check 'misc-use-after-move'
ClosedPublic

Authored by mboehme on Aug 10 2016, 8:29 AM.

Details

Summary

The check warns if an object is used after it has been moved, without an
intervening reinitialization.

See user-facing documentation for details.

Diff Detail

Repository
rL LLVM

Event Timeline

mboehme updated this revision to Diff 67524.Aug 10 2016, 8:29 AM
mboehme retitled this revision from to [clang-tidy] Add check 'misc-use-after-move'.
mboehme updated this object.
mboehme added a reviewer: alexfh.
mboehme added a subscriber: cfe-commits.
ioeric added a subscriber: ioeric.Aug 10 2016, 8:30 AM

Apologies for the size of this patch. alexfh@ said he was willing to review it as-is -- however, I'm happy to resubmit in smaller pieces if necessary.

fowles added a subscriber: fowles.Aug 10 2016, 9:09 AM
fowles added inline comments.
test/clang-tidy/misc-use-after-move.cpp
158 ↗(On Diff #67524)

would this warn on:

std::unique_ptr<A> ptr;
std::move(ptr);
ptr->Foo();

I would like it to since that is a likely segfault.

279 ↗(On Diff #67524)

can you add tests with reference capture?

also what about:

A a;
auto lambda = [&]() { a.foo(); };
std::move(a);
lambda();

Prazek added a subscriber: Prazek.

I will review it later, but my first thoughts:

  1. I think we should make some other group, because misc seems to be overloaded. I discussed it with Alex months ago - something like bugprone would be good.
  2. Also it would be good to make link in cppcoreguidelines.
Eugene.Zelenko added inline comments.
docs/ReleaseNotes.rst
75 ↗(On Diff #67524)

Please remove This check and capitalize warns

docs/clang-tidy/checks/misc-use-after-move.rst
15 ↗(On Diff #67524)

str is not language construct, please use `.

51 ↗(On Diff #67524)

i is not language construct, please use `.

78 ↗(On Diff #67524)

Please highlight std::unique_ptr and std::shared_ptr with ``

181 ↗(On Diff #67524)

Please insert empty line and indent code as in previous examples.

190 ↗(On Diff #67524)

s, s.str and S are not language construct. Please use `.

Eugene.Zelenko set the repository for this revision to rL LLVM.
Eugene.Zelenko added inline comments.Aug 10 2016, 1:53 PM
clang-tidy/misc/UseAfterMoveCheck.cpp
512 ↗(On Diff #67524)

Please insert empty line before.

alexfh edited edge metadata.Aug 12 2016, 9:38 AM

A few initial comments.

clang-tidy/misc/UseAfterMoveCheck.cpp
492 ↗(On Diff #67524)

Any reason to avoid range-based for loops here?

505 ↗(On Diff #67524)

The type is specified verbatim in the initializer, so it's better to use const auto * here.

506 ↗(On Diff #67524)

It's uncommon to use braces for single-line if/for/... bodies in LLVM/Clang code.

docs/clang-tidy/checks/misc-use-after-move.rst
51 ↗(On Diff #67524)

It's an inline code snippet, isn't it? I'd format it as code (double backquotes).

190 ↗(On Diff #67524)

Seems fine to format these as code as well.

mboehme updated this revision to Diff 68147.Aug 16 2016, 1:47 AM
mboehme edited edge metadata.

Responses to reviewer comments.

mboehme marked 9 inline comments as done.Aug 16 2016, 2:06 AM
mboehme added inline comments.
clang-tidy/misc/UseAfterMoveCheck.cpp
493 ↗(On Diff #68147)

For some reason, I thought I had read that they weren't compatible with CFG / CFGBlock -- but obviously I must have been imagining things. ;)

Also changed the other occurrences.

docs/clang-tidy/checks/misc-use-after-move.rst
16 ↗(On Diff #68147)

There doesn't seem to be a clear preference here (see alexfh's comments on similar cases), so I'll leave this open until it's resolved one way or the other.

182 ↗(On Diff #68147)

Sorry -- forgot to check that the documentation compiles (it does now).

test/clang-tidy/misc-use-after-move.cpp
159 ↗(On Diff #68147)

No, it doesn't. At the moment, the check intentionally disregards all uses of unique_ptr and shared_ptr (see also the documentation).

I agree that it definitely makes sense to check for scenarios like the one you mention. They're a bit of a different beast though because unique_ptr and shared_ptr have a well-defined state after they've been moved from. This means they would require some special logic -- we'd want to disallow ptr->Foo() after a std::move, but not ptr.get(). For this reason, I've left them out of this initial version.

Also, I'm not sure whether this check is the best place for these unique_ptr and shared_ptr checks to live. Because the after-move state of unique_ptr and shared_ptr is well defined, the "use, then dereference" case is really just a subset of what could be a more general "dereference null pointer" check.

280 ↗(On Diff #68147)

can you add tests with reference capture?

Done.

also what about: [snip]

The check won't warn about this. More generally, it doesn't do any kind of inter-procedural analysis.

Inter-procedural analysis would certainly help in a number of ways. For example, it could be used to answer the following:

  • If a function takes a non-const reference to an object, does it reinitialize that object? (Currently, we optimistically assume that it always does.)
  • If a function (that isn't a move constructor or move assignment operator) takes an rvalue reference to an object, does it actually move from that object, and does it do so unconditionally?

However, this would take significant additional implementation effort and would also run more slowly.

mboehme marked 4 inline comments as done.Aug 16 2016, 2:11 AM

I will review it later, but my first thoughts:

  1. I think we should make some other group, because misc seems to be overloaded. I discussed it with Alex months ago - something like bugprone would be good.

Agree that "misc" seems pretty overcrowded. I'll defer to those who have been working on clang-tidy longer than me to make this call.

  1. Also it would be good to make link in cppcoreguidelines.

How exactly would I create such a "link"? Are you just thinking of a link in the documentation, or is there a way to have one clang-tidy check activate another (and is this what you're thinking of)?

omtcyfz added inline comments.
clang-tidy/misc/UseAfterMoveCheck.cpp
659 ↗(On Diff #68147)

Nit: As I discussed with Alex, it is better to omit {} in conditional statements if the body only contains one statement. Even if it wasn't so, it'd be better to use one "style" (i.e. either always omit {} or always have {}) at least inside a single check and you have no {} in many places inside this file (L637, L647, L577, ...).

Just a stylistic thing, doesn't matter too much, though.

alexfh added inline comments.Aug 17 2016, 3:03 AM
clang-tidy/misc/UseAfterMoveCheck.cpp
659 ↗(On Diff #68147)

I always say "single-line", not "single statement", which is a bit different ;)

mboehme updated this revision to Diff 68365.Aug 17 2016, 8:38 AM

Remove braces around single-line bodies of if statements

mboehme updated this revision to Diff 68366.Aug 17 2016, 8:41 AM

Remove braces around another single-line if statement block

mboehme marked 2 inline comments as done.Aug 17 2016, 8:43 AM
mboehme added inline comments.
clang-tidy/misc/UseAfterMoveCheck.cpp
659 ↗(On Diff #68147)

Agree -- I'm just used to putting the braces in there. ;)

I went through and cleaned up a bunch of these -- hope I found them all.

Prazek edited edge metadata.Aug 17 2016, 9:50 AM

I will review it later, but my first thoughts:

  1. I think we should make some other group, because misc seems to be overloaded. I discussed it with Alex months ago - something like bugprone would be good.

Agree that "misc" seems pretty overcrowded. I'll defer to those who have been working on clang-tidy longer than me to make this call.

  1. Also it would be good to make link in cppcoreguidelines.

How exactly would I create such a "link"? Are you just thinking of a link in the documentation, or is there a way to have one clang-tidy check activate another (and is this what you're thinking of)?

I am not sure if there is any other mechanism than just links in documentation.
In the perfect word it would be nice to invoke this check using cppcoreguidelines-use-after-move also with some special options like Pedantic=1 (That would warn about any use after move, even after reinitialization - this is what cppcoreguidelines says)

clang-tidy/misc/UseAfterMoveCheck.cpp
134 ↗(On Diff #67524)

What do you think about moving this, and maybe other things to some different header file to make it not so scary?

649–652 ↗(On Diff #67524)

you can replace it with

else
  return;
test/clang-tidy/misc-use-after-move.cpp
504–505 ↗(On Diff #67524)

I would like to mark it as use after move with some pedantic flag

alexfh requested changes to this revision.Aug 17 2016, 10:29 AM
alexfh edited edge metadata.
alexfh added inline comments.
clang-tidy/misc/UseAfterMoveCheck.cpp
29 ↗(On Diff #68366)

Please enclose inline code snippets in double backquotes (doxygen supports markdown to a certain degree).

46 ↗(On Diff #68366)

Does it look feasible?

135 ↗(On Diff #68366)

It's definitely subjective, but I don't think it's scary. And the size of the file doesn't seem to be an issue yet. IMO, a reason to move this to a header would appear once this class is needed elsewhere.

216 ↗(On Diff #68366)

nit: How about for (const auto &SyntheticStmt : llvm::make_range(TheCFG->synthetic_stmt_begin(), TheCFG->synthetic_stmt_end())) ...?

Alternatively, we could add CFG::synthetic_stmt() method that would return an iterator_range<...>.

435 ↗(On Diff #68366)

Use llvm::make_range and a range-for loop?

465 ↗(On Diff #68366)

nit: Variable names should start with a capital letter.

This revision now requires changes to proceed.Aug 17 2016, 10:29 AM
mboehme updated this revision to Diff 69206.Aug 25 2016, 1:40 AM
mboehme edited edge metadata.

Responses to reviewer comments.

mboehme marked 9 inline comments as done.Aug 25 2016, 2:03 AM
  1. Also it would be good to make link in cppcoreguidelines.

How exactly would I create such a "link"? Are you just thinking of a link in the documentation, or is there a way to have one clang-tidy check activate another (and is this what you're thinking of)?

I am not sure if there is any other mechanism than just links in documentation.

I've taken a look, but I'm not sure where I would put this link. I could add another file that starts with "cppcoreguidelines-", but that would make it look as if an actual check with that name exists, and I'm not sure that's what we want. Do you have a suggestion?

In the perfect word it would be nice to invoke this check using cppcoreguidelines-use-after-move also with some special options like Pedantic=1 (That would warn about any use after move, even after reinitialization - this is what cppcoreguidelines says)

Do you have a pointer to something in CppCoreGuidelines that says this explicitly?

The closest I've been able to find is in F.18: "Flag access to moved-from objects." It's not entirely clear here whether "access" is meant to include reinitialization.

However, other parts of CppCoreGuidelines seem to imply that it _is_ OK to reinitialize an object:

From ES.56:
"Usually, a std::move() is used as an argument to a && parameter. And after you do that, assume the object has been moved from (see C.64) and don't read its state again until you first set it to a new value."

And from C.64:
"Unless there is an exceptionally strong reason not to, make x = std::move(y); y = z; work with the conventional semantics."

clang-tidy/misc/UseAfterMoveCheck.cpp
29 ↗(On Diff #68366)

Shouldn't those be single backquotes? (See https://www.stack.nl/~dimitri/doxygen/manual/markdown.html)

Done with single backquotes.

46 ↗(On Diff #68366)

At least it's not something that I feel I would be able to do without breaking things -- I'm not familiar enough with SequenceChecker for that.

135 ↗(On Diff #68366)

Leaving it here for now.

217 ↗(On Diff #69206)

I've added CFG::synthetic_stmts() in D23842.

436 ↗(On Diff #69206)

Added CFGBlock::succs() in D23842. This looks much nicer now!

test/clang-tidy/misc-use-after-move.cpp
505–506 ↗(On Diff #69206)

Noted for a future addition. I'd like to get this patch in though without further expanding the functionality (it's already pretty big...).

Prazek added inline comments.Sep 1 2016, 11:59 AM
clang-tidy/misc/UseAfterMoveCheck.cpp
191 ↗(On Diff #69206)

Dry: const auto *

alexfh accepted this revision.Sep 7 2016, 5:13 AM
alexfh edited edge metadata.

LG

clang-tidy/misc/UseAfterMoveCheck.cpp
30 ↗(On Diff #69206)

Yep, you're right. I was thinking about .rst, probably.

This revision is now accepted and ready to land.Sep 7 2016, 5:13 AM
mboehme updated this revision to Diff 71312.Sep 14 2016, 3:26 AM
mboehme marked 6 inline comments as done.
mboehme edited edge metadata.

Responses to reviewer comments.

mboehme marked an inline comment as done.Sep 14 2016, 3:29 AM
This revision was automatically updated to reflect the committed changes.