Consumed Analysis: IgnoreParens bugfix.

llvm-svn: 204395
This commit is contained in:
DeLesley Hutchins 2014-03-20 20:39:20 +00:00
parent ba5570221d
commit d7fa5bd431
2 changed files with 71 additions and 29 deletions

View File

@ -471,11 +471,21 @@ class ConsumedStmtVisitor : public ConstStmtVisitor<ConsumedStmtVisitor> {
ConsumedStateMap *StateMap;
MapType PropagationMap;
void forwardInfo(const Stmt *From, const Stmt *To);
void copyInfo(const Stmt *From, const Stmt *To, ConsumedState CS);
ConsumedState getInfo(const Stmt *From);
void setInfo(const Stmt *To, ConsumedState NS);
void propagateReturnType(const Stmt *Call, const FunctionDecl *Fun);
InfoEntry findInfo(const Expr *E) {
return PropagationMap.find(E->IgnoreParens());
}
ConstInfoEntry findInfo(const Expr *E) const {
return PropagationMap.find(E->IgnoreParens());
}
void insertInfo(const Expr *E, const PropagationInfo &PI) {
PropagationMap.insert(PairType(E->IgnoreParens(), PI));
}
void forwardInfo(const Expr *From, const Expr *To);
void copyInfo(const Expr *From, const Expr *To, ConsumedState CS);
ConsumedState getInfo(const Expr *From);
void setInfo(const Expr *To, ConsumedState NS);
void propagateReturnType(const Expr *Call, const FunctionDecl *Fun);
public:
void checkCallability(const PropagationInfo &PInfo,
@ -504,8 +514,8 @@ public:
ConsumedStateMap *StateMap)
: AC(AC), Analyzer(Analyzer), StateMap(StateMap) {}
PropagationInfo getInfo(const Stmt *StmtNode) const {
ConstInfoEntry Entry = PropagationMap.find(StmtNode);
PropagationInfo getInfo(const Expr *StmtNode) const {
ConstInfoEntry Entry = findInfo(StmtNode);
if (Entry != PropagationMap.end())
return Entry->second;
@ -519,23 +529,23 @@ public:
};
void ConsumedStmtVisitor::forwardInfo(const Stmt *From, const Stmt *To) {
InfoEntry Entry = PropagationMap.find(From);
void ConsumedStmtVisitor::forwardInfo(const Expr *From, const Expr *To) {
InfoEntry Entry = findInfo(From);
if (Entry != PropagationMap.end())
PropagationMap.insert(PairType(To, Entry->second));
insertInfo(To, Entry->second);
}
// Create a new state for To, which is initialized to the state of From.
// If NS is not CS_None, sets the state of From to NS.
void ConsumedStmtVisitor::copyInfo(const Stmt *From, const Stmt *To,
void ConsumedStmtVisitor::copyInfo(const Expr *From, const Expr *To,
ConsumedState NS) {
InfoEntry Entry = PropagationMap.find(From);
InfoEntry Entry = findInfo(From);
if (Entry != PropagationMap.end()) {
PropagationInfo& PInfo = Entry->second;
ConsumedState CS = PInfo.getAsState(StateMap);
if (CS != CS_None)
PropagationMap.insert(PairType(To, CS));
insertInfo(To, PropagationInfo(CS));
if (NS != CS_None && PInfo.isPointerToValue())
setStateForVarOrTmp(StateMap, PInfo, NS);
}
@ -543,8 +553,8 @@ void ConsumedStmtVisitor::copyInfo(const Stmt *From, const Stmt *To,
// Get the ConsumedState for From
ConsumedState ConsumedStmtVisitor::getInfo(const Stmt *From) {
InfoEntry Entry = PropagationMap.find(From);
ConsumedState ConsumedStmtVisitor::getInfo(const Expr *From) {
InfoEntry Entry = findInfo(From);
if (Entry != PropagationMap.end()) {
PropagationInfo& PInfo = Entry->second;
return PInfo.getAsState(StateMap);
@ -554,14 +564,14 @@ ConsumedState ConsumedStmtVisitor::getInfo(const Stmt *From) {
// If we already have info for To then update it, otherwise create a new entry.
void ConsumedStmtVisitor::setInfo(const Stmt *To, ConsumedState NS) {
InfoEntry Entry = PropagationMap.find(To);
void ConsumedStmtVisitor::setInfo(const Expr *To, ConsumedState NS) {
InfoEntry Entry = findInfo(To);
if (Entry != PropagationMap.end()) {
PropagationInfo& PInfo = Entry->second;
if (PInfo.isPointerToValue())
setStateForVarOrTmp(StateMap, PInfo, NS);
} else if (NS != CS_None) {
PropagationMap.insert(PairType(To, PropagationInfo(NS)));
insertInfo(To, PropagationInfo(NS));
}
}
@ -616,7 +626,7 @@ bool ConsumedStmtVisitor::handleCall(const CallExpr *Call, const Expr *ObjArg,
const ParmVarDecl *Param = FunD->getParamDecl(Index - Offset);
QualType ParamType = Param->getType();
InfoEntry Entry = PropagationMap.find(Call->getArg(Index));
InfoEntry Entry = findInfo(Call->getArg(Index));
if (Entry == PropagationMap.end() || Entry->second.isTest())
continue;
@ -651,7 +661,7 @@ bool ConsumedStmtVisitor::handleCall(const CallExpr *Call, const Expr *ObjArg,
return false;
// check implicit 'self' parameter, if present
InfoEntry Entry = PropagationMap.find(ObjArg);
InfoEntry Entry = findInfo(ObjArg);
if (Entry != PropagationMap.end()) {
PropagationInfo PInfo = Entry->second;
checkCallability(PInfo, FunD, Call->getExprLoc());
@ -675,7 +685,7 @@ bool ConsumedStmtVisitor::handleCall(const CallExpr *Call, const Expr *ObjArg,
}
void ConsumedStmtVisitor::propagateReturnType(const Stmt *Call,
void ConsumedStmtVisitor::propagateReturnType(const Expr *Call,
const FunctionDecl *Fun) {
QualType RetType = Fun->getCallResultType();
if (RetType->isReferenceType())
@ -697,8 +707,8 @@ void ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) {
switch (BinOp->getOpcode()) {
case BO_LAnd:
case BO_LOr : {
InfoEntry LEntry = PropagationMap.find(BinOp->getLHS()),
REntry = PropagationMap.find(BinOp->getRHS());
InfoEntry LEntry = findInfo(BinOp->getLHS()),
REntry = findInfo(BinOp->getRHS());
VarTestResult LTest, RTest;
@ -770,7 +780,7 @@ void ConsumedStmtVisitor::VisitCastExpr(const CastExpr *Cast) {
void ConsumedStmtVisitor::VisitCXXBindTemporaryExpr(
const CXXBindTemporaryExpr *Temp) {
InfoEntry Entry = PropagationMap.find(Temp->getSubExpr());
InfoEntry Entry = findInfo(Temp->getSubExpr());
if (Entry != PropagationMap.end() && !Entry->second.isTest()) {
StateMap->setState(Temp, Entry->second.getAsState(StateMap));
@ -894,7 +904,7 @@ void ConsumedStmtVisitor::VisitReturnStmt(const ReturnStmt *Ret) {
ConsumedState ExpectedState = Analyzer.getExpectedReturnState();
if (ExpectedState != CS_None) {
InfoEntry Entry = PropagationMap.find(Ret->getRetValue());
InfoEntry Entry = findInfo(Ret->getRetValue());
if (Entry != PropagationMap.end()) {
ConsumedState RetState = Entry->second.getAsState(StateMap);
@ -911,7 +921,7 @@ void ConsumedStmtVisitor::VisitReturnStmt(const ReturnStmt *Ret) {
}
void ConsumedStmtVisitor::VisitUnaryOperator(const UnaryOperator *UOp) {
InfoEntry Entry = PropagationMap.find(UOp->getSubExpr()->IgnoreParens());
InfoEntry Entry = findInfo(UOp->getSubExpr());
if (Entry == PropagationMap.end()) return;
switch (UOp->getOpcode()) {
@ -933,8 +943,7 @@ void ConsumedStmtVisitor::VisitUnaryOperator(const UnaryOperator *UOp) {
void ConsumedStmtVisitor::VisitVarDecl(const VarDecl *Var) {
if (isConsumableType(Var->getType())) {
if (Var->hasInit()) {
MapType::iterator VIT = PropagationMap.find(
Var->getInit()->IgnoreImplicit());
MapType::iterator VIT = findInfo(Var->getInit()->IgnoreImplicit());
if (VIT != PropagationMap.end()) {
PropagationInfo PInfo = VIT->second;
ConsumedState St = PInfo.getAsState(StateMap);
@ -1292,7 +1301,7 @@ bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
if (const IfStmt *IfNode =
dyn_cast_or_null<IfStmt>(CurrBlock->getTerminator().getStmt())) {
const Stmt *Cond = IfNode->getCond();
const Expr *Cond = IfNode->getCond();
PInfo = Visitor.getInfo(Cond);
if (!PInfo.isValid() && isa<BinaryOperator>(Cond))

View File

@ -684,6 +684,8 @@ class CONSUMABLE(unconsumed)
int code;
public:
static Status OK;
Status() RETURN_TYPESTATE(consumed);
Status(int c) RETURN_TYPESTATE(unconsumed);
@ -693,6 +695,8 @@ public:
Status& operator=(const Status &other) CALLABLE_WHEN("unknown", "consumed");
Status& operator=(Status &&other) CALLABLE_WHEN("unknown", "consumed");
bool operator==(const Status &other) const SET_TYPESTATE(consumed);
bool check() const SET_TYPESTATE(consumed);
void ignore() const SET_TYPESTATE(consumed);
// Status& markAsChecked() { return *this; }
@ -710,6 +714,11 @@ void handleStatusRef(Status& s);
void handleStatusPtr(Status* s);
void handleStatusUnmarked(const Status& s);
void log(const char* msg);
void fail() __attribute__((noreturn));
void checkStat(const Status& s);
void testSimpleTemporaries0() {
doSomething(); // expected-warning {{invalid invocation of method '~Status' on a temporary object while it is in the 'unconsumed' state}}
}
@ -870,6 +879,29 @@ Status testReturnAutocast() {
return s; // should autocast back to unconsumed
}
namespace TestParens {
void test3() {
checkStat((doSomething()));
}
void test4() {
Status s = (doSomething());
s.check();
}
void test5() {
(doSomething()).check();
}
void test6() {
if ((doSomething()) == Status::OK)
return;
}
} // end namespace TestParens
} // end namespace InitializerAssertionFailTest
@ -899,3 +931,4 @@ namespace PR18260 {
std::__1::move(x);
}
} // end namespace PR18260