forked from OSchip/llvm-project
[analyzer] Inline C++ operator new when c++-inline-allocators is turned on.
This will let us stage in the modeling of operator new. The -analyzer-config opton 'c++-inline-allocators' is currently off by default. Patch by Karthik Bhat! llvm-svn: 201122
This commit is contained in:
parent
5a69dda9b0
commit
8b808d64af
|
@ -199,6 +199,9 @@ private:
|
|||
/// \sa mayInlineTemplateFunctions
|
||||
Optional<bool> InlineTemplateFunctions;
|
||||
|
||||
/// \sa mayInlineCXXAllocator
|
||||
Optional<bool> InlineCXXAllocator;
|
||||
|
||||
/// \sa mayInlineCXXContainerCtorsAndDtors
|
||||
Optional<bool> InlineCXXContainerCtorsAndDtors;
|
||||
|
||||
|
@ -291,6 +294,12 @@ public:
|
|||
/// accepts the values "true" and "false".
|
||||
bool mayInlineTemplateFunctions();
|
||||
|
||||
/// Returns whether or not allocator call may be considered for inlining.
|
||||
///
|
||||
/// This is controlled by the 'c++-allocator-inlining' config option, which
|
||||
/// accepts the values "true" and "false".
|
||||
bool mayInlineCXXAllocator();
|
||||
|
||||
/// Returns whether or not constructors and destructors of C++ container
|
||||
/// objects may be considered for inlining.
|
||||
///
|
||||
|
|
|
@ -421,6 +421,10 @@ public:
|
|||
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);
|
||||
|
||||
|
|
|
@ -134,6 +134,12 @@ bool AnalyzerOptions::mayInlineTemplateFunctions() {
|
|||
/*Default=*/true);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::mayInlineCXXAllocator() {
|
||||
return getBooleanOption(InlineCXXAllocator,
|
||||
"c++-allocator-inlining",
|
||||
/*Default=*/false);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::mayInlineCXXContainerCtorsAndDtors() {
|
||||
return getBooleanOption(InlineCXXContainerCtorsAndDtors,
|
||||
"c++-container-inlining",
|
||||
|
|
|
@ -532,6 +532,11 @@ void CoreEngine::enqueueStmtNode(ExplodedNode *N,
|
|||
return;
|
||||
}
|
||||
|
||||
if ((*Block)[Idx].getKind() == CFGElement::NewAllocator) {
|
||||
WList->enqueue(N, Block, Idx+1);
|
||||
return;
|
||||
}
|
||||
|
||||
// At this point, we know we're processing a normal statement.
|
||||
CFGStmt CS = (*Block)[Idx].castAs<CFGStmt>();
|
||||
PostStmt Loc(CS.getStmt(), N->getLocationContext());
|
||||
|
|
|
@ -553,12 +553,20 @@ void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
|
|||
|
||||
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);
|
||||
AnalysisManager &AMgr = getAnalysisManager();
|
||||
AnalyzerOptions &Opts = AMgr.options;
|
||||
// TODO: We're not evaluating allocators for all cases just yet as
|
||||
// we're not handling the return value correctly, which causes false
|
||||
// positives when the alpha.cplusplus.NewDeleteLeaks check is on.
|
||||
if (Opts.mayInlineCXXAllocator())
|
||||
VisitCXXNewAllocatorCall(NE, Pred, Dst);
|
||||
else {
|
||||
NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
|
||||
const LocationContext *LCtx = Pred->getLocationContext();
|
||||
PostImplicitCall PP(NE->getOperatorNew(), NE->getLocStart(), LCtx);
|
||||
Bldr.generateNode(PP, Pred->getState(), Pred);
|
||||
}
|
||||
Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
|
||||
}
|
||||
|
||||
|
|
|
@ -329,6 +329,32 @@ void ExprEngine::VisitCXXDestructor(QualType ObjectType,
|
|||
*Call, *this);
|
||||
}
|
||||
|
||||
void ExprEngine::VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
|
||||
ExplodedNode *Pred,
|
||||
ExplodedNodeSet &Dst) {
|
||||
ProgramStateRef State = Pred->getState();
|
||||
const LocationContext *LCtx = Pred->getLocationContext();
|
||||
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
|
||||
CNE->getStartLoc(),
|
||||
"Error evaluating New Allocator Call");
|
||||
CallEventManager &CEMgr = getStateManager().getCallEventManager();
|
||||
CallEventRef<CXXAllocatorCall> Call =
|
||||
CEMgr.getCXXAllocatorCall(CNE, State, LCtx);
|
||||
|
||||
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.
|
||||
|
|
|
@ -664,6 +664,8 @@ static CallInlinePolicy mayInlineCallKind(const CallEvent &Call,
|
|||
break;
|
||||
}
|
||||
case CE_CXXAllocator:
|
||||
if (Opts.mayInlineCXXAllocator())
|
||||
break;
|
||||
// Do not inline allocators until we model deallocators.
|
||||
// This is unfortunate, but basically necessary for smart pointers and such.
|
||||
return CIP_DisallowedAlways;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config ipa=inlining -verify %s
|
||||
// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config ipa=inlining -analyzer-config c++-allocator-inlining=true -verify %s
|
||||
|
||||
void clang_analyzer_eval(bool);
|
||||
void clang_analyzer_checkInlined(bool);
|
||||
|
@ -9,6 +9,7 @@ extern "C" void *malloc(size_t);
|
|||
// This is the standard placement new.
|
||||
inline void* operator new(size_t, void* __p) throw()
|
||||
{
|
||||
clang_analyzer_checkInlined(true);// expected-warning{{TRUE}}
|
||||
return __p;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue