[cfe-commits] r85895 - in /cfe/trunk: include/clang/Analysis/PathSensitive/Checker.h include/clang/Analysis/PathSensitive/Checkers/UndefSizedVLAChecker.h include/clang/Analysis/PathSensitive/Checkers/ZeroSizedVLAChecker.h lib/Analysis/GRExprEngine.cpp lib/Analysis/GRExprEngineInternalChecks.cpp lib/Analysis/UndefSizedVLAChecker.cpp lib/Analysis/ZeroSizedVLAChecker.cpp test/Analysis/misc-ps.m

Zhongxing Xu xuzhongxing at gmail.com
Tue Nov 3 04:13:39 PST 2009


Author: zhongxingxu
Date: Tue Nov  3 06:13:38 2009
New Revision: 85895

URL: http://llvm.org/viewvc/llvm-project?rev=85895&view=rev
Log:
Pull VLA size checker into its own files. 
Split it to two checkers, one for undefined size, 
the other for zero size, so that we don't need to query the size
when emitting the bug report.

Added:
    cfe/trunk/include/clang/Analysis/PathSensitive/Checkers/UndefSizedVLAChecker.h
    cfe/trunk/include/clang/Analysis/PathSensitive/Checkers/ZeroSizedVLAChecker.h
    cfe/trunk/lib/Analysis/UndefSizedVLAChecker.cpp
    cfe/trunk/lib/Analysis/ZeroSizedVLAChecker.cpp
Modified:
    cfe/trunk/include/clang/Analysis/PathSensitive/Checker.h
    cfe/trunk/lib/Analysis/GRExprEngine.cpp
    cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp
    cfe/trunk/test/Analysis/misc-ps.m

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/Checker.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/Checker.h?rev=85895&r1=85894&r2=85895&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/Checker.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/Checker.h Tue Nov  3 06:13:38 2009
@@ -126,6 +126,13 @@
                                       GRExprEngine &Eng) {
     return Pred;
   }
+
+  virtual ExplodedNode *CheckType(QualType T, ExplodedNode *Pred, 
+                                  const GRState *state, Stmt *S, 
+                                  GRExprEngine &Eng) {
+    return Pred;
+  }
+
 };
 
 } // end clang namespace

Added: cfe/trunk/include/clang/Analysis/PathSensitive/Checkers/UndefSizedVLAChecker.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/Checkers/UndefSizedVLAChecker.h?rev=85895&view=auto

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/Checkers/UndefSizedVLAChecker.h (added)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/Checkers/UndefSizedVLAChecker.h Tue Nov  3 06:13:38 2009
@@ -0,0 +1,29 @@
+//=== UndefSizedVLAChecker.h - Undefined dereference checker ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines UndefSizedVLAChecker, a builtin check in GRExprEngine that 
+// performs checks for declaration of VLA of undefined size.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checker.h"
+
+namespace clang {
+
+class UndefSizedVLAChecker : public Checker {
+  BugType *BT;
+
+public:
+  UndefSizedVLAChecker() : BT(0) {}
+  static void *getTag();
+  ExplodedNode *CheckType(QualType T, ExplodedNode *Pred, 
+                          const GRState *state, Stmt *S, GRExprEngine &Eng);
+};
+
+}

Added: cfe/trunk/include/clang/Analysis/PathSensitive/Checkers/ZeroSizedVLAChecker.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/Checkers/ZeroSizedVLAChecker.h?rev=85895&view=auto

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/Checkers/ZeroSizedVLAChecker.h (added)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/Checkers/ZeroSizedVLAChecker.h Tue Nov  3 06:13:38 2009
@@ -0,0 +1,29 @@
+//=== ZeroSizedVLAChecker.cpp - Undefined dereference checker ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines ZeorSizedVLAChecker, a builtin check in GRExprEngine that 
+// performs checks for declaration of VLA of zero size.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checker.h"
+
+namespace clang {
+
+class ZeroSizedVLAChecker : public Checker {
+  BugType *BT;
+
+public:
+  ZeroSizedVLAChecker() : BT(0) {}
+  static void *getTag();
+  ExplodedNode *CheckType(QualType T, ExplodedNode *Pred, 
+                          const GRState *state, Stmt *S, GRExprEngine &Eng);
+};
+
+}

Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=85895&r1=85894&r2=85895&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Tue Nov  3 06:13:38 2009
@@ -2058,45 +2058,25 @@
     Tmp.Add(Pred);
 
   for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
-    const GRState* state = GetState(*I);
-    unsigned Count = Builder->getCurrentBlockCount();
-
-    // Check if 'VD' is a VLA and if so check if has a non-zero size.
-    QualType T = getContext().getCanonicalType(VD->getType());
-    if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
-      // FIXME: Handle multi-dimensional VLAs.
-
-      Expr* SE = VLA->getSizeExpr();
-      SVal Size_untested = state->getSVal(SE);
+    ExplodedNode *N = *I;
+    const GRState *state;
 
-      if (Size_untested.isUndef()) {
-        if (ExplodedNode* N = Builder->generateNode(DS, state, Pred)) {
-          N->markAsSink();
-          ExplicitBadSizedVLA.insert(N);
-        }
-        continue;
-      }
-
-      DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(Size_untested);
-      const GRState *zeroState =  state->Assume(Size, false);
-      state = state->Assume(Size, true);
+    for (CheckersOrdered::iterator CI = Checkers.begin(), CE = Checkers.end(); 
+         CI != CE; ++CI) {
+      state = GetState(N);
+      N = CI->second->CheckType(getContext().getCanonicalType(VD->getType()),
+                                N, state, DS, *this);
+      if (!N)
+        break;
+    }
 
-      if (zeroState) {
-        if (ExplodedNode* N = Builder->generateNode(DS, zeroState, Pred)) {
-          N->markAsSink();
-          if (state)
-            ImplicitBadSizedVLA.insert(N);
-          else
-            ExplicitBadSizedVLA.insert(N);
-        }
-      }
+    if (!N)
+      continue;
 
-      if (!state)
-        continue;
-    }
+    state = GetState(N);
 
     // Decls without InitExpr are not initialized explicitly.
-    const LocationContext *LC = (*I)->getLocationContext();
+    const LocationContext *LC = N->getLocationContext();
 
     if (InitEx) {
       SVal InitVal = state->getSVal(InitEx);
@@ -2106,7 +2086,8 @@
       // UnknownVal.
       if (InitVal.isUnknown() ||
           !getConstraintManager().canReasonAbout(InitVal)) {
-        InitVal = ValMgr.getConjuredSymbolVal(NULL, InitEx, Count);
+        InitVal = ValMgr.getConjuredSymbolVal(NULL, InitEx, 
+                                               Builder->getCurrentBlockCount());
       }
 
       state = state->bindDecl(VD, LC, InitVal);

Modified: cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp?rev=85895&r1=85894&r2=85895&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp Tue Nov  3 06:13:38 2009
@@ -21,6 +21,8 @@
 #include "clang/Analysis/PathSensitive/Checkers/BadCallChecker.h"
 #include "clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h"
 #include "clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/UndefSizedVLAChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/ZeroSizedVLAChecker.h"
 #include "clang/Analysis/PathDiagnostic.h"
 #include "clang/Basic/SourceManager.h"
 #include "llvm/Support/Compiler.h"
@@ -449,66 +451,6 @@
   }
 };
 
-class VISIBILITY_HIDDEN BadSizeVLA : public BuiltinBug {
-public:
-  BadSizeVLA(GRExprEngine* eng) :
-    BuiltinBug(eng, "Bad variable-length array (VLA) size") {}
-
-  void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
-    for (GRExprEngine::ErrorNodes::iterator
-          I = Eng.ExplicitBadSizedVLA.begin(),
-          E = Eng.ExplicitBadSizedVLA.end(); I!=E; ++I) {
-
-      // Determine whether this was a 'zero-sized' VLA or a VLA with an
-      // undefined size.
-      ExplodedNode* N = *I;
-      PostStmt PS = cast<PostStmt>(N->getLocation());
-      const DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
-      VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
-      QualType T = Eng.getContext().getCanonicalType(VD->getType());
-      VariableArrayType* VT = cast<VariableArrayType>(T);
-      Expr* SizeExpr = VT->getSizeExpr();
-
-      std::string buf;
-      llvm::raw_string_ostream os(buf);
-      os << "The expression used to specify the number of elements in the "
-            "variable-length array (VLA) '"
-         << VD->getNameAsString() << "' evaluates to ";
-
-      bool isUndefined = N->getState()->getSVal(SizeExpr).isUndef();
-
-      if (isUndefined)
-        os << "an undefined or garbage value.";
-      else
-        os << "0. VLAs with no elements have undefined behavior.";
-
-      std::string shortBuf;
-      llvm::raw_string_ostream os_short(shortBuf);
-      os_short << "Variable-length array '" << VD->getNameAsString() << "' "
-               << (isUndefined ? "garbage value for array size"
-                   : "has zero elements (undefined behavior)");
-
-      ArgReport *report = new ArgReport(*this, os_short.str().c_str(),
-                                        os.str().c_str(), N, SizeExpr);
-
-      report->addRange(SizeExpr->getSourceRange());
-      BR.EmitReport(report);
-    }
-  }
-
-  void registerInitialVisitors(BugReporterContext& BRC,
-                               const ExplodedNode* N,
-                               BuiltinBugReport *R) {
-    registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
-                                  N);
-  }
-};
-
-//===----------------------------------------------------------------------===//
-// __attribute__(nonnull) checking
-
-
-
 } // end clang namespace
 
 //===----------------------------------------------------------------------===//
@@ -528,7 +470,6 @@
   BR.Register(new BadMsgExprArg(this));
   BR.Register(new BadReceiver(this));
   BR.Register(new OutOfBoundMemoryAccess(this));
-  BR.Register(new BadSizeVLA(this));
   BR.Register(new NilReceiverStructRet(this));
   BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
 
@@ -543,4 +484,6 @@
   registerCheck<DivZeroChecker>(new DivZeroChecker());
   registerCheck<UndefDerefChecker>(new UndefDerefChecker());
   registerCheck<NullDerefChecker>(new NullDerefChecker());
+  registerCheck<UndefSizedVLAChecker>(new UndefSizedVLAChecker());
+  registerCheck<ZeroSizedVLAChecker>(new ZeroSizedVLAChecker());
 }

Added: cfe/trunk/lib/Analysis/UndefSizedVLAChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/UndefSizedVLAChecker.cpp?rev=85895&view=auto

==============================================================================
--- cfe/trunk/lib/Analysis/UndefSizedVLAChecker.cpp (added)
+++ cfe/trunk/lib/Analysis/UndefSizedVLAChecker.cpp Tue Nov  3 06:13:38 2009
@@ -0,0 +1,54 @@
+//=== UndefSizedVLAChecker.cpp - Undefined dereference checker --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines UndefSizedVLAChecker, a builtin check in GRExprEngine that 
+// performs checks for declaration of VLA of undefined size.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/UndefSizedVLAChecker.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *UndefSizedVLAChecker::getTag() {
+  static int x = 0;
+  return &x;
+}
+
+ExplodedNode *UndefSizedVLAChecker::CheckType(QualType T, ExplodedNode *Pred,
+                                              const GRState *state,
+                                              Stmt *S, GRExprEngine &Eng) {
+  GRStmtNodeBuilder &Builder = Eng.getBuilder();
+  BugReporter &BR = Eng.getBugReporter();
+
+  if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
+    // FIXME: Handle multi-dimensional VLAs.
+    Expr* SE = VLA->getSizeExpr();
+    SVal Size_untested = state->getSVal(SE);
+
+    if (Size_untested.isUndef()) {
+      if (ExplodedNode* N = Builder.generateNode(S, state, Pred)) {
+        N->markAsSink();
+        if (!BT)
+          BT = new BugType("Declare variable-length array (VLA) of undefined "
+                            "size", "Logic error");
+
+        EnhancedBugReport *R =
+                          new EnhancedBugReport(*BT, BT->getName().c_str(), N);
+        R->addRange(SE->getSourceRange());
+        R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
+        BR.EmitReport(R);
+      }
+      return 0;    
+    }
+  }
+  return Pred;
+}

Added: cfe/trunk/lib/Analysis/ZeroSizedVLAChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ZeroSizedVLAChecker.cpp?rev=85895&view=auto

==============================================================================
--- cfe/trunk/lib/Analysis/ZeroSizedVLAChecker.cpp (added)
+++ cfe/trunk/lib/Analysis/ZeroSizedVLAChecker.cpp Tue Nov  3 06:13:38 2009
@@ -0,0 +1,66 @@
+//=== ZeroSizedVLAChecker.cpp - Undefined dereference checker ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines ZeorSizedVLAChecker, a builtin check in GRExprEngine that 
+// performs checks for declaration of VLA of zero size.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/ZeroSizedVLAChecker.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *ZeroSizedVLAChecker::getTag() {
+  static int x;
+  return &x;
+}
+
+ExplodedNode *ZeroSizedVLAChecker::CheckType(QualType T, ExplodedNode *Pred, 
+                                             const GRState *state, Stmt *S, 
+                                             GRExprEngine &Eng) {
+  GRStmtNodeBuilder &Builder = Eng.getBuilder();
+  BugReporter &BR = Eng.getBugReporter();
+
+  if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
+    // FIXME: Handle multi-dimensional VLAs.
+    Expr* SE = VLA->getSizeExpr();
+    SVal Size_untested = state->getSVal(SE);
+
+    DefinedOrUnknownSVal *Size = dyn_cast<DefinedOrUnknownSVal>(&Size_untested);
+    // Undefined size is checked in another checker.
+    if (!Size)
+      return Pred;
+
+    const GRState *zeroState =  state->Assume(*Size, false);
+    state = state->Assume(*Size, true);
+
+    if (zeroState && !state) {
+      if (ExplodedNode* N = Builder.generateNode(S, zeroState, Pred)) {
+        N->markAsSink();
+        if (!BT)
+          BT = new BugType("Declare variable-length array (VLA) of zero size",
+                            "Logic error");
+
+        EnhancedBugReport *R =
+                          new EnhancedBugReport(*BT, BT->getName().c_str(), N);
+        R->addRange(SE->getSourceRange());
+        R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
+        BR.EmitReport(R);
+      }
+    }
+    if (!state)
+      return 0;
+
+    return Builder.generateNode(S, state, Pred);
+  }
+  else
+    return Pred;
+}

Modified: cfe/trunk/test/Analysis/misc-ps.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps.m?rev=85895&r1=85894&r2=85895&view=diff

==============================================================================
--- cfe/trunk/test/Analysis/misc-ps.m (original)
+++ cfe/trunk/test/Analysis/misc-ps.m Tue Nov  3 06:13:38 2009
@@ -121,12 +121,12 @@
   if (x)
     return;
 
-  int vla[x]; // expected-warning{{Variable-length array 'vla' has zero elements (undefined behavior)}}
+  int vla[x]; // expected-warning{{Declare variable-length array (VLA) of zero size}}
 }
 
 void check_uninit_sized_VLA() {
   int x;
-  int vla[x]; // expected-warning{{Variable-length array 'vla' garbage value for array size}}
+  int vla[x]; // expected-warning{{Declare variable-length array (VLA) of undefined size}}
 }
 
 // sizeof(void)





More information about the cfe-commits mailing list