]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / contrib / llvm / tools / clang / lib / StaticAnalyzer / Checkers / UndefResultChecker.cpp
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 "ClangSACheckers.h"
16 #include "clang/StaticAnalyzer/Core/Checker.h"
17 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
18 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
19 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
20 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
21
22 using namespace clang;
23 using namespace ento;
24
25 namespace {
26 class UndefResultChecker 
27   : public Checker< check::PostStmt<BinaryOperator> > {
28
29   mutable llvm::OwningPtr<BugType> BT;
30   
31 public:
32   void checkPostStmt(const BinaryOperator *B, CheckerContext &C) const;
33 };
34 } // end anonymous namespace
35
36 void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
37                                        CheckerContext &C) const {
38   const ProgramState *state = C.getState();
39   if (state->getSVal(B).isUndef()) {
40     // Generate an error node.
41     ExplodedNode *N = C.generateSink();
42     if (!N)
43       return;
44     
45     if (!BT)
46       BT.reset(new BuiltinBug("Result of operation is garbage or undefined"));
47
48     llvm::SmallString<256> sbuf;
49     llvm::raw_svector_ostream OS(sbuf);
50     const Expr *Ex = NULL;
51     bool isLeft = true;
52     
53     if (state->getSVal(B->getLHS()).isUndef()) {
54       Ex = B->getLHS()->IgnoreParenCasts();
55       isLeft = true;
56     }
57     else if (state->getSVal(B->getRHS()).isUndef()) {
58       Ex = B->getRHS()->IgnoreParenCasts();
59       isLeft = false;
60     }
61     
62     if (Ex) {
63       OS << "The " << (isLeft ? "left" : "right")
64          << " operand of '"
65          << BinaryOperator::getOpcodeStr(B->getOpcode())
66          << "' is a garbage value";
67     }          
68     else {
69       // Neither operand was undefined, but the result is undefined.
70       OS << "The result of the '"
71          << BinaryOperator::getOpcodeStr(B->getOpcode())
72          << "' expression is undefined";
73     }
74     BugReport *report = new BugReport(*BT, OS.str(), N);
75     if (Ex) {
76       report->addRange(Ex->getSourceRange());
77       report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex));
78     }
79     else
80       report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, B));
81     C.EmitReport(report);
82   }
83 }
84
85 void ento::registerUndefResultChecker(CheckerManager &mgr) {
86   mgr.registerChecker<UndefResultChecker>();
87 }