Refactor builtin function evaluation into a checker.
llvm-svn: 90847
This commit is contained in:
parent
3969e30d38
commit
fe2f901269
|
@ -0,0 +1,76 @@
|
|||
//=== BuiltinFunctionChecker.cpp --------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This checker evaluates clang builtin functions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "GRExprEngineInternalChecks.h"
|
||||
#include "clang/Analysis/PathSensitive/Checker.h"
|
||||
#include "clang/Basic/Builtins.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
namespace {
|
||||
|
||||
class BuiltinFunctionChecker : public Checker {
|
||||
public:
|
||||
static void *getTag() { static int tag = 0; return &tag; }
|
||||
virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void clang::RegisterBuiltinFunctionChecker(GRExprEngine &Eng) {
|
||||
Eng.registerCheck(new BuiltinFunctionChecker());
|
||||
}
|
||||
|
||||
bool BuiltinFunctionChecker::EvalCallExpr(CheckerContext &C,const CallExpr *CE){
|
||||
const GRState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = state->getSVal(Callee);
|
||||
const FunctionDecl *FD = L.getAsFunctionDecl();
|
||||
|
||||
if (!FD)
|
||||
return false;
|
||||
|
||||
unsigned id = FD->getBuiltinID();
|
||||
|
||||
if (!id)
|
||||
return false;
|
||||
|
||||
switch (id) {
|
||||
case Builtin::BI__builtin_expect: {
|
||||
// For __builtin_expect, just return the value of the subexpression.
|
||||
assert (CE->arg_begin() != CE->arg_end());
|
||||
SVal X = state->getSVal(*(CE->arg_begin()));
|
||||
C.GenerateNode(state->BindExpr(CE, X));
|
||||
return true;
|
||||
}
|
||||
|
||||
case Builtin::BI__builtin_alloca: {
|
||||
// FIXME: Refactor into StoreManager itself?
|
||||
MemRegionManager& RM = C.getStoreManager().getRegionManager();
|
||||
const MemRegion* R =
|
||||
RM.getAllocaRegion(CE, C.getNodeBuilder().getCurrentBlockCount(),
|
||||
C.getPredecessor()->getLocationContext());
|
||||
|
||||
// Set the extent of the region in bytes. This enables us to use the
|
||||
// SVal of the argument directly. If we save the extent in bits, we
|
||||
// cannot represent values like symbol*8.
|
||||
SVal Extent = state->getSVal(*(CE->arg_begin()));
|
||||
state = C.getStoreManager().setExtent(state, R, Extent);
|
||||
C.GenerateNode(state->BindExpr(CE, loc::MemRegionVal(R)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -10,6 +10,7 @@ add_clang_library(clangAnalysis
|
|||
BasicValueFactory.cpp
|
||||
BugReporter.cpp
|
||||
BugReporterVisitors.cpp
|
||||
BuiltinFunctionChecker.cpp
|
||||
CFG.cpp
|
||||
CFRefCount.cpp
|
||||
CallAndMessageChecker.cpp
|
||||
|
|
|
@ -244,6 +244,7 @@ static void RegisterInternalChecks(GRExprEngine &Eng) {
|
|||
|
||||
// This is not a checker yet.
|
||||
RegisterNoReturnFunctionChecker(Eng);
|
||||
RegisterBuiltinFunctionChecker(Eng);
|
||||
}
|
||||
|
||||
GRExprEngine::GRExprEngine(AnalysisManager &mgr)
|
||||
|
@ -1669,7 +1670,6 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, ExplodedNode* Pred,
|
|||
// Check for the "noreturn" attribute.
|
||||
|
||||
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
|
||||
const FunctionDecl* FD = L.getAsFunctionDecl();
|
||||
|
||||
ExplodedNodeSet DstTmp3, DstChecker, DstOther;
|
||||
|
||||
|
@ -1677,12 +1677,6 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, ExplodedNode* Pred,
|
|||
if (CheckerEvalCall(CE, DstChecker, *DI))
|
||||
DstTmp3 = DstChecker;
|
||||
else {
|
||||
//MarkNoReturnFunction(FD, CE, state, Builder);
|
||||
|
||||
// Evaluate the call.
|
||||
if (EvalBuiltinFunction(FD, CE, *DI, Dst))
|
||||
continue;
|
||||
|
||||
// Dispatch to the plug-in transfer function.
|
||||
SaveOr OldHasGen(Builder->HasGeneratedNode);
|
||||
Pred = *DI;
|
||||
|
@ -1691,7 +1685,6 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, ExplodedNode* Pred,
|
|||
// FIXME: Allow us to chain together transfer functions.
|
||||
assert(Builder && "GRStmtNodeBuilder must be defined.");
|
||||
|
||||
|
||||
if (!EvalOSAtomic(DstOther, *this, *Builder, CE, L, Pred))
|
||||
getTF().EvalCall(DstOther, *this, *Builder, CE, L, Pred);
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ void RegisterUndefBranchChecker(GRExprEngine &Eng);
|
|||
void RegisterUndefResultChecker(GRExprEngine &Eng);
|
||||
|
||||
void RegisterNoReturnFunctionChecker(GRExprEngine &Eng);
|
||||
void RegisterBuiltinFunctionChecker(GRExprEngine &Eng);
|
||||
|
||||
} // end clang namespace
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue