aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhongxing Xu <xuzhongxing@gmail.com>2010-11-16 07:52:17 +0000
committerZhongxing Xu <xuzhongxing@gmail.com>2010-11-16 07:52:17 +0000
commit9dc84c9455df2a77195147d0210c915dc1775a88 (patch)
tree17f323502c631bd4a851a4ad8f5470d170c3f42a
parenta437ad3ec5b407ede394d74e6f9f463fa3657dbe (diff)
Handle member initializer in C++ ctor.
- Add a new Kind of ProgramPoint: PostInitializer. - Still use GRStmtNodeBuilder. But special handling PostInitializer in GRStmtNodeBuilder::GenerateAutoTransition(). - Someday we should clean up the interface of GRStmtNodeBuilder. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119335 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Expr.h2
-rw-r--r--include/clang/Analysis/ProgramPoint.h12
-rw-r--r--include/clang/Checker/PathSensitive/GRCoreEngine.h3
-rw-r--r--include/clang/Checker/PathSensitive/GRExprEngine.h2
-rw-r--r--lib/Checker/GRCXXExprEngine.cpp11
-rw-r--r--lib/Checker/GRCoreEngine.cpp17
-rw-r--r--lib/Checker/GRExprEngine.cpp40
-rw-r--r--test/Analysis/initializer.cpp14
8 files changed, 83 insertions, 18 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index eae3e69476..89295e4c7e 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -3468,7 +3468,7 @@ public:
BlockDeclRefExpr(ValueDecl *d, QualType t, SourceLocation l, bool ByRef,
bool constAdded = false,
Stmt *copyConstructorVal = 0)
- : Expr(BlockDeclRefExprClass, t, (!t.isNull() && t->isDependentType()),false),
+ : Expr(BlockDeclRefExprClass, t, (!t.isNull() && t->isDependentType()),false),
D(d), Loc(l), IsByRef(ByRef),
ConstQualAdded(constAdded), CopyConstructorVal(copyConstructorVal) {}
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index c29fd02c0a..a77ca39b15 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -44,6 +44,7 @@ public:
PostPurgeDeadSymbolsKind,
PostStmtCustomKind,
PostLValueKind,
+ PostInitializerKind,
CallEnterKind,
CallExitKind,
MinPostStmtKind = PostStmtKind,
@@ -304,6 +305,17 @@ public:
}
};
+class PostInitializer : public ProgramPoint {
+public:
+ PostInitializer(const CXXBaseOrMemberInitializer *I,
+ const LocationContext *L)
+ : ProgramPoint(I, PostInitializerKind, L) {}
+
+ static bool classof(const ProgramPoint *Location) {
+ return Location->getKind() == PostInitializerKind;
+ }
+};
+
class CallEnter : public StmtPoint {
public:
// L is caller's location context. AC is callee's AnalysisContext.
diff --git a/include/clang/Checker/PathSensitive/GRCoreEngine.h b/include/clang/Checker/PathSensitive/GRCoreEngine.h
index 411f29d802..58c148f66d 100644
--- a/include/clang/Checker/PathSensitive/GRCoreEngine.h
+++ b/include/clang/Checker/PathSensitive/GRCoreEngine.h
@@ -72,8 +72,7 @@ private:
void HandleBlockEdge(const BlockEdge& E, ExplodedNode* Pred);
void HandleBlockEntrance(const BlockEntrance& E, ExplodedNode* Pred);
void HandleBlockExit(const CFGBlock* B, ExplodedNode* Pred);
- void HandlePostStmt(const PostStmt& S, const CFGBlock* B,
- unsigned StmtIdx, ExplodedNode *Pred);
+ void HandlePostStmt(const CFGBlock* B, unsigned StmtIdx, ExplodedNode *Pred);
void HandleBranch(const Stmt* Cond, const Stmt* Term, const CFGBlock* B,
ExplodedNode* Pred);
diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h
index ab6a74dc34..80c53107b5 100644
--- a/include/clang/Checker/PathSensitive/GRExprEngine.h
+++ b/include/clang/Checker/PathSensitive/GRExprEngine.h
@@ -438,7 +438,7 @@ public:
ExplodedNodeSet &Dst);
/// Synthesize CXXThisRegion.
- const CXXThisRegion *getCXXThisRegion(const CXXMethodDecl *MD,
+ const CXXThisRegion *getCXXThisRegion(const CXXRecordDecl *RD,
const StackFrameContext *SFC);
/// Evaluate arguments with a work list algorithm.
diff --git a/lib/Checker/GRCXXExprEngine.cpp b/lib/Checker/GRCXXExprEngine.cpp
index 890387632f..072c21e721 100644
--- a/lib/Checker/GRCXXExprEngine.cpp
+++ b/lib/Checker/GRCXXExprEngine.cpp
@@ -64,10 +64,10 @@ void GRExprEngine::EvalArguments(ConstExprIterator AI, ConstExprIterator AE,
}
}
-const CXXThisRegion *GRExprEngine::getCXXThisRegion(const CXXMethodDecl *D,
+const CXXThisRegion *GRExprEngine::getCXXThisRegion(const CXXRecordDecl *D,
const StackFrameContext *SFC) {
- Type *T = D->getParent()->getTypeForDecl();
- QualType PT = getContext().getPointerType(QualType(T,0));
+ Type *T = D->getTypeForDecl();
+ QualType PT = getContext().getPointerType(QualType(T, 0));
return ValMgr.getRegionManager().getCXXThisRegion(PT, SFC);
}
@@ -121,7 +121,8 @@ void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
Pred->getLocationContext(),
E, Builder->getBlock(), Builder->getIndex());
- const CXXThisRegion *ThisR = getCXXThisRegion(E->getConstructor(), SFC);
+ const CXXThisRegion *ThisR =getCXXThisRegion(E->getConstructor()->getParent(),
+ SFC);
CallEnter Loc(E, SFC->getAnalysisContext(), Pred->getLocationContext());
for (ExplodedNodeSet::iterator NI = ArgsEvaluated.begin(),
@@ -182,7 +183,7 @@ void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
MCE,
Builder->getBlock(),
Builder->getIndex());
- const CXXThisRegion *ThisR = getCXXThisRegion(MD, SFC);
+ const CXXThisRegion *ThisR = getCXXThisRegion(MD->getParent(), SFC);
CallEnter Loc(MCE, SFC->getAnalysisContext(), Pred->getLocationContext());
for (ExplodedNodeSet::iterator I = PreVisitChecks.begin(),
E = PreVisitChecks.end(); I != E; ++I) {
diff --git a/lib/Checker/GRCoreEngine.cpp b/lib/Checker/GRCoreEngine.cpp
index 01d254c8f4..c77a0228e4 100644
--- a/lib/Checker/GRCoreEngine.cpp
+++ b/lib/Checker/GRCoreEngine.cpp
@@ -233,9 +233,9 @@ bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
break;
default:
- assert(isa<PostStmt>(Node->getLocation()));
- HandlePostStmt(cast<PostStmt>(Node->getLocation()), WU.getBlock(),
- WU.getIndex(), Node);
+ assert(isa<PostStmt>(Node->getLocation()) ||
+ isa<PostInitializer>(Node->getLocation()));
+ HandlePostStmt(WU.getBlock(), WU.getIndex(), Node);
break;
}
}
@@ -413,9 +413,8 @@ void GRCoreEngine::HandleBranch(const Stmt* Cond, const Stmt* Term,
ProcessBranch(Cond, Term, Builder);
}
-void GRCoreEngine::HandlePostStmt(const PostStmt& L, const CFGBlock* B,
- unsigned StmtIdx, ExplodedNode* Pred) {
-
+void GRCoreEngine::HandlePostStmt(const CFGBlock* B, unsigned StmtIdx,
+ ExplodedNode* Pred) {
assert (!B->empty());
if (StmtIdx == B->size())
@@ -473,6 +472,12 @@ void GRStmtNodeBuilder::GenerateAutoTransition(ExplodedNode* N) {
return;
}
+ // Do not create extra nodes. Move to the next CFG element.
+ if (isa<PostInitializer>(N->getLocation())) {
+ Eng.WList->Enqueue(N, &B, Idx+1);
+ return;
+ }
+
PostStmt Loc(getStmt(), N->getLocationContext());
if (Loc == N->getLocation()) {
diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp
index 017a6959cc..acb67d63dc 100644
--- a/lib/Checker/GRExprEngine.cpp
+++ b/lib/Checker/GRExprEngine.cpp
@@ -327,7 +327,7 @@ GRExprEngine::GRExprEngine(AnalysisManager &mgr, GRTransferFuncs *tf)
SymMgr(StateMgr.getSymbolManager()),
ValMgr(StateMgr.getValueManager()),
SVator(ValMgr.getSValuator()),
- CurrentStmt(NULL),
+ EntryNode(NULL), CurrentStmt(NULL),
NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL),
RaiseSel(GetNullarySelector("raise", getContext())),
BR(mgr, *this), TF(tf) {
@@ -679,8 +679,41 @@ void GRExprEngine::ProcessStmt(const CFGStmt S, GRStmtNodeBuilder& builder) {
Builder = NULL;
}
-void GRExprEngine::ProcessInitializer(const CFGInitializer I,
+void GRExprEngine::ProcessInitializer(const CFGInitializer Init,
GRStmtNodeBuilder &builder) {
+ // We don't set EntryNode and CurrentStmt. And we don't clean up state.
+ const CXXBaseOrMemberInitializer *BMI = Init.getInitializer();
+
+ ExplodedNode *Pred = builder.getBasePredecessor();
+ const LocationContext *LC = Pred->getLocationContext();
+
+ if (BMI->isMemberInitializer()) {
+ ExplodedNodeSet Dst;
+
+ // Evaluate the initializer.
+ Visit(BMI->getInit(), Pred, Dst);
+
+ for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); I != E; ++I){
+ ExplodedNode *Pred = *I;
+ const GRState *state = Pred->getState();
+
+ const FieldDecl *FD = BMI->getMember();
+ const RecordDecl *RD = FD->getParent();
+ const CXXThisRegion *ThisR = getCXXThisRegion(cast<CXXRecordDecl>(RD),
+ cast<StackFrameContext>(LC));
+
+ SVal ThisV = state->getSVal(ThisR);
+ SVal FieldLoc = state->getLValue(FD, ThisV);
+ SVal InitVal = state->getSVal(BMI->getInit());
+ state = state->bindLoc(FieldLoc, InitVal);
+
+ // Use a custom node building process.
+ PostInitializer PP(BMI, LC);
+ // Builder automatically add the generated node to the deferred set,
+ // which are processed in the builder's dtor.
+ builder.generateNode(PP, state, Pred);
+ }
+ }
}
void GRExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
@@ -1566,7 +1599,8 @@ void GRExprEngine::ProcessCallExit(GRCallExitNodeBuilder &B) {
// Bind the constructed object value to CXXConstructExpr.
if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
- const CXXThisRegion *ThisR = getCXXThisRegion(CCE->getConstructor(),LocCtx);
+ const CXXThisRegion *ThisR =
+ getCXXThisRegion(CCE->getConstructor()->getParent(), LocCtx);
// We might not have 'this' region in the binding if we didn't inline
// the ctor call.
SVal ThisV = state->getSVal(ThisR);
diff --git a/test/Analysis/initializer.cpp b/test/Analysis/initializer.cpp
new file mode 100644
index 0000000000..2fa3a9eb86
--- /dev/null
+++ b/test/Analysis/initializer.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store region -cfg-add-initializers -verify %s
+
+class A {
+ int x;
+public:
+ A();
+};
+
+A::A() : x(0) {
+ if (x != 0) {
+ int *p = 0;
+ *p = 0; // no-warning
+ }
+}