clang API Documentation

UndefResultChecker.cpp
Go to the documentation of this file.
00001 //=== UndefResultChecker.cpp ------------------------------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This defines UndefResultChecker, a builtin check in ExprEngine that 
00011 // performs checks for undefined results of non-assignment binary operators.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "ClangSACheckers.h"
00016 #include "clang/StaticAnalyzer/Core/Checker.h"
00017 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
00018 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
00019 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
00020 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
00021 #include "llvm/ADT/SmallString.h"
00022 
00023 using namespace clang;
00024 using namespace ento;
00025 
00026 namespace {
00027 class UndefResultChecker 
00028   : public Checker< check::PostStmt<BinaryOperator> > {
00029 
00030   mutable OwningPtr<BugType> BT;
00031   
00032 public:
00033   void checkPostStmt(const BinaryOperator *B, CheckerContext &C) const;
00034 };
00035 } // end anonymous namespace
00036 
00037 void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
00038                                        CheckerContext &C) const {
00039   ProgramStateRef state = C.getState();
00040   const LocationContext *LCtx = C.getLocationContext();
00041   if (state->getSVal(B, LCtx).isUndef()) {
00042     // Generate an error node.
00043     ExplodedNode *N = C.generateSink();
00044     if (!N)
00045       return;
00046     
00047     if (!BT)
00048       BT.reset(new BuiltinBug("Result of operation is garbage or undefined"));
00049 
00050     SmallString<256> sbuf;
00051     llvm::raw_svector_ostream OS(sbuf);
00052     const Expr *Ex = NULL;
00053     bool isLeft = true;
00054     
00055     if (state->getSVal(B->getLHS(), LCtx).isUndef()) {
00056       Ex = B->getLHS()->IgnoreParenCasts();
00057       isLeft = true;
00058     }
00059     else if (state->getSVal(B->getRHS(), LCtx).isUndef()) {
00060       Ex = B->getRHS()->IgnoreParenCasts();
00061       isLeft = false;
00062     }
00063     
00064     if (Ex) {
00065       OS << "The " << (isLeft ? "left" : "right")
00066          << " operand of '"
00067          << BinaryOperator::getOpcodeStr(B->getOpcode())
00068          << "' is a garbage value";
00069     }          
00070     else {
00071       // Neither operand was undefined, but the result is undefined.
00072       OS << "The result of the '"
00073          << BinaryOperator::getOpcodeStr(B->getOpcode())
00074          << "' expression is undefined";
00075     }
00076     BugReport *report = new BugReport(*BT, OS.str(), N);
00077     if (Ex) {
00078       report->addRange(Ex->getSourceRange());
00079       report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex,
00080                                                                       report));
00081     }
00082     else
00083       report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, B,
00084                                                                       report));
00085     C.EmitReport(report);
00086   }
00087 }
00088 
00089 void ento::registerUndefResultChecker(CheckerManager &mgr) {
00090   mgr.registerChecker<UndefResultChecker>();
00091 }