UndefResultChecker.cpp revision 04291a7c76e16a2dc5433c80c3d13c826bf372dc
1//=== UndefResultChecker.cpp ------------------------------------*- 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// This defines UndefResultChecker, a builtin check in ExprEngine that
11// performs checks for undefined results of non-assignment binary operators.
12//
13//===----------------------------------------------------------------------===//
14
15#include "InternalChecks.h"
16#include "clang/StaticAnalyzer/BugReporter/BugType.h"
17#include "clang/StaticAnalyzer/PathSensitive/CheckerVisitor.h"
18#include "clang/StaticAnalyzer/PathSensitive/ExprEngine.h"
19
20using namespace clang;
21using namespace ento;
22
23namespace {
24class UndefResultChecker
25  : public CheckerVisitor<UndefResultChecker> {
26
27  BugType *BT;
28
29public:
30  UndefResultChecker() : BT(0) {}
31  static void *getTag() { static int tag = 0; return &tag; }
32  void PostVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
33};
34} // end anonymous namespace
35
36void ento::RegisterUndefResultChecker(ExprEngine &Eng) {
37  Eng.registerCheck(new UndefResultChecker());
38}
39
40void UndefResultChecker::PostVisitBinaryOperator(CheckerContext &C,
41                                                 const BinaryOperator *B) {
42  const GRState *state = C.getState();
43  if (state->getSVal(B).isUndef()) {
44    // Generate an error node.
45    ExplodedNode *N = C.generateSink();
46    if (!N)
47      return;
48
49    if (!BT)
50      BT = new BuiltinBug("Result of operation is garbage or undefined");
51
52    llvm::SmallString<256> sbuf;
53    llvm::raw_svector_ostream OS(sbuf);
54    const Expr *Ex = NULL;
55    bool isLeft = true;
56
57    if (state->getSVal(B->getLHS()).isUndef()) {
58      Ex = B->getLHS()->IgnoreParenCasts();
59      isLeft = true;
60    }
61    else if (state->getSVal(B->getRHS()).isUndef()) {
62      Ex = B->getRHS()->IgnoreParenCasts();
63      isLeft = false;
64    }
65
66    if (Ex) {
67      OS << "The " << (isLeft ? "left" : "right")
68         << " operand of '"
69         << BinaryOperator::getOpcodeStr(B->getOpcode())
70         << "' is a garbage value";
71    }
72    else {
73      // Neither operand was undefined, but the result is undefined.
74      OS << "The result of the '"
75         << BinaryOperator::getOpcodeStr(B->getOpcode())
76         << "' expression is undefined";
77    }
78    EnhancedBugReport *report = new EnhancedBugReport(*BT, OS.str(), N);
79    if (Ex) {
80      report->addRange(Ex->getSourceRange());
81      report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
82    }
83    else
84      report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, B);
85    C.EmitReport(report);
86  }
87}
88