blob: f638dda2d8e9f5fa0e18969315ba54e0c05865fd [file] [log] [blame]
Jordy Rose93a9d822012-05-16 16:01:07 +00001//==- 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