]> granicus.if.org Git - clang/commitdiff
[analyzer] Remove SVal::getAsVarDecl() and reason about MemRegions, not Decls. Sugges...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 1 Mar 2011 01:47:48 +0000 (01:47 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 1 Mar 2011 01:47:48 +0000 (01:47 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126734 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
lib/StaticAnalyzer/Core/SVals.cpp

index 35c7274f7d3f8226977877f9524647be8a584c45..0d430794e76cb4e924323ac79d435be0370c235e 100644 (file)
@@ -125,10 +125,6 @@ public:
   /// Otherwise return 0.
   const FunctionDecl* getAsFunctionDecl() const;
 
-  /// \brief If this SVal is a MemRegionVal and wraps a VarDecl,
-  /// return that VarDecl. Otherwise return 0.
-  const VarDecl* getAsVarDecl() const;
-
   /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and
   ///  wraps a symbol, return that SymbolRef.  Otherwise return NULL.
   SymbolRef getAsLocSymbol() const;
index c4d533150d8683cdcad8fc71b307a007181d4e82..307d185fed13a2d2494a08602b82e72da2eb0971 100644 (file)
@@ -28,8 +28,8 @@
 using namespace clang;
 using namespace ento;
 
-static bool IsNSError(const ParmVarDecl *PD, IdentifierInfo *II);
-static bool IsCFError(const ParmVarDecl *PD, IdentifierInfo *II);
+static bool IsNSError(QualType T, IdentifierInfo *II);
+static bool IsCFError(QualType T, IdentifierInfo *II);
 
 //===----------------------------------------------------------------------===//
 // NSErrorMethodChecker
@@ -62,7 +62,7 @@ void NSErrorMethodChecker::checkASTDecl(const ObjCMethodDecl *D,
   bool hasNSError = false;
   for (ObjCMethodDecl::param_iterator
          I = D->param_begin(), E = D->param_end(); I != E; ++I)  {
-    if (IsNSError(*I, II)) {
+    if (IsNSError((*I)->getType(), II)) {
       hasNSError = true;
       break;
     }
@@ -108,7 +108,7 @@ void CFErrorFunctionChecker::checkASTDecl(const FunctionDecl *D,
   bool hasCFError = false;
   for (FunctionDecl::param_const_iterator
          I = D->param_begin(), E = D->param_end(); I != E; ++I)  {
-    if (IsCFError(*I, II)) {
+    if (IsCFError((*I)->getType(), II)) {
       hasCFError = true;
       break;
     }
@@ -191,6 +191,17 @@ static void setFlag(const GRState *state, SVal val, CheckerContext &C) {
     C.addTransition(state->set<T>(sym, true));
 }
 
+static QualType parameterTypeFromSVal(SVal val) {
+  if (const loc::MemRegionVal* X = dyn_cast<loc::MemRegionVal>(&val)) {
+    const MemRegion* R = X->getRegion();
+    if (const VarRegion *VR = R->getAs<VarRegion>())
+      if (VR->hasStackParametersStorage())
+        return VR->getValueType();
+  }
+
+  return QualType();
+}
+
 void NSOrCFErrorDerefChecker::checkLocation(SVal loc, bool isLoad,
                                             CheckerContext &C) const {
   if (!isLoad)
@@ -198,6 +209,7 @@ void NSOrCFErrorDerefChecker::checkLocation(SVal loc, bool isLoad,
   if (loc.isUndef() || !isa<Loc>(loc))
     return;
 
+  ASTContext &Ctx = C.getASTContext();
   const GRState *state = C.getState();
 
   // If we are loading from NSError**/CFErrorRef* parameter, mark the resulting
@@ -205,23 +217,22 @@ void NSOrCFErrorDerefChecker::checkLocation(SVal loc, bool isLoad,
   // ImplicitNullDerefEvent event.
   // FIXME: Cumbersome! Maybe add hook at construction of SVals at start of
   // function ?
-  
-  const VarDecl *VD = loc.getAsVarDecl();
-  if (!VD) return;
-  const ParmVarDecl *PD = dyn_cast<ParmVarDecl>(VD);
-  if (!PD) return;
+
+  QualType parmT = parameterTypeFromSVal(loc);
+  if (parmT.isNull())
+    return;
 
   if (!NSErrorII)
-    NSErrorII = &PD->getASTContext().Idents.get("NSError");
+    NSErrorII = &Ctx.Idents.get("NSError");
   if (!CFErrorII)
-    CFErrorII = &PD->getASTContext().Idents.get("CFErrorRef");
+    CFErrorII = &Ctx.Idents.get("CFErrorRef");
 
-  if (ShouldCheckNSError && IsNSError(PD, NSErrorII)) {
+  if (ShouldCheckNSError && IsNSError(parmT, NSErrorII)) {
     setFlag<NSErrorOut>(state, state->getSVal(cast<Loc>(loc)), C);
     return;
   }
 
-  if (ShouldCheckCFError && IsCFError(PD, CFErrorII)) {
+  if (ShouldCheckCFError && IsCFError(parmT, CFErrorII)) {
     setFlag<CFErrorOut>(state, state->getSVal(cast<Loc>(loc)), C);
     return;
   }
@@ -267,9 +278,9 @@ void NSOrCFErrorDerefChecker::checkEvent(ImplicitNullDerefEvent event) const {
   BR.EmitReport(report);
 }
 
-static bool IsNSError(const ParmVarDecl *PD, IdentifierInfo *II) {
+static bool IsNSError(QualType T, IdentifierInfo *II) {
 
-  const PointerType* PPT = PD->getType()->getAs<PointerType>();
+  const PointerType* PPT = T->getAs<PointerType>();
   if (!PPT)
     return false;
 
@@ -288,8 +299,8 @@ static bool IsNSError(const ParmVarDecl *PD, IdentifierInfo *II) {
   return false;
 }
 
-static bool IsCFError(const ParmVarDecl *PD, IdentifierInfo *II) {
-  const PointerType* PPT = PD->getType()->getAs<PointerType>();
+static bool IsCFError(QualType T, IdentifierInfo *II) {
+  const PointerType* PPT = T->getAs<PointerType>();
   if (!PPT) return false;
 
   const TypedefType* TT = PPT->getPointeeType()->getAs<TypedefType>();
index 76ad94e40d817959e1db558cecb05a9b39b5ad9e..4614e349dece4275a4668813a6e49dabca437e6c 100644 (file)
@@ -60,16 +60,6 @@ const FunctionDecl *SVal::getAsFunctionDecl() const {
   return NULL;
 }
 
-const VarDecl* SVal::getAsVarDecl() const {
-  if (const loc::MemRegionVal* X = dyn_cast<loc::MemRegionVal>(this)) {
-    const MemRegion* R = X->getRegion();
-    if (const VarRegion *VR = R->getAs<VarRegion>())
-      return cast<VarDecl>(VR->getDecl());
-  }
-
-  return NULL;
-}
-
 /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and
 ///  wraps a symbol, return that SymbolRef.  Otherwise return 0.
 // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?