Added boilerplate to execute the CF reference count checker (which isn't yet implemented).

llvm-svn: 47982
This commit is contained in:
Ted Kremenek 2008-03-06 00:08:09 +00:00
parent dcabdb1b38
commit ea6507fe04
6 changed files with 153 additions and 1 deletions

View File

@ -0,0 +1,65 @@
// CFRefCount.cpp - Transfer functions for tracking simple values -*- C++ -*--
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This files defines the methods for CFRefCount, which implements
// a reference count checker for Core Foundation (Mac OS X).
//
//===----------------------------------------------------------------------===//
#include "CFRefCount.h"
#include "clang/Analysis/PathSensitive/ValueState.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Analysis/LocalCheckers.h"
using namespace clang;
namespace clang {
void CheckCFRefCount(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
Diagnostic& Diag) {
if (Diag.hasErrorOccurred())
return;
// FIXME: Refactor some day so this becomes a single function invocation.
GRCoreEngine<GRExprEngine> Engine(cfg, FD, Ctx);
GRExprEngine* CS = &Engine.getCheckerState();
CFRefCount TF;
CS->setTransferFunctions(TF);
Engine.ExecuteWorkList(20000);
}
}
void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
ValueStateManager& StateMgr,
GRStmtNodeBuilder<ValueState>& Builder,
ValueManager& ValMgr,
CallExpr* CE, LVal L,
ExplodedNode<ValueState>* Pred) {
ValueState* St = Pred->getState();
// Invalidate all arguments passed in by reference (LVals).
for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
I != E; ++I) {
RVal V = StateMgr.GetRVal(St, *I);
if (isa<LVal>(V))
St = StateMgr.SetRVal(St, cast<LVal>(V), UnknownVal());
}
Builder.Nodify(Dst, CE, Pred, St);
}

View File

@ -0,0 +1,39 @@
// CFRefCount.h - Transfer functions for the CF Ref. Count checker -*- C++ -*---
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This files defines CFRefCount, which defines the transfer functions
// to implement the Core Foundation reference count checker.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_GRREFCOUNT
#define LLVM_CLANG_ANALYSIS_GRREFCOUNT
#include "GRSimpleVals.h"
namespace clang {
class CFRefCount : public GRSimpleVals {
public:
CFRefCount() {}
virtual ~CFRefCount() {}
// Calls.
virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
ValueStateManager& StateMgr,
GRStmtNodeBuilder<ValueState>& Builder,
ValueManager& ValMgr,
CallExpr* CE, LVal L,
ExplodedNode<ValueState>* Pred);
};
} // end clang namespace
#endif

View File

@ -636,6 +636,43 @@ void GRSimpleValsVisitor::VisitCFG(CFG& C, FunctionDecl& FD) {
}
}
//===----------------------------------------------------------------------===//
// Core Foundation Reference Counting Checker
namespace {
class CFRefCountCheckerVisitor : public CFGVisitor {
Diagnostic &Diags;
ASTContext* Ctx;
public:
CFRefCountCheckerVisitor(Diagnostic &diags, const std::string& fname)
: CFGVisitor(fname), Diags(diags) {}
virtual void Initialize(ASTContext &Context) { Ctx = &Context; }
virtual void VisitCFG(CFG& C, FunctionDecl&);
virtual bool printFuncDeclStart() { return false; }
};
} // end anonymous namespace
ASTConsumer* clang::CreateCFRefChecker(Diagnostic &Diags,
const std::string& FunctionName) {
return new CFRefCountCheckerVisitor(Diags, FunctionName);
}
void CFRefCountCheckerVisitor::VisitCFG(CFG& C, FunctionDecl& FD) {
SourceLocation Loc = FD.getLocation();
if (!Loc.isFileID() ||
Loc.getFileID() != Ctx->getSourceManager().getMainFileID())
return;
CheckCFRefCount(C, FD, *Ctx, Diags);
}
//===----------------------------------------------------------------------===//
// AST Serializer

View File

@ -45,6 +45,9 @@ ASTConsumer *CreateUnitValsChecker(Diagnostic &Diags);
ASTConsumer *CreateGRSimpleVals(Diagnostic &Diags,
const std::string& Function,
bool Visualize = false);
ASTConsumer* CreateCFRefChecker(Diagnostic &Diags,
const std::string& FunctionName);
ASTConsumer *CreateCodeRewriterTest(const std::string& InFile,
Diagnostic &Diags);

View File

@ -71,6 +71,7 @@ enum ProgActions {
AnalysisLiveVariables, // Print results of live-variable analysis.
AnalysisGRSimpleVals, // Perform graph-reachability constant prop.
AnalysisGRSimpleValsView, // Visualize results of path-sens. analysis.
CheckerCFRef, // Run the Core Foundation Ref. Count Checker.
WarnDeadStores, // Run DeadStores checker on parsed ASTs.
WarnDeadStoresCheck, // Check diagnostics for "DeadStores".
WarnUninitVals, // Run UnitializedVariables checker.
@ -119,6 +120,8 @@ ProgAction(llvm::cl::desc("Choose output type:"), llvm::cl::ZeroOrMore,
"Perform path-sensitive constant propagation."),
clEnumValN(AnalysisGRSimpleValsView, "grsimple-view",
"View results of path-sensitive constant propagation."),
clEnumValN(CheckerCFRef, "check-cfref",
"Run the Core Foundation reference count checker."),
clEnumValN(TestSerialization, "test-pickling",
"Run prototype serializtion code."),
clEnumValN(EmitLLVM, "emit-llvm",
@ -1038,6 +1041,9 @@ static ASTConsumer* CreateASTConsumer(const std::string& InFile,
case AnalysisGRSimpleValsView:
return CreateGRSimpleVals(Diag, AnalyzeSpecificFunction, true);
case CheckerCFRef:
return CreateCFRefChecker(Diag, AnalyzeSpecificFunction);
case TestSerialization:
return CreateSerializationTest(Diag, FileMgr, LangOpts);

View File

@ -27,7 +27,9 @@ void CheckDeadStores(CFG& cfg, FunctionDecl& FD, ASTContext &Ctx,
void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags,
bool FullUninitTaint=false);
void CheckCFRefCount(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
Diagnostic& Diag);
} // end namespace clang