Hi jordan_rose,

The analyzer incorrectly handled noreturn destructors which were hidden inside
function calls. This happened because NoReturnFunctionChecker only listened for
PostStmt events, which are not executed for destructor calls. I've changed it to
listen to PostCall events, which should catch both cases.

http://llvm-reviews.chandlerc.com/D1056

Files:
  lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
  test/Analysis/dtor.cpp

Index: lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
+++ lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
@@ -26,23 +26,28 @@
 
 namespace {
 
-class NoReturnFunctionChecker : public Checker< check::PostStmt<CallExpr>,
+class NoReturnFunctionChecker : public Checker< check::PostCall,
                                                 check::PostObjCMessage > {
 public:
-  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+  void checkPostCall(const CallEvent &CE, CheckerContext &C) const;
   void checkPostObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) 
const;
 };
 
 }
 
-void NoReturnFunctionChecker::checkPostStmt(const CallExpr *CE,
+void NoReturnFunctionChecker::checkPostCall(const CallEvent &CE,
                                             CheckerContext &C) const {
   ProgramStateRef state = C.getState();
-  const Expr *Callee = CE->getCallee();
+  bool BuildSinks = false;
 
-  bool BuildSinks = getFunctionExtInfo(Callee->getType()).getNoReturn();
+  if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CE.getDecl()))
+    BuildSinks = FD->getAttr<AnalyzerNoReturnAttr>() || FD->isNoReturn();
 
-  if (!BuildSinks) {
+  const Expr *Callee = CE.getOriginExpr();
+  if (!BuildSinks && Callee)
+    BuildSinks = getFunctionExtInfo(Callee->getType()).getNoReturn();
+
+  if (!BuildSinks && Callee) {
     SVal L = state->getSVal(Callee, C.getLocationContext());
     const FunctionDecl *FD = L.getAsFunctionDecl();
     if (!FD)
Index: test/Analysis/dtor.cpp
===================================================================
--- test/Analysis/dtor.cpp
+++ test/Analysis/dtor.cpp
@@ -401,3 +401,19 @@
     clang_analyzer_eval(SaveOnVirtualDestruct::lastOutput == 42); // 
expected-warning{{TRUE}}
   }
 }
+
+namespace NoReturn {
+  struct NR {
+    ~NR() __attribute__((noreturn));
+  };
+
+  void f(int **x) {
+    NR nr;
+  }
+
+  void g() {
+    int *x;
+    f(&x);
+    *x = 47; // no warning
+  }
+}
Index: lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
+++ lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
@@ -26,23 +26,28 @@
 
 namespace {
 
-class NoReturnFunctionChecker : public Checker< check::PostStmt<CallExpr>,
+class NoReturnFunctionChecker : public Checker< check::PostCall,
                                                 check::PostObjCMessage > {
 public:
-  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+  void checkPostCall(const CallEvent &CE, CheckerContext &C) const;
   void checkPostObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
 };
 
 }
 
-void NoReturnFunctionChecker::checkPostStmt(const CallExpr *CE,
+void NoReturnFunctionChecker::checkPostCall(const CallEvent &CE,
                                             CheckerContext &C) const {
   ProgramStateRef state = C.getState();
-  const Expr *Callee = CE->getCallee();
+  bool BuildSinks = false;
 
-  bool BuildSinks = getFunctionExtInfo(Callee->getType()).getNoReturn();
+  if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CE.getDecl()))
+    BuildSinks = FD->getAttr<AnalyzerNoReturnAttr>() || FD->isNoReturn();
 
-  if (!BuildSinks) {
+  const Expr *Callee = CE.getOriginExpr();
+  if (!BuildSinks && Callee)
+    BuildSinks = getFunctionExtInfo(Callee->getType()).getNoReturn();
+
+  if (!BuildSinks && Callee) {
     SVal L = state->getSVal(Callee, C.getLocationContext());
     const FunctionDecl *FD = L.getAsFunctionDecl();
     if (!FD)
Index: test/Analysis/dtor.cpp
===================================================================
--- test/Analysis/dtor.cpp
+++ test/Analysis/dtor.cpp
@@ -401,3 +401,19 @@
     clang_analyzer_eval(SaveOnVirtualDestruct::lastOutput == 42); // expected-warning{{TRUE}}
   }
 }
+
+namespace NoReturn {
+  struct NR {
+    ~NR() __attribute__((noreturn));
+  };
+
+  void f(int **x) {
+    NR nr;
+  }
+
+  void g() {
+    int *x;
+    f(&x);
+    *x = 47; // no warning
+  }
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to