Skip to content

Commit

Permalink
[analyzer] MoveChecker: Add an option to suppress warnings on locals.
Browse files Browse the repository at this point in the history
Re-using a moved-from local variable is most likely a bug because there's
rarely a good motivation for not introducing a separate variable instead.
We plan to keep emitting such warnings by default.

Introduce a flag that allows disabling warnings on local variables that are
not of a known move-unsafe type. If it doesn't work out as we expected,
we'll just flip the flag.

We still warn on move-unsafe objects and unsafe operations on known move-safe
objects.

Differential Revision: https://reviews.llvm.org/D55730

llvm-svn: 349327
  • Loading branch information
haoNoQ committed Dec 17, 2018
1 parent 6990954 commit 2b500cb
Show file tree
Hide file tree
Showing 2 changed files with 384 additions and 117 deletions.
38 changes: 29 additions & 9 deletions clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
Expand Up @@ -26,7 +26,6 @@ using namespace clang;
using namespace ento;

namespace {

struct RegionState {
private:
enum Kind { Moved, Reported } K;
Expand All @@ -42,7 +41,9 @@ struct RegionState {
bool operator==(const RegionState &X) const { return K == X.K; }
void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(K); }
};
} // end of anonymous namespace

namespace {
class MoveChecker
: public Checker<check::PreCall, check::PostCall,
check::DeadSymbols, check::RegionChanges> {
Expand All @@ -62,8 +63,18 @@ class MoveChecker

private:
enum MisuseKind { MK_FunCall, MK_Copy, MK_Move, MK_Dereference };
// This needs to be unsigned in order to avoid undefined behavior
// when putting it into a tight bitfield.
enum StdObjectKind : unsigned { SK_NonStd, SK_Unsafe, SK_Safe, SK_SmartPtr };

enum AggressivenessKind { // In any case, don't warn after a reset.
AK_Invalid = -1,
AK_KnownsOnly = 0, // Warn only about known move-unsafe classes.
AK_KnownsAndLocals = 1, // Also warn about all local objects.
AK_All = 2, // Warn on any use-after-move.
AK_NumKinds = AK_All
};

static bool misuseCausesCrash(MisuseKind MK) {
return MK == MK_Dereference;
}
Expand Down Expand Up @@ -117,8 +128,9 @@ class MoveChecker
// In aggressive mode, warn on any use-after-move because the user has
// intentionally asked us to completely eliminate use-after-move
// in his code.
return IsAggressive || OK.IsLocal
|| OK.StdKind == SK_Unsafe || OK.StdKind == SK_SmartPtr;
return (Aggressiveness == AK_All) ||
(Aggressiveness >= AK_KnownsAndLocals && OK.IsLocal) ||
OK.StdKind == SK_Unsafe || OK.StdKind == SK_SmartPtr;
}

// Some objects only suffer from some kinds of misuses, but we need to track
Expand All @@ -127,8 +139,9 @@ class MoveChecker
// Additionally, only warn on smart pointers when they are dereferenced (or
// local or we are aggressive).
return shouldBeTracked(OK) &&
(IsAggressive || OK.IsLocal
|| OK.StdKind != SK_SmartPtr || MK == MK_Dereference);
((Aggressiveness == AK_All) ||
(Aggressiveness >= AK_KnownsAndLocals && OK.IsLocal) ||
OK.StdKind != SK_SmartPtr || MK == MK_Dereference);
}

// Obtains ObjectKind of an object. Because class declaration cannot always
Expand Down Expand Up @@ -173,10 +186,17 @@ class MoveChecker
bool Found;
};

bool IsAggressive = false;
AggressivenessKind Aggressiveness;

public:
void setAggressiveness(bool Aggressive) { IsAggressive = Aggressive; }
void setAggressiveness(StringRef Str) {
Aggressiveness =
llvm::StringSwitch<AggressivenessKind>(Str)
.Case("KnownsOnly", AK_KnownsOnly)
.Case("KnownsAndLocals", AK_KnownsAndLocals)
.Case("All", AK_All)
.Default(AK_KnownsAndLocals); // A sane default.
};

private:
mutable std::unique_ptr<BugType> BT;
Expand Down Expand Up @@ -717,6 +737,6 @@ void MoveChecker::printState(raw_ostream &Out, ProgramStateRef State,
}
void ento::registerMoveChecker(CheckerManager &mgr) {
MoveChecker *chk = mgr.registerChecker<MoveChecker>();
chk->setAggressiveness(mgr.getAnalyzerOptions().getCheckerBooleanOption(
"Aggressive", false, chk));
chk->setAggressiveness(
mgr.getAnalyzerOptions().getCheckerStringOption("WarnOn", "", chk));
}

0 comments on commit 2b500cb

Please sign in to comment.