diff options
Diffstat (limited to 'lib/EntoSA')
89 files changed, 31482 insertions, 0 deletions
diff --git a/lib/EntoSA/AggExprVisitor.cpp b/lib/EntoSA/AggExprVisitor.cpp new file mode 100644 index 0000000000..c356186622 --- /dev/null +++ b/lib/EntoSA/AggExprVisitor.cpp @@ -0,0 +1,63 @@ +//=-- AggExprVisitor.cpp - evaluating expressions of C++ class type -*- C++ -*-= +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines AggExprVisitor class, which contains lots of boiler +// plate code for evaluating expressions of C++ class type. +// +//===----------------------------------------------------------------------===// + +#include "clang/EntoSA/PathSensitive/ExprEngine.h" +#include "clang/AST/StmtVisitor.h" + +using namespace clang; +using namespace ento; + +namespace { +/// AggExprVisitor is designed after AggExprEmitter of the CodeGen module. It +/// is used for evaluating exprs of C++ object type. Evaluating such exprs +/// requires a destination pointer pointing to the object being evaluated +/// into. Passing such a pointer around would pollute the Visit* interface of +/// ExprEngine. AggExprVisitor encapsulates code that goes through various +/// cast and construct exprs (and others), and at the final point, dispatches +/// back to the ExprEngine to let the real evaluation logic happen. +class AggExprVisitor : public StmtVisitor<AggExprVisitor> { + const MemRegion *Dest; + ExplodedNode *Pred; + ExplodedNodeSet &DstSet; + ExprEngine &Eng; + +public: + AggExprVisitor(const MemRegion *dest, ExplodedNode *N, ExplodedNodeSet &dst, + ExprEngine &eng) + : Dest(dest), Pred(N), DstSet(dst), Eng(eng) {} + + void VisitCastExpr(CastExpr *E); + void VisitCXXConstructExpr(CXXConstructExpr *E); +}; +} + +void AggExprVisitor::VisitCastExpr(CastExpr *E) { + switch (E->getCastKind()) { + default: + assert(0 && "Unhandled cast kind"); + case CK_NoOp: + case CK_ConstructorConversion: + Visit(E->getSubExpr()); + break; + } +} + +void AggExprVisitor::VisitCXXConstructExpr(CXXConstructExpr *E) { + Eng.VisitCXXConstructExpr(E, Dest, Pred, DstSet); +} + +void ExprEngine::VisitAggExpr(const Expr *E, const MemRegion *Dest, + ExplodedNode *Pred, ExplodedNodeSet &Dst) { + AggExprVisitor(Dest, Pred, Dst, *this).Visit(const_cast<Expr *>(E)); +} diff --git a/lib/EntoSA/AnalysisManager.cpp b/lib/EntoSA/AnalysisManager.cpp new file mode 100644 index 0000000000..fa64f472f7 --- /dev/null +++ b/lib/EntoSA/AnalysisManager.cpp @@ -0,0 +1,32 @@ +//===-- AnalysisManager.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/EntoSA/PathSensitive/AnalysisManager.h" +#include "clang/Index/Entity.h" +#include "clang/Index/Indexer.h" + +using namespace clang; +using namespace ento; + +AnalysisContext * +AnalysisManager::getAnalysisContextInAnotherTU(const Decl *D) { + idx::Entity Ent = idx::Entity::get(const_cast<Decl *>(D), + Idxer->getProgram()); + FunctionDecl *FuncDef; + idx::TranslationUnit *TU; + llvm::tie(FuncDef, TU) = Idxer->getDefinitionFor(Ent); + + if (FuncDef == 0) + return 0; + + // This AnalysisContext wraps function definition in another translation unit. + // But it is still owned by the AnalysisManager associated with the current + // translation unit. + return AnaCtxMgr.getContext(FuncDef, TU); +} diff --git a/lib/EntoSA/AnalyzerStatsChecker.cpp b/lib/EntoSA/AnalyzerStatsChecker.cpp new file mode 100644 index 0000000000..fb0e74b4b5 --- /dev/null +++ b/lib/EntoSA/AnalyzerStatsChecker.cpp @@ -0,0 +1,123 @@ +//==--AnalyzerStatsChecker.cpp - Analyzer visitation statistics --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This file reports various statistics about analyzer visitation. +//===----------------------------------------------------------------------===// + +#include "clang/EntoSA/PathSensitive/CheckerVisitor.h" +#include "clang/EntoSA/PathSensitive/ExplodedGraph.h" +#include "clang/EntoSA/BugReporter/BugReporter.h" + +// FIXME: Restructure checker registration. +#include "Checkers/ExprEngineExperimentalChecks.h" + +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/SmallPtrSet.h" + +using namespace clang; +using namespace ento; + +namespace { +class AnalyzerStatsChecker : public CheckerVisitor<AnalyzerStatsChecker> { +public: + static void *getTag(); + void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B, ExprEngine &Eng); + +private: + llvm::SmallPtrSet<const CFGBlock*, 256> reachable; +}; +} + +void *AnalyzerStatsChecker::getTag() { + static int x = 0; + return &x; +} + +void ento::RegisterAnalyzerStatsChecker(ExprEngine &Eng) { + Eng.registerCheck(new AnalyzerStatsChecker()); +} + +void AnalyzerStatsChecker::VisitEndAnalysis(ExplodedGraph &G, + BugReporter &B, + ExprEngine &Eng) { + const CFG *C = 0; + const Decl *D = 0; + const LocationContext *LC = 0; + const SourceManager &SM = B.getSourceManager(); + + // Iterate over explodedgraph + for (ExplodedGraph::node_iterator I = G.nodes_begin(); + I != G.nodes_end(); ++I) { + const ProgramPoint &P = I->getLocation(); + // Save the LocationContext if we don't have it already + if (!LC) + LC = P.getLocationContext(); + + if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) { + const CFGBlock *CB = BE->getBlock(); + reachable.insert(CB); + } + } + + // Get the CFG and the Decl of this block + C = LC->getCFG(); + D = LC->getAnalysisContext()->getDecl(); + + unsigned total = 0, unreachable = 0; + + // Find CFGBlocks that were not covered by any node + for (CFG::const_iterator I = C->begin(); I != C->end(); ++I) { + const CFGBlock *CB = *I; + ++total; + // Check if the block is unreachable + if (!reachable.count(CB)) { + ++unreachable; + } + } + + // We never 'reach' the entry block, so correct the unreachable count + unreachable--; + + // Generate the warning string + llvm::SmallString<128> buf; + llvm::raw_svector_ostream output(buf); + PresumedLoc Loc = SM.getPresumedLoc(D->getLocation()); + if (Loc.isValid()) { + output << Loc.getFilename() << " : "; + + if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) { + const NamedDecl *ND = cast<NamedDecl>(D); + output << ND; + } + else if (isa<BlockDecl>(D)) { + output << "block(line:" << Loc.getLine() << ":col:" << Loc.getColumn(); + } + } + + output << " -> Total CFGBlocks: " << total << " | Unreachable CFGBlocks: " + << unreachable << " | Aborted Block: " + << (Eng.wasBlockAborted() ? "yes" : "no") + << " | Empty WorkList: " + << (Eng.hasEmptyWorkList() ? "yes" : "no"); + + B.EmitBasicReport("Analyzer Statistics", "Internal Statistics", output.str(), + D->getLocation()); + + // Emit warning for each block we bailed out on + typedef CoreEngine::BlocksAborted::const_iterator AbortedIterator; + const CoreEngine &CE = Eng.getCoreEngine(); + for (AbortedIterator I = CE.blocks_aborted_begin(), + E = CE.blocks_aborted_end(); I != E; ++I) { + const BlockEdge &BE = I->first; + const CFGBlock *Exit = BE.getDst(); + const CFGElement &CE = Exit->front(); + if (const CFGStmt *CS = dyn_cast<CFGStmt>(&CE)) + B.EmitBasicReport("Bailout Point", "Internal Statistics", "The analyzer " + "stopped analyzing at this point", CS->getStmt()->getLocStart()); + } +} diff --git a/lib/EntoSA/BasicConstraintManager.cpp b/lib/EntoSA/BasicConstraintManager.cpp new file mode 100644 index 0000000000..92837d2ff4 --- /dev/null +++ b/lib/EntoSA/BasicConstraintManager.cpp @@ -0,0 +1,338 @@ +//== BasicConstraintManager.cpp - Manage basic constraints.------*- C++ -*--==// +// |