diff options
-rw-r--r-- | lib/Checker/Environment.cpp | 7 | ||||
-rw-r--r-- | lib/Checker/GRExprEngine.cpp | 26 | ||||
-rw-r--r-- | test/Analysis/method-call.cpp | 1 |
3 files changed, 22 insertions, 12 deletions
diff --git a/lib/Checker/Environment.cpp b/lib/Checker/Environment.cpp index 7bf2929161..954129883d 100644 --- a/lib/Checker/Environment.cpp +++ b/lib/Checker/Environment.cpp @@ -63,7 +63,12 @@ SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder) const { if (CT->isVoidType()) return UnknownVal(); if (C->getCastKind() == CK_NoOp) { - E = C->getSubExpr(); + // If the no-op cast has value, use it. Should we always propagate + // values through all levels of no-op casts? + if (const SVal* X = ExprBindings.lookup(C)) + return *X; + else + E = C->getSubExpr(); continue; } break; diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index 2945de162a..a24a5df4fb 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -1475,15 +1475,8 @@ void GRExprEngine::ProcessCallExit(GRCallExitNodeBuilder &B) { getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx); SVal ThisV = state->getSVal(ThisR); - - if (calleeCtx->evalAsLValue()) { - state = state->BindExpr(CCE, ThisV); - } else { - loc::MemRegionVal *V = cast<loc::MemRegionVal>(&ThisV); - SVal ObjVal = state->getSVal(V->getRegion()); - assert(isa<nonloc::LazyCompoundVal>(ObjVal)); - state = state->BindExpr(CCE, ObjVal); - } + // Always bind the region to the CXXConstructExpr. + state = state->BindExpr(CCE, ThisV); } B.generateNode(state); @@ -2508,7 +2501,12 @@ void GRExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, if (InitEx) { if (VD->getType()->isReferenceType() && !InitEx->isLValue()) { - CreateCXXTemporaryObject(InitEx, Pred, Tmp); + // If the initializer is C++ record type, it should already has a + // temp object. + if (!InitEx->getType()->isRecordType()) + CreateCXXTemporaryObject(InitEx, Pred, Tmp); + else + Tmp.Add(Pred); } else Visit(InitEx, Pred, Tmp); } else @@ -2527,6 +2525,14 @@ void GRExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, if (InitEx) { SVal InitVal = state->getSVal(InitEx); + // We bound the temp obj region to the CXXConstructExpr. Now recover + // the lazy compound value when the variable is not a reference. + if (AMgr.getLangOptions().CPlusPlus && VD->getType()->isRecordType() && + !VD->getType()->isReferenceType() && isa<loc::MemRegionVal>(InitVal)){ + InitVal = state->getSVal(cast<loc::MemRegionVal>(InitVal).getRegion()); + assert(isa<nonloc::LazyCompoundVal>(InitVal)); + } + // Recover some path-sensitivity if a scalar value evaluated to // UnknownVal. if ((InitVal.isUnknown() || diff --git a/test/Analysis/method-call.cpp b/test/Analysis/method-call.cpp index 31065f41db..8c6b9da0f4 100644 --- a/test/Analysis/method-call.cpp +++ b/test/Analysis/method-call.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-inline-call -analyzer-store region -verify %s -// XFAIL: * struct A { int x; |