ExprInspectionChecker.cpp revision 93a9d828378b5c969344f27aeb275b8c2a19d918
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
15using namespace clang;
16using namespace ento;
17
18namespace {
19class ExprInspectionChecker : public Checker< eval::Call > {
20  mutable OwningPtr<BugType> BT;
21public:
22  bool evalCall(const CallExpr *CE, CheckerContext &C) const;
23};
24}
25
26bool 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
82void ento::registerExprInspectionChecker(CheckerManager &Mgr) {
83  Mgr.registerChecker<ExprInspectionChecker>();
84}
85
86