[analyzer] Support Reinitializes attribute in MisusedMovedObject check

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

llvm-svn: 344017
This commit is contained in:
Gabor Horvath 2018-10-09 07:28:57 +00:00
parent 7ce9334ad7
commit d1fd93ceea
2 changed files with 21 additions and 15 deletions

View File

@ -314,17 +314,18 @@ bool MisusedMovedObjectChecker::isMoveSafeMethod(
return true; return true;
} }
// Function call `empty` can be skipped. // Function call `empty` can be skipped.
if (MethodDec && MethodDec->getDeclName().isIdentifier() && return (MethodDec && MethodDec->getDeclName().isIdentifier() &&
(MethodDec->getName().lower() == "empty" || (MethodDec->getName().lower() == "empty" ||
MethodDec->getName().lower() == "isempty")) MethodDec->getName().lower() == "isempty"));
return true;
return false;
} }
bool MisusedMovedObjectChecker::isStateResetMethod( bool MisusedMovedObjectChecker::isStateResetMethod(
const CXXMethodDecl *MethodDec) const { const CXXMethodDecl *MethodDec) const {
if (MethodDec && MethodDec->getDeclName().isIdentifier()) { if (!MethodDec)
return false;
if (MethodDec->hasAttr<ReinitializesAttr>())
return true;
if (MethodDec->getDeclName().isIdentifier()) {
std::string MethodName = MethodDec->getName().lower(); std::string MethodName = MethodDec->getName().lower();
if (MethodName == "reset" || MethodName == "clear" || if (MethodName == "reset" || MethodName == "clear" ||
MethodName == "destroy") MethodName == "destroy")
@ -429,8 +430,7 @@ void MisusedMovedObjectChecker::checkPreCall(const CallEvent &Call,
// We want to investigate the whole object, not only sub-object of a parent // We want to investigate the whole object, not only sub-object of a parent
// class in which the encountered method defined. // class in which the encountered method defined.
while (const CXXBaseObjectRegion *BR = while (const auto *BR = dyn_cast<CXXBaseObjectRegion>(ThisRegion))
dyn_cast<CXXBaseObjectRegion>(ThisRegion))
ThisRegion = BR->getSuperRegion(); ThisRegion = BR->getSuperRegion();
if (isMoveSafeMethod(MethodDecl)) if (isMoveSafeMethod(MethodDecl))
@ -487,13 +487,9 @@ ProgramStateRef MisusedMovedObjectChecker::checkRegionChanges(
ThisRegion = IC->getCXXThisVal().getAsRegion(); ThisRegion = IC->getCXXThisVal().getAsRegion();
} }
for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(), for (const auto *Region : ExplicitRegions) {
E = ExplicitRegions.end(); if (ThisRegion != Region)
I != E; ++I) {
const auto *Region = *I;
if (ThisRegion != Region) {
State = removeFromState(State, Region); State = removeFromState(State, Region);
}
} }
return State; return State;

View File

@ -638,7 +638,10 @@ void ifStmtSequencesDeclAndConditionTest() {
} }
} }
class C : public A {}; struct C : public A {
[[clang::reinitializes]] void reinit();
};
void subRegionMoveTest() { void subRegionMoveTest() {
{ {
A a; A a;
@ -672,6 +675,13 @@ void resetSuperClass() {
C c2 = c; // no-warning C c2 = c; // no-warning
} }
void resetSuperClass2() {
C c;
C c1 = std::move(c);
c.reinit();
C c2 = c; // no-warning
}
void reportSuperClass() { void reportSuperClass() {
C c; C c;
C c1 = std::move(c); // expected-note {{'c' became 'moved-from' here}} C c1 = std::move(c); // expected-note {{'c' became 'moved-from' here}}