forked from OSchip/llvm-project
[analyzer] Support Reinitializes attribute in MisusedMovedObject check
Differential Revision: https://reviews.llvm.org/D52983 llvm-svn: 344017
This commit is contained in:
parent
7ce9334ad7
commit
d1fd93ceea
|
@ -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;
|
||||||
|
|
|
@ -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}}
|
||||||
|
|
Loading…
Reference in New Issue