1 //==- ExprInspectionChecker.cpp - Used for regression tests ------*- C++ -*-==// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "ClangSACheckers.h" 11 #include "clang/StaticAnalyzer/Core/Checker.h" 12 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 13 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 14 15 using namespace clang; 16 using namespace ento; 17 18 namespace { 19 class ExprInspectionChecker : public Checker< eval::Call > { 20 mutable OwningPtr<BugType> BT; 21 public: 22 bool evalCall(const CallExpr *CE, CheckerContext &C) const; 23 }; 24 } 25 26 bool ExprInspectionChecker::evalCall(const CallExpr *CE, 27 CheckerContext &C) const { 28 // These checks should have no effect on the surrounding environment 29 // (globals should not be evaluated, etc), hence the use of evalCall. 30 ExplodedNode *N = C.getPredecessor(); 31 const LocationContext *LC = N->getLocationContext(); 32 33 if (!C.getCalleeName(CE).equals("clang_analyzer_eval")) 34 return false; 35 36 // A specific instantiation of an inlined function may have more constrained 37 // values than can generally be assumed. Skip the check. 38 if (LC->getParent() != 0) 39 return true; 40 41 const char *Msg = 0; 42 43 if (CE->getNumArgs() == 0) 44 Msg = "Missing assertion argument"; 45 else { 46 ProgramStateRef State = N->getState(); 47 const Expr *Assertion = CE->getArg(0); 48 SVal AssertionVal = State->getSVal(Assertion, LC); 49 50 if (AssertionVal.isUndef()) 51 Msg = "UNDEFINED"; 52 else { 53 ProgramStateRef StTrue, StFalse; 54 llvm::tie(StTrue, StFalse) = 55 State->assume(cast<DefinedOrUnknownSVal>(AssertionVal)); 56 57 if (StTrue) { 58 if (StFalse) 59 Msg = "UNKNOWN"; 60 else 61 Msg = "TRUE"; 62 } else { 63 if (StFalse) 64 Msg = "FALSE"; 65 else 66 llvm_unreachable("Invalid constraint; neither true or false."); 67 } 68 } 69 } 70 71 assert(Msg); 72 73 if (!BT) 74 BT.reset(new BugType("Checking analyzer assumptions", "debug")); 75 76 BugReport *R = new BugReport(*BT, Msg, N); 77 C.EmitReport(R); 78 79 return true; 80 } 81 82 void ento::registerExprInspectionChecker(CheckerManager &Mgr) { 83 Mgr.registerChecker<ExprInspectionChecker>(); 84 } 85 86