blob: 348573d21c6e4ebc304f0121841b77fabebdf633 [file] [log] [blame]
Zhongxing Xu668399b2009-11-24 08:24:26 +00001//=== 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//
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000010// This defines UndefResultChecker, a builtin check in ExprEngine that
Zhongxing Xu668399b2009-11-24 08:24:26 +000011// performs checks for undefined results of non-assignment binary operators.
12//
13//===----------------------------------------------------------------------===//
14
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000015#include "ExprEngineInternalChecks.h"
Argyrios Kyrtzidis98cabba2010-12-22 18:51:49 +000016#include "clang/GR/BugReporter/BugType.h"
17#include "clang/GR/PathSensitive/CheckerVisitor.h"
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000018#include "clang/GR/PathSensitive/ExprEngine.h"
Zhongxing Xu668399b2009-11-24 08:24:26 +000019
20using namespace clang;
Argyrios Kyrtzidis5a4f98f2010-12-22 18:53:20 +000021using namespace GR;
Zhongxing Xu668399b2009-11-24 08:24:26 +000022
23namespace {
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000024class UndefResultChecker
Zhongxing Xu668399b2009-11-24 08:24:26 +000025 : 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
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +000036void GR::RegisterUndefResultChecker(ExprEngine &Eng) {
Zhongxing Xu668399b2009-11-24 08:24:26 +000037 Eng.registerCheck(new UndefResultChecker());
38}
39
40void UndefResultChecker::PostVisitBinaryOperator(CheckerContext &C,
41 const BinaryOperator *B) {
42 const GRState *state = C.getState();
Ted Kremenek13976632010-02-08 16:18:51 +000043 if (state->getSVal(B).isUndef()) {
Zhongxing Xu668399b2009-11-24 08:24:26 +000044 // Generate an error node.
Ted Kremenekd048c6e2010-12-20 21:19:09 +000045 ExplodedNode *N = C.generateSink();
Zhongxing Xu668399b2009-11-24 08:24:26 +000046 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
Ted Kremenek13976632010-02-08 16:18:51 +000057 if (state->getSVal(B->getLHS()).isUndef()) {
Zhongxing Xu668399b2009-11-24 08:24:26 +000058 Ex = B->getLHS()->IgnoreParenCasts();
59 isLeft = true;
60 }
Ted Kremenek13976632010-02-08 16:18:51 +000061 else if (state->getSVal(B->getRHS()).isUndef()) {
Zhongxing Xu668399b2009-11-24 08:24:26 +000062 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 }
Benjamin Kramer4988a9a2009-11-29 18:03:28 +000078 EnhancedBugReport *report = new EnhancedBugReport(*BT, OS.str(), N);
Ted Kremenekd4daa7c2009-11-29 06:37:44 +000079 if (Ex) {
80 report->addRange(Ex->getSourceRange());
Zhongxing Xu668399b2009-11-24 08:24:26 +000081 report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
Ted Kremenekd4daa7c2009-11-29 06:37:44 +000082 }
Zhongxing Xu668399b2009-11-24 08:24:26 +000083 else
84 report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, B);
85 C.EmitReport(report);
86 }
87}