[analyzer] Refactoring: Move stuff into namespace 'GR'.
[clang.git] / lib / GR / Checkers / CastSizeChecker.cpp
blobbcbb89441f46ad888351eedcfa9275afc2ca3495
1 //=== CastSizeChecker.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 // CastSizeChecker checks when casting a malloc'ed symbolic region to type T,
11 // whether the size of the symbolic region is a multiple of the size of T.
13 //===----------------------------------------------------------------------===//
14 #include "clang/AST/CharUnits.h"
15 #include "clang/GR/BugReporter/BugType.h"
16 #include "clang/GR/PathSensitive/CheckerVisitor.h"
17 #include "GRExprEngineInternalChecks.h"
19 using namespace clang;
20 using namespace GR;
22 namespace {
23 class CastSizeChecker : public CheckerVisitor<CastSizeChecker> {
24 BuiltinBug *BT;
25 public:
26 CastSizeChecker() : BT(0) {}
27 static void *getTag();
28 void PreVisitCastExpr(CheckerContext &C, const CastExpr *B);
32 void *CastSizeChecker::getTag() {
33 static int x;
34 return &x;
37 void CastSizeChecker::PreVisitCastExpr(CheckerContext &C, const CastExpr *CE) {
38 const Expr *E = CE->getSubExpr();
39 ASTContext &Ctx = C.getASTContext();
40 QualType ToTy = Ctx.getCanonicalType(CE->getType());
41 PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr());
43 if (!ToPTy)
44 return;
46 QualType ToPointeeTy = ToPTy->getPointeeType();
48 // Only perform the check if 'ToPointeeTy' is a complete type.
49 if (ToPointeeTy->isIncompleteType())
50 return;
52 const GRState *state = C.getState();
53 const MemRegion *R = state->getSVal(E).getAsRegion();
54 if (R == 0)
55 return;
57 const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R);
58 if (SR == 0)
59 return;
61 SValBuilder &svalBuilder = C.getSValBuilder();
62 SVal extent = SR->getExtent(svalBuilder);
63 const llvm::APSInt *extentInt = svalBuilder.getKnownValue(state, extent);
64 if (!extentInt)
65 return;
67 CharUnits regionSize = CharUnits::fromQuantity(extentInt->getSExtValue());
68 CharUnits typeSize = C.getASTContext().getTypeSizeInChars(ToPointeeTy);
70 // Ignore void, and a few other un-sizeable types.
71 if (typeSize.isZero())
72 return;
74 if (regionSize % typeSize != 0) {
75 if (ExplodedNode *errorNode = C.generateSink()) {
76 if (!BT)
77 BT = new BuiltinBug("Cast region with wrong size.",
78 "Cast a region whose size is not a multiple of the"
79 " destination type size.");
80 RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(),
81 errorNode);
82 R->addRange(CE->getSourceRange());
83 C.EmitReport(R);
89 void GR::RegisterCastSizeChecker(GRExprEngine &Eng) {
90 Eng.registerCheck(new CastSizeChecker());