From ea6507fe0473c595b7fd7f45ef116355c5804939 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 6 Mar 2008 00:08:09 +0000 Subject: [PATCH] Added boilerplate to execute the CF reference count checker (which isn't yet implemented). llvm-svn: 47982 --- clang/Analysis/CFRefCount.cpp | 65 ++++++++++++++++++++ clang/Analysis/CFRefCount.h | 39 ++++++++++++ clang/Driver/ASTConsumers.cpp | 37 +++++++++++ clang/Driver/ASTConsumers.h | 3 + clang/Driver/clang.cpp | 6 ++ clang/include/clang/Analysis/LocalCheckers.h | 4 +- 6 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 clang/Analysis/CFRefCount.cpp create mode 100644 clang/Analysis/CFRefCount.h diff --git a/clang/Analysis/CFRefCount.cpp b/clang/Analysis/CFRefCount.cpp new file mode 100644 index 000000000000..188ce7084ce1 --- /dev/null +++ b/clang/Analysis/CFRefCount.cpp @@ -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 Engine(cfg, FD, Ctx); + GRExprEngine* CS = &Engine.getCheckerState(); + CFRefCount TF; + CS->setTransferFunctions(TF); + Engine.ExecuteWorkList(20000); + +} + +} + +void CFRefCount::EvalCall(ExplodedNodeSet& Dst, + ValueStateManager& StateMgr, + GRStmtNodeBuilder& Builder, + ValueManager& ValMgr, + CallExpr* CE, LVal L, + ExplodedNode* 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(V)) + St = StateMgr.SetRVal(St, cast(V), UnknownVal()); + } + + Builder.Nodify(Dst, CE, Pred, St); +} diff --git a/clang/Analysis/CFRefCount.h b/clang/Analysis/CFRefCount.h new file mode 100644 index 000000000000..efc1d679eca2 --- /dev/null +++ b/clang/Analysis/CFRefCount.h @@ -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& Dst, + ValueStateManager& StateMgr, + GRStmtNodeBuilder& Builder, + ValueManager& ValMgr, + CallExpr* CE, LVal L, + ExplodedNode* Pred); +}; + +} // end clang namespace + +#endif diff --git a/clang/Driver/ASTConsumers.cpp b/clang/Driver/ASTConsumers.cpp index c5e8e5ece77f..f8fbdc917300 100644 --- a/clang/Driver/ASTConsumers.cpp +++ b/clang/Driver/ASTConsumers.cpp @@ -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 diff --git a/clang/Driver/ASTConsumers.h b/clang/Driver/ASTConsumers.h index 85940c86f6f8..3d2f9495fa0d 100644 --- a/clang/Driver/ASTConsumers.h +++ b/clang/Driver/ASTConsumers.h @@ -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); diff --git a/clang/Driver/clang.cpp b/clang/Driver/clang.cpp index f5790df482e1..216e669ccca9 100644 --- a/clang/Driver/clang.cpp +++ b/clang/Driver/clang.cpp @@ -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); diff --git a/clang/include/clang/Analysis/LocalCheckers.h b/clang/include/clang/Analysis/LocalCheckers.h index f3f533c550ac..510e9a3cdef8 100644 --- a/clang/include/clang/Analysis/LocalCheckers.h +++ b/clang/include/clang/Analysis/LocalCheckers.h @@ -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