Hi Jordan,
I suppose you wanted me to inline the allocator call during a call to new
first. This patch inlines the allocator call but i'm still facing few problems.
If i code as -
void* operator new(size_t num)
{
return 0;
}
int main() {
int* i = new int(1);
*i = 1;
delete i;
return 0;
}
In the above code we are not able to detect the null deref at *i = 1; . I
suppose that is because we are conjuring a new symbol in VisitCXXNewExpr which
is being used as output of new expression. My doubt was how do i make sure that
the VisitCXXNewExpr uses the output of VisitCXXNewAllocatorCall?
I tried something like -
1) conjure a symbol in VisitCXXNewAllocatorCall.
2) Bind it to conjured symbol to CXXNewExpr
3) Call getSVal in VisitCXXNewExpr with the CXXNewExpr and location context
to get back the conjured symbol.
but unfortunetly in VisitCXXNewExpr when i call getSVal with CXXNewExpr and
LocationContext i get the result as Unknown instead of the symbol conjured in
VisitCXXNewAllocatorCall.
How do i make sure that VisitCXXNewExpr uses the result of
VisitCXXNewAllocatorCall? It would be great if you could guide me here.
Thanks
Karthik Bhat
Hi jordan_rose,
http://llvm-reviews.chandlerc.com/D2616
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D2616?vs=6639&id=6709#toc
Files:
lib/StaticAnalyzer/Core/ExprEngine.cpp
lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
test/Analysis/NewDelete-custom.cpp
test/Analysis/inline.cpp
include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -553,12 +553,8 @@
void ExprEngine::ProcessNewAllocator(const CXXNewExpr *NE,
ExplodedNode *Pred) {
- //TODO: Implement VisitCXXNewAllocatorCall
ExplodedNodeSet Dst;
- NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
- const LocationContext *LCtx = Pred->getLocationContext();
- PostImplicitCall PP(NE->getOperatorNew(), NE->getLocStart(), LCtx);
- Bldr.generateNode(PP, Pred->getState(), Pred);
+ VisitCXXNewAllocatorCall(NE, Pred, Dst);
Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
}
Index: lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -664,9 +664,7 @@
break;
}
case CE_CXXAllocator:
- // Do not inline allocators until we model deallocators.
- // This is unfortunate, but basically necessary for smart pointers and
such.
- return CIP_DisallowedAlways;
+ break;
case CE_ObjCMessage:
if (!Opts.mayInlineObjCMethod())
return CIP_DisallowedAlways;
Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -329,6 +329,32 @@
*Call, *this);
}
+void ExprEngine::VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ ProgramStateRef State = Pred->getState();
+ const LocationContext *LCtx = Pred->getLocationContext();
+ CallEventManager &CEMgr = getStateManager().getCallEventManager();
+ CallEventRef<CXXAllocatorCall> Call =
+ CEMgr.getCXXAllocatorCall(CNE, State, LCtx);
+ PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
+ Call->getSourceRange().getBegin(),
+ "Error evaluating New Allocator Call");
+
+ ExplodedNodeSet DstPreCall;
+ getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,
+ *Call, *this);
+
+ ExplodedNodeSet DstInvalidated;
+ StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+ for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
+ I != E; ++I)
+ defaultEvalCall(Bldr, *I, *Call);
+ getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
+ *Call, *this);
+}
+
+
void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
// FIXME: Much of this should eventually migrate to CXXAllocatorCall.
Index: test/Analysis/NewDelete-custom.cpp
===================================================================
--- test/Analysis/NewDelete-custom.cpp
+++ test/Analysis/NewDelete-custom.cpp
@@ -28,6 +28,7 @@
}
#ifdef LEAKS
// expected-warning@-2{{Potential leak of memory pointed to by 'c3'}}
+// expected-warning@-4{{Potential memory leak}}
#endif
void testOpNewArray() {
@@ -39,6 +40,7 @@
}
#ifdef LEAKS
// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
+// expected-warning@-4{{Potential memory leak}}
#endif
@@ -52,6 +54,7 @@
}
#ifdef LEAKS
// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
+// expected-warning@-4{{Potential memory leak}}
#endif
Index: test/Analysis/inline.cpp
===================================================================
--- test/Analysis/inline.cpp
+++ test/Analysis/inline.cpp
@@ -9,6 +9,7 @@
// This is the standard placement new.
inline void* operator new(size_t, void* __p) throw()
{
+ clang_analyzer_checkInlined(true);// expected-warning{{TRUE}}
return __p;
}
Index: include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -421,6 +421,10 @@
const Stmt *S, bool IsBaseDtor,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
+ void VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -553,12 +553,8 @@
void ExprEngine::ProcessNewAllocator(const CXXNewExpr *NE,
ExplodedNode *Pred) {
- //TODO: Implement VisitCXXNewAllocatorCall
ExplodedNodeSet Dst;
- NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
- const LocationContext *LCtx = Pred->getLocationContext();
- PostImplicitCall PP(NE->getOperatorNew(), NE->getLocStart(), LCtx);
- Bldr.generateNode(PP, Pred->getState(), Pred);
+ VisitCXXNewAllocatorCall(NE, Pred, Dst);
Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
}
Index: lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -664,9 +664,7 @@
break;
}
case CE_CXXAllocator:
- // Do not inline allocators until we model deallocators.
- // This is unfortunate, but basically necessary for smart pointers and such.
- return CIP_DisallowedAlways;
+ break;
case CE_ObjCMessage:
if (!Opts.mayInlineObjCMethod())
return CIP_DisallowedAlways;
Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -329,6 +329,32 @@
*Call, *this);
}
+void ExprEngine::VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ ProgramStateRef State = Pred->getState();
+ const LocationContext *LCtx = Pred->getLocationContext();
+ CallEventManager &CEMgr = getStateManager().getCallEventManager();
+ CallEventRef<CXXAllocatorCall> Call =
+ CEMgr.getCXXAllocatorCall(CNE, State, LCtx);
+ PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
+ Call->getSourceRange().getBegin(),
+ "Error evaluating New Allocator Call");
+
+ ExplodedNodeSet DstPreCall;
+ getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,
+ *Call, *this);
+
+ ExplodedNodeSet DstInvalidated;
+ StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+ for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
+ I != E; ++I)
+ defaultEvalCall(Bldr, *I, *Call);
+ getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
+ *Call, *this);
+}
+
+
void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
// FIXME: Much of this should eventually migrate to CXXAllocatorCall.
Index: test/Analysis/NewDelete-custom.cpp
===================================================================
--- test/Analysis/NewDelete-custom.cpp
+++ test/Analysis/NewDelete-custom.cpp
@@ -28,6 +28,7 @@
}
#ifdef LEAKS
// expected-warning@-2{{Potential leak of memory pointed to by 'c3'}}
+// expected-warning@-4{{Potential memory leak}}
#endif
void testOpNewArray() {
@@ -39,6 +40,7 @@
}
#ifdef LEAKS
// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
+// expected-warning@-4{{Potential memory leak}}
#endif
@@ -52,6 +54,7 @@
}
#ifdef LEAKS
// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
+// expected-warning@-4{{Potential memory leak}}
#endif
Index: test/Analysis/inline.cpp
===================================================================
--- test/Analysis/inline.cpp
+++ test/Analysis/inline.cpp
@@ -9,6 +9,7 @@
// This is the standard placement new.
inline void* operator new(size_t, void* __p) throw()
{
+ clang_analyzer_checkInlined(true);// expected-warning{{TRUE}}
return __p;
}
Index: include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -421,6 +421,10 @@
const Stmt *S, bool IsBaseDtor,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
+ void VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits