From 51dd6b2b022ade7a1fc4ec8c404d9b81c7e961f5 Mon Sep 17 00:00:00 2001 From: "Zancanaro; Carlo" Date: Tue, 27 Nov 2012 14:56:56 +1100 Subject: Updated solver stuff. This really should have already been in here... --- clang/lib/StaticAnalyzer/Checkers/IntervalTest.cpp | 102 ++++++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) (limited to 'clang/lib/StaticAnalyzer/Checkers') diff --git a/clang/lib/StaticAnalyzer/Checkers/IntervalTest.cpp b/clang/lib/StaticAnalyzer/Checkers/IntervalTest.cpp index badb671..c1e0273 100644 --- a/clang/lib/StaticAnalyzer/Checkers/IntervalTest.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/IntervalTest.cpp @@ -7,6 +7,15 @@ using namespace clang; using namespace ento; +using namespace std; + +#include +template +string toString(const T& obj) { + stringstream stream; + stream << obj; + return stream.str(); +} namespace { class IntervalTest: public Checker { @@ -14,7 +23,98 @@ public: void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, BugReporter &BR) const { if (IntervalAnalysis *a = mgr.getAnalysis(D)) { - a->runOnAllBlocks(*D); + CFG* cfg = mgr.getCFG(D); + + set variables; + + if (const FunctionDecl* func = dyn_cast(D)) { + for (unsigned int i = func->getNumParams(); i > 0; i--) { + variables.insert(func->getParamDecl(i-1)->getNameAsString()); + } + } + for (CFG::iterator + it = cfg->begin(), + ei = cfg->end(); + it != ei; + ++it) { + for (CFGBlock::iterator + block_it = (*it)->begin(), + block_end = (*it)->end(); + block_it != block_end; + block_it++) { + const CFGStmt* cfg_stmt = block_it->getAs(); + const Stmt* stmt = cfg_stmt->getStmt(); + if (stmt->getStmtClass() == Stmt::BinaryOperatorClass) { + const BinaryOperator* binop = static_cast(stmt); + if (binop->isAssignmentOp()) { + const Expr* left = binop->getLHS()->IgnoreParenCasts(); + if (left->getStmtClass() == Stmt::DeclRefExprClass) { + variables.insert(static_cast(left)->getNameInfo().getAsString()); + } + } + } else if (stmt->getStmtClass() == Stmt::DeclStmtClass) { + const DeclStmt* decl_stmt = static_cast(stmt); + for (DeclStmt::const_decl_iterator jt = decl_stmt->decl_begin(), + ej = decl_stmt->decl_end(); + jt != ej; + ++jt) { + if ((*jt)->getKind() == Decl::Var) { + const VarDecl* decl = static_cast(*jt); + variables.insert(decl->getNameAsString()); + jt++; + if (jt != ej) { + llvm::errs() << "Only the first declaration in a multi-declaration statement is used.\n"; + } + break; // only take the first one, for now + } + } + } + } + } + + + + vector labels; + ConstraintMatrix T; + set::iterator end = variables.end(); + for (set::iterator it = variables.begin(); + it != end; + ++it) { + map pos_row; + pos_row[*it] = 1; + T.push_back(pos_row); + labels.push_back(*it); + + map neg_row; + neg_row[*it] = -1; + T.push_back(neg_row); + labels.push_back("-" + *it); + + for (set::iterator jt = variables.begin(); + jt != end; + ++jt) { + if (it != jt) { + map diff_row; + diff_row[*it] = 1; + diff_row[*jt] = -1; + T.push_back(diff_row); + labels.push_back(*it + " - " + *jt); + } + } + } + + map > result = a->runOnAllBlocks(*D, T); + + for (map >::iterator + it = result.begin(), + ei = result.end(); + it != ei; + ++it) { + llvm::errs() << "Block " << toString(it->first->getBlockID()) << ": \n"; + for (unsigned int i = 0; i < T.size(); ++i) { + llvm::errs() << "\t" << labels[i] << " <= " << toString(it->second[i]) << "\n"; + } + } } } }; -- cgit v1.2.3