diff options
author | Zhongxing Xu <xuzhongxing@gmail.com> | 2010-12-22 07:20:27 +0000 |
---|---|---|
committer | Zhongxing Xu <xuzhongxing@gmail.com> | 2010-12-22 07:20:27 +0000 |
commit | 7089250f5a97e98bf6b39c1d37e46e894ca1e383 (patch) | |
tree | 801060fa72fc42b17e9965494ee140229350969f /clang/lib/Checker | |
parent | f3e5b4eb8062c35af7e715494760863dc57e0035 (diff) | |
download | bcm5719-llvm-7089250f5a97e98bf6b39c1d37e46e894ca1e383.tar.gz bcm5719-llvm-7089250f5a97e98bf6b39c1d37e46e894ca1e383.zip |
After inlining the CXXConstructExpr, bind the temporary object region to it.
This change is necessary when the variable is a const reference and we need
the l-value of the construct expr. After that, when binding the variable,
recover the lazy compound value when the variable is not a reference.
In Environment, use the value of a no-op cast expression when it has one.
Otherwise, blast-through it.
llvm-svn: 122388
Diffstat (limited to 'clang/lib/Checker')
-rw-r--r-- | clang/lib/Checker/Environment.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Checker/GRExprEngine.cpp | 26 |
2 files changed, 22 insertions, 11 deletions
diff --git a/clang/lib/Checker/Environment.cpp b/clang/lib/Checker/Environment.cpp index 7bf2929161c..954129883d6 100644 --- a/clang/lib/Checker/Environment.cpp +++ b/clang/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/clang/lib/Checker/GRExprEngine.cpp b/clang/lib/Checker/GRExprEngine.cpp index 2945de162a9..a24a5df4fb6 100644 --- a/clang/lib/Checker/GRExprEngine.cpp +++ b/clang/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() || |