[cfe-commits] r163759 - in /cfe/trunk: include/clang/Analysis/DomainSpecific/ObjCNoReturn.h include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h lib/Analysis/CMakeLists.txt lib/Analysis/ObjCNoReturn.cpp lib/StaticAnalyzer/Core/ExprEngine.cpp lib/StaticAnalyzer/Core/ExprEngineObjC.cpp

Ted Kremenek kremenek at apple.com
Wed Sep 12 17:21:31 PDT 2012


Author: kremenek
Date: Wed Sep 12 19:21:31 2012
New Revision: 163759

URL: http://llvm.org/viewvc/llvm-project?rev=163759&view=rev
Log:
Refactor logic in ExprEngine for detecting 'noreturn' methods
in NSException to a helper object in libAnalysis that can also
be used by Sema.  Not sure if the predicate name 'isImplicitNoReturn'
is the best one, but we can massage that later.

No functionality change.

Added:
    cfe/trunk/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
    cfe/trunk/lib/Analysis/ObjCNoReturn.cpp
Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
    cfe/trunk/lib/Analysis/CMakeLists.txt
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp

Added: cfe/trunk/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h?rev=163759&view=auto
==============================================================================
--- cfe/trunk/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h (added)
+++ cfe/trunk/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h Wed Sep 12 19:21:31 2012
@@ -0,0 +1,46 @@
+//= ObjCNoReturn.h - Handling of Cocoa APIs known not to return --*- C++ -*---//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements special handling of recognizing ObjC API hooks that
+// do not return but aren't marked as such in API headers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_DS_OBJCNORETURN
+#define LLVM_CLANG_ANALYSIS_DS_OBJCNORETURN
+
+#include "clang/Basic/IdentifierTable.h"
+
+namespace clang {
+
+class ASTContext;
+class ObjCMessageExpr;
+  
+class ObjCNoReturn {
+  /// Cached "raise" selector.
+  Selector RaiseSel;
+
+  /// Cached identifier for "NSException".
+  IdentifierInfo *NSExceptionII;
+
+  enum { NUM_RAISE_SELECTORS = 2 };
+
+  /// Cached set of selectors in NSException that are 'noreturn'.
+  Selector NSExceptionInstanceRaiseSelectors[NUM_RAISE_SELECTORS];
+
+public:
+  ObjCNoReturn(ASTContext &C);
+  
+  /// Return true if the given message expression is known to never
+  /// return.
+  bool isImplicitNoReturn(const ObjCMessageExpr *ME);
+};
+}
+
+#endif

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?rev=163759&r1=163758&r2=163759&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Wed Sep 12 19:21:31 2012
@@ -16,6 +16,7 @@
 #ifndef LLVM_CLANG_GR_EXPRENGINE
 #define LLVM_CLANG_GR_EXPRENGINE
 
+#include "clang/Analysis/DomainSpecific/ObjCNoReturn.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
@@ -74,13 +75,10 @@
   const Stmt *currStmt;
   unsigned int currStmtIdx;
   const NodeBuilderContext *currBldrCtx;
-
-  /// Obj-C Class Identifiers.
-  IdentifierInfo* NSExceptionII;
-
-  /// Obj-C Selectors.
-  Selector* NSExceptionInstanceRaiseSelectors;
-  Selector RaiseSel;
+  
+  /// Helper object to determine if an Objective-C message expression
+  /// implicitly never returns.
+  ObjCNoReturn ObjCNoRet;
   
   /// Whether or not GC is enabled in this analysis.
   bool ObjCGCEnabled;

Modified: cfe/trunk/lib/Analysis/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CMakeLists.txt?rev=163759&r1=163758&r2=163759&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CMakeLists.txt (original)
+++ cfe/trunk/lib/Analysis/CMakeLists.txt Wed Sep 12 19:21:31 2012
@@ -1,13 +1,14 @@
 add_clang_library(clangAnalysis
   AnalysisDeclContext.cpp
-  CallGraph.cpp
   CFG.cpp
   CFGReachabilityAnalysis.cpp
   CFGStmtMap.cpp
+  CallGraph.cpp
   CocoaConventions.cpp
   Dominators.cpp
   FormatString.cpp
   LiveVariables.cpp
+  ObjCNoReturn.cpp
   PostOrderCFGView.cpp
   PrintfFormatString.cpp
   ProgramPoint.cpp

Added: cfe/trunk/lib/Analysis/ObjCNoReturn.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ObjCNoReturn.cpp?rev=163759&view=auto
==============================================================================
--- cfe/trunk/lib/Analysis/ObjCNoReturn.cpp (added)
+++ cfe/trunk/lib/Analysis/ObjCNoReturn.cpp Wed Sep 12 19:21:31 2012
@@ -0,0 +1,67 @@
+//= ObjCNoReturn.cpp - Handling of Cocoa APIs known not to return --*- C++ -*---
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements special handling of recognizing ObjC API hooks that
+// do not return but aren't marked as such in API headers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Analysis/DomainSpecific/ObjCNoReturn.h"
+
+using namespace clang;
+
+static bool isSubclass(const ObjCInterfaceDecl *Class, IdentifierInfo *II) {
+  if (!Class)
+    return false;
+  if (Class->getIdentifier() == II)
+    return true;
+  return isSubclass(Class->getSuperClass(), II);
+}
+
+ObjCNoReturn::ObjCNoReturn(ASTContext &C)
+  : RaiseSel(GetNullarySelector("raise", C)),
+    NSExceptionII(&C.Idents.get("NSException"))
+{
+  // Generate selectors.
+  SmallVector<IdentifierInfo*, 3> II;
+  
+  // raise:format:
+  II.push_back(&C.Idents.get("raise"));
+  II.push_back(&C.Idents.get("format"));
+  NSExceptionInstanceRaiseSelectors[0] =
+    C.Selectors.getSelector(II.size(), &II[0]);
+    
+  // raise:format:arguments:
+  II.push_back(&C.Idents.get("arguments"));
+  NSExceptionInstanceRaiseSelectors[1] =
+    C.Selectors.getSelector(II.size(), &II[0]);
+}
+
+
+bool ObjCNoReturn::isImplicitNoReturn(const ObjCMessageExpr *ME) {
+  Selector S = ME->getSelector();
+  
+  if (ME->isInstanceMessage()) {
+    // Check for the "raise" message.
+    return S == RaiseSel;
+  }
+
+  if (const ObjCInterfaceDecl *ID = ME->getReceiverInterface()) {
+    if (isSubclass(ID, NSExceptionII)) {
+      for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i) {
+        if (S == NSExceptionInstanceRaiseSelectors[i])
+          return true;
+      }
+    }
+  }
+  
+  return false;
+}
\ No newline at end of file

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=163759&r1=163758&r2=163759&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Wed Sep 12 19:21:31 2012
@@ -68,8 +68,7 @@
     svalBuilder(StateMgr.getSValBuilder()),
     EntryNode(NULL),
     currStmt(NULL), currStmtIdx(0), currBldrCtx(0),
-    NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL),
-    RaiseSel(GetNullarySelector("raise", getContext())),
+    ObjCNoRet(mgr.getASTContext()),
     ObjCGCEnabled(gcEnabled), BR(mgr, *this),
     VisitedCallees(VisitedCalleesIn)
 {
@@ -81,7 +80,6 @@
 
 ExprEngine::~ExprEngine() {
   BR.FlushReports();
-  delete [] NSExceptionInstanceRaiseSelectors;
 }
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp?rev=163759&r1=163758&r2=163759&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp Wed Sep 12 19:21:31 2012
@@ -132,14 +132,6 @@
   getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
 }
 
-static bool isSubclass(const ObjCInterfaceDecl *Class, IdentifierInfo *II) {
-  if (!Class)
-    return false;
-  if (Class->getIdentifier() == II)
-    return true;
-  return isSubclass(Class->getSuperClass(), II);
-}
-
 void ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME,
                                   ExplodedNode *Pred,
                                   ExplodedNodeSet &Dst) {
@@ -184,7 +176,7 @@
         
         // Check if the "raise" message was sent.
         assert(notNilState);
-        if (Msg->getSelector() == RaiseSel) {
+        if (ObjCNoRet.isImplicitNoReturn(ME)) {
           // If we raise an exception, for now treat it as a sink.
           // Eventually we will want to handle exceptions properly.
           Bldr.generateSink(currStmt, Pred, State);
@@ -198,52 +190,13 @@
         }
       }
     } else {
-      // Check for special class methods.
-      if (const ObjCInterfaceDecl *Iface = Msg->getReceiverInterface()) {
-        if (!NSExceptionII) {
-          ASTContext &Ctx = getContext();
-          NSExceptionII = &Ctx.Idents.get("NSException");
-        }
-        
-        if (isSubclass(Iface, NSExceptionII)) {
-          enum { NUM_RAISE_SELECTORS = 2 };
-          
-          // Lazily create a cache of the selectors.
-          if (!NSExceptionInstanceRaiseSelectors) {
-            ASTContext &Ctx = getContext();
-            NSExceptionInstanceRaiseSelectors =
-              new Selector[NUM_RAISE_SELECTORS];
-            SmallVector<IdentifierInfo*, NUM_RAISE_SELECTORS> II;
-            unsigned idx = 0;
-            
-            // raise:format:
-            II.push_back(&Ctx.Idents.get("raise"));
-            II.push_back(&Ctx.Idents.get("format"));
-            NSExceptionInstanceRaiseSelectors[idx++] =
-              Ctx.Selectors.getSelector(II.size(), &II[0]);
-            
-            // raise:format:arguments:
-            II.push_back(&Ctx.Idents.get("arguments"));
-            NSExceptionInstanceRaiseSelectors[idx++] =
-              Ctx.Selectors.getSelector(II.size(), &II[0]);
-          }
-          
-          Selector S = Msg->getSelector();
-          bool RaisesException = false;
-          for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i) {
-            if (S == NSExceptionInstanceRaiseSelectors[i]) {
-              RaisesException = true;
-              break;
-            }
-          }
-          if (RaisesException) {
-            // If we raise an exception, for now treat it as a sink.
-            // Eventually we will want to handle exceptions properly.
-            Bldr.generateSink(currStmt, Pred, Pred->getState());
-            continue;
-          }
-
-        }
+      // Check for special class methods that are known to not return
+      // and that we should treat as a sink.
+      if (ObjCNoRet.isImplicitNoReturn(ME)) {
+        // If we raise an exception, for now treat it as a sink.
+        // Eventually we will want to handle exceptions properly.
+        Bldr.generateSink(currStmt, Pred, Pred->getState());
+        continue;
       }
     }
 





More information about the cfe-commits mailing list