Refactor undefined result checker. This is the last one.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89750 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/UndefResultChecker.cpp b/lib/Analysis/UndefResultChecker.cpp
new file mode 100644
index 0000000..1911480
--- /dev/null
+++ b/lib/Analysis/UndefResultChecker.cpp
@@ -0,0 +1,86 @@
+//=== UndefResultChecker.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines UndefResultChecker, a builtin check in GRExprEngine that 
+// performs checks for undefined results of non-assignment binary operators.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GRExprEngineInternalChecks.h"
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN UndefResultChecker 
+  : public CheckerVisitor<UndefResultChecker> {
+
+  BugType *BT;
+  
+public:
+  UndefResultChecker() : BT(0) {}
+  static void *getTag() { static int tag = 0; return &tag; }
+  void PostVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+};
+} // end anonymous namespace
+
+void clang::RegisterUndefResultChecker(GRExprEngine &Eng) {
+  Eng.registerCheck(new UndefResultChecker());
+}
+
+void UndefResultChecker::PostVisitBinaryOperator(CheckerContext &C, 
+                                                 const BinaryOperator *B) {
+  const GRState *state = C.getState();
+  if (state->getSVal(B).isUndef()) {
+    // Generate an error node.
+    ExplodedNode *N = C.GenerateSink();
+    if (!N)
+      return;
+    
+    if (!BT)
+      BT = new BuiltinBug("Result of operation is garbage or undefined");
+
+    llvm::SmallString<256> sbuf;
+    llvm::raw_svector_ostream OS(sbuf);
+    const Expr *Ex = NULL;
+    bool isLeft = true;
+    
+    if (state->getSVal(B->getLHS()).isUndef()) {
+      Ex = B->getLHS()->IgnoreParenCasts();
+      isLeft = true;
+    }
+    else if (state->getSVal(B->getRHS()).isUndef()) {
+      Ex = B->getRHS()->IgnoreParenCasts();
+      isLeft = false;
+    }
+    
+    if (Ex) {
+      OS << "The " << (isLeft ? "left" : "right")
+         << " operand of '"
+         << BinaryOperator::getOpcodeStr(B->getOpcode())
+         << "' is a garbage value";
+    }          
+    else {
+      // Neither operand was undefined, but the result is undefined.
+      OS << "The result of the '"
+         << BinaryOperator::getOpcodeStr(B->getOpcode())
+         << "' expression is undefined";
+    }
+    EnhancedBugReport *report = new EnhancedBugReport(*BT, 
+                                                    OS.str().str().c_str(), N);
+    report->addRange(Ex->getSourceRange());
+    if (Ex)
+      report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
+    else
+      report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, B);
+    C.EmitReport(report);
+  }
+}