Out << "Read objc fwd class decl\n";
} else if (isa<FileScopeAsmDecl>(D)) {
Out << "Read file scope asm decl\n";
- } else {
+ } else if (ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(D)) {
+ Out << "Read objc method decl: '" << MD->getSelector().getName()
+ << "'\n";
+ } else if (isa<ObjCImplementationDecl>(D)) {
+ Out << "Read objc implementation decl\n";
+ }
+ else {
assert(0 && "Unknown decl type!");
}
}
llvm::cerr << '\n';
}
}
+ else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ DeclPrinter().PrintObjCMethodDecl(MD);
+
+ if (MD->getBody()) {
+ llvm::cerr << '\n';
+ MD->getBody()->viewAST();
+ llvm::cerr << '\n';
+ }
+ }
}
};
}
CFGVisitor() : FName("") {}
// CFG Visitor interface to be implemented by subclass.
- virtual void VisitCFG(CFG& C, FunctionDecl& FD) = 0;
+ virtual void VisitCFG(CFG& C, Decl& CD) = 0;
virtual bool printFuncDeclStart() { return true; }
virtual void HandleTopLevelDecl(Decl *D);
} // end anonymous namespace
void CFGVisitor::HandleTopLevelDecl(Decl *D) {
- FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+
+ CFG *C = NULL;
+
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- if (!FD || !FD->getBody())
- return;
+ if (!FD->getBody())
+ return;
- if (FName.size() > 0 && FName != FD->getIdentifier()->getName())
- return;
+ if (FName.size() > 0 && FName != FD->getIdentifier()->getName())
+ return;
+
+ if (printFuncDeclStart()) {
+ DeclPrinter().PrintFunctionDeclStart(FD);
+ llvm::cerr << '\n';
+ }
- if (printFuncDeclStart()) {
- DeclPrinter().PrintFunctionDeclStart(FD);
- llvm::cerr << '\n';
+ C = CFG::buildCFG(FD->getBody());
}
+ else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+
+ if (!MD->getBody())
+ return;
+
+ if (printFuncDeclStart()) {
+ DeclPrinter().PrintObjCMethodDecl(MD);
+ llvm::cerr << '\n';
+ }
- CFG *C = CFG::buildCFG(FD->getBody());
+ C = CFG::buildCFG(MD->getBody());
+ }
if (C) {
- VisitCFG(*C, *FD);
+ VisitCFG(*C, *D);
delete C;
}
- else
- llvm::cerr << "warning: CFG could not be constructed.\n";
}
//===----------------------------------------------------------------------===//
CFGDumper(bool use_graphviz, const std::string& fname)
: CFGVisitor(fname), UseGraphviz(use_graphviz) {}
- virtual void VisitCFG(CFG& C, FunctionDecl&) {
+ virtual void VisitCFG(CFG& C, Decl&) {
if (UseGraphviz)
C.viewCFG();
else
SM = &Context.getSourceManager();
}
- virtual void VisitCFG(CFG& C, FunctionDecl& FD) {
+ virtual void VisitCFG(CFG& C, Decl& CD) {
LiveVariables L(C);
L.runOnCFG(C);
L.dumpBlockLiveness(*SM);
Ctx = &Context;
}
- virtual void VisitCFG(CFG& C, FunctionDecl& FD) {
+ virtual void VisitCFG(CFG& C, Decl& CD) {
CheckDeadStores(C, *Ctx, Diags);
}
Ctx = &Context;
}
- virtual void VisitCFG(CFG& C, FunctionDecl&) {
+ virtual void VisitCFG(CFG& C, Decl&) {
CheckUninitializedValues(C, *Ctx, Diags);
}
: CFGVisitor(fname), Diags(diags), Visualize(visualize), TrimGraph(trim){}
virtual void Initialize(ASTContext &Context) { Ctx = &Context; }
- virtual void VisitCFG(CFG& C, FunctionDecl&);
+ virtual void VisitCFG(CFG& C, Decl&);
virtual bool printFuncDeclStart() { return false; }
};
} // end anonymous namespace
return new GRSimpleValsVisitor(Diags, FunctionName, Visualize, TrimGraph);
}
-void GRSimpleValsVisitor::VisitCFG(CFG& C, FunctionDecl& FD) {
+void GRSimpleValsVisitor::VisitCFG(CFG& C, Decl& CD) {
- SourceLocation Loc = FD.getLocation();
+ SourceLocation Loc = CD.getLocation();
if (!Loc.isFileID() ||
Loc.getFileID() != Ctx->getSourceManager().getMainFileID())
return;
if (!Visualize) {
- llvm::cerr << "ANALYZE: " << FD.getIdentifier()->getName() << ' '
- << Ctx->getSourceManager().getSourceName(FD.getLocation())
- << ' ';
+
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(&CD)) {
+ llvm::cerr << "ANALYZE: " << FD->getIdentifier()->getName() << ' '
+ << Ctx->getSourceManager().getSourceName(FD->getLocation())
+ << ' ';
+ }
+ else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(&CD)) {
+ llvm::cerr << "ANALYZE (ObjC Method): "
+ << MD->getSelector().getName() << ' '
+ << Ctx->getSourceManager().getSourceName(MD->getLocation())
+ << ' ';
+ }
llvm::Timer T("GRSimpleVals");
T.startTimer();
- unsigned size = RunGRSimpleVals(C, FD, *Ctx, Diags, false, false);
+ unsigned size = RunGRSimpleVals(C, CD, *Ctx, Diags, false, false);
T.stopTimer();
llvm::cerr << size << ' ' << T.getWallTime() << '\n';
}
else {
llvm::cerr << '\n';
- RunGRSimpleVals(C, FD, *Ctx, Diags, Visualize, TrimGraph);
+ RunGRSimpleVals(C, CD, *Ctx, Diags, Visualize, TrimGraph);
}
}
: CFGVisitor(fname), Diags(diags) {}
virtual void Initialize(ASTContext &Context) { Ctx = &Context; }
- virtual void VisitCFG(CFG& C, FunctionDecl&);
+ virtual void VisitCFG(CFG& C, Decl&);
virtual bool printFuncDeclStart() { return false; }
};
} // end anonymous namespace
return new CFRefCountCheckerVisitor(Diags, FunctionName);
}
-void CFRefCountCheckerVisitor::VisitCFG(CFG& C, FunctionDecl& FD) {
+void CFRefCountCheckerVisitor::VisitCFG(CFG& C, Decl& CD) {
- SourceLocation Loc = FD.getLocation();
+ SourceLocation Loc = CD.getLocation();
if (!Loc.isFileID() ||
Loc.getFileID() != Ctx->getSourceManager().getMainFileID())
return;
- CheckCFRefCount(C, FD, *Ctx, Diags);
+ CheckCFRefCount(C, CD, *Ctx, Diags);
}
//===----------------------------------------------------------------------===//
#define LLVM_CLANG_ANALYSIS_EXPLODEDGRAPH
#include "clang/Analysis/ProgramPoint.h"
+#include "clang/AST/Decl.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/DepthFirstIterator.h"
+#include "llvm/Support/Casting.h"
namespace clang {
class GRSwitchNodeBuilderImpl;
class CFG;
class ASTContext;
-class FunctionDecl;
-
class ExplodedNodeImpl : public llvm::FoldingSetNode {
protected:
friend class ExplodedGraphImpl;
/// cfg - The CFG associated with this analysis graph.
CFG& cfg;
- /// FD - The function declaration of the function being analyzed.
- FunctionDecl& FD;
+ /// CodeDecl - The declaration containing the code being analyzed. This
+ /// can be a FunctionDecl or and ObjCMethodDecl.
+ Decl& CodeDecl;
- /// Ctx - The ASTContext used to "interpret" FD.
+ /// Ctx - The ASTContext used to "interpret" CodeDecl.
ASTContext& Ctx;
/// NumNodes - The number of nodes in the graph.
}
// ctor.
- ExplodedGraphImpl(CFG& c, FunctionDecl& f, ASTContext& ctx)
- : cfg(c), FD(f), Ctx(ctx), NumNodes(0) {}
+ ExplodedGraphImpl(CFG& c, Decl& cd, ASTContext& ctx)
+ : cfg(c), CodeDecl(cd), Ctx(ctx), NumNodes(0) {}
public:
virtual ~ExplodedGraphImpl() {}
llvm::BumpPtrAllocator& getAllocator() { return Allocator; }
CFG& getCFG() { return cfg; }
ASTContext& getContext() { return Ctx; }
- FunctionDecl& getFunctionDecl() { return FD; }
+
+ const Decl& getCodeDecl() const { return CodeDecl; }
+
+ const FunctionDecl* getFunctionDecl() const {
+ return llvm::dyn_cast<FunctionDecl>(&CodeDecl);
+ }
ExplodedGraphImpl* Trim(ExplodedNodeImpl** NBeg,
ExplodedNodeImpl** NEnd) const;
}
virtual ExplodedGraphImpl* MakeEmptyGraph() const {
- return new ExplodedGraph(cfg, FD, Ctx);
+ return new ExplodedGraph(cfg, CodeDecl, Ctx);
}
public:
- ExplodedGraph(CFG& c, FunctionDecl& fd, ASTContext& ctx)
- : ExplodedGraphImpl(c, fd, ctx), CheckerState(new CheckerTy(*this)) {}
+ ExplodedGraph(CFG& c, Decl& cd, ASTContext& ctx)
+ : ExplodedGraphImpl(c, cd, ctx), CheckerState(new CheckerTy(*this)) {}
/// getCheckerState - Returns the internal checker state associated
/// with the exploded graph. Ownership remains with the ExplodedGraph
public:
/// Construct a GRCoreEngine object to analyze the provided CFG using
/// a DFS exploration of the exploded graph.
- GRCoreEngine(CFG& cfg, FunctionDecl& fd, ASTContext& ctx)
- : GRCoreEngineImpl(new GraphTy(cfg, fd, ctx), GRWorkList::MakeDFS()),
+ GRCoreEngine(CFG& cfg, Decl& cd, ASTContext& ctx)
+ : GRCoreEngineImpl(new GraphTy(cfg, cd, ctx), GRWorkList::MakeDFS()),
Checker(static_cast<GraphTy*>(G.get())->getCheckerState()) {}
/// Construct a GRCoreEngine object to analyze the provided CFG and to
/// use the provided worklist object to execute the worklist algorithm.
/// The GRCoreEngine object assumes ownership of 'wlist'.
- GRCoreEngine(CFG& cfg, FunctionDecl& fd, ASTContext& ctx, GRWorkList* wlist)
- : GRCoreEngineImpl(new GraphTy(cfg, fd, ctx), wlist),
+ GRCoreEngine(CFG& cfg, Decl& cd, ASTContext& ctx, GRWorkList* wlist)
+ : GRCoreEngineImpl(new GraphTy(cfg, cd, ctx), wlist),
Checker(static_cast<GraphTy*>(G.get())->getCheckerState()) {}
virtual ~GRCoreEngine() {}