This makes the consumed analysis less dependent on the CFG layout and fixes
a bug where we wouldn't warn on an unconsumed value.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@208300
91177308-0d34-0410-b5e6-
96231b3b80d8
/// \brief Set the consumed state of a given temporary value.
void setState(const CXXBindTemporaryExpr *Tmp, ConsumedState State);
- /// \brief Remove the variable from our state map.
- void remove(const VarDecl *Var);
+ /// \brief Remove the temporary value from our state map.
+ void remove(const CXXBindTemporaryExpr *Tmp);
/// \brief Tests to see if there is a mismatch in the states stored in two
/// maps.
TmpMap[Tmp] = State;
}
-void ConsumedStateMap::remove(const VarDecl *Var) {
- VarMap.erase(Var);
+void ConsumedStateMap::remove(const CXXBindTemporaryExpr *Tmp) {
+ TmpMap.erase(Tmp);
}
bool ConsumedStateMap::operator!=(const ConsumedStateMap *Other) const {
Visitor.checkCallability(PropagationInfo(BTE),
DTor.getDestructorDecl(AC.getASTContext()),
BTE->getExprLoc());
+ CurrStates->remove(BTE);
break;
}
}
}
- CurrStates->clearTemporaries();
-
// TODO: Handle other forms of branching with precision, including while-
// and for-loops. (Deferred)
if (!splitState(CurrBlock, Visitor)) {
void clear() CALLABLE_WHEN("unknown", "consumed") SET_TYPESTATE(consumed);
~Status() CALLABLE_WHEN("unknown", "consumed");
+
+ operator bool() const; // Will not consume the object.
};
Status s = doSomething();
} // expected-warning {{invalid invocation of method '~Status' on object 's' while it is in the 'unconsumed' state}}
+void testTemporariesWithControlFlow(bool a) {
+ bool b = false || doSomething(); // expected-warning {{invalid invocation of method '~Status' on a temporary object while it is in the 'unconsumed' state}}
+}
+
Status testSimpleTemporariesReturn0() {
return doSomething();
}