[cfe-commits] r126875 - in /cfe/trunk: include/clang/Analysis/CFG.h lib/Analysis/CFG.cpp lib/Sema/AnalysisBasedWarnings.cpp test/SemaCXX/return-noreturn.cpp

Ted Kremenek kremenek at apple.com
Wed Mar 2 12:32:29 PST 2011


Author: kremenek
Date: Wed Mar  2 14:32:29 2011
New Revision: 126875

URL: http://llvm.org/viewvc/llvm-project?rev=126875&view=rev
Log:
Introduce CFGImplicitDtor::isNoReturn() to query whether a destructor actually returns.  Use this for -Wreturn-type to prune false positives reported in PR 6884.

Modified:
    cfe/trunk/include/clang/Analysis/CFG.h
    cfe/trunk/lib/Analysis/CFG.cpp
    cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
    cfe/trunk/test/SemaCXX/return-noreturn.cpp

Modified: cfe/trunk/include/clang/Analysis/CFG.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/CFG.h?rev=126875&r1=126874&r2=126875&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/CFG.h (original)
+++ cfe/trunk/include/clang/Analysis/CFG.h Wed Mar  2 14:32:29 2011
@@ -130,6 +130,7 @@
 
 public:
   const CXXDestructorDecl *getDestructorDecl() const;
+  bool isNoReturn() const;
 
   static bool classof(const CFGElement *E) {
     Kind kind = E->getKind();

Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=126875&r1=126874&r2=126875&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Wed Mar  2 14:32:29 2011
@@ -2773,7 +2773,40 @@
 }
 
 const CXXDestructorDecl *CFGImplicitDtor::getDestructorDecl() const {
-  return 0;
+  switch (getKind()) {
+    case CFGElement::Invalid:
+    case CFGElement::Statement:
+    case CFGElement::Initializer:
+      llvm_unreachable("getDestructorDecl should only be used with "
+                       "ImplicitDtors");
+    case CFGElement::AutomaticObjectDtor: {
+      const VarDecl *var = cast<CFGAutomaticObjDtor>(this)->getVarDecl();
+      QualType ty = var->getType();
+      const RecordType *recordType = ty->getAs<RecordType>();
+      const CXXRecordDecl *classDecl =
+        cast<CXXRecordDecl>(recordType->getDecl());
+      return classDecl->getDestructor();      
+    }
+    case CFGElement::TemporaryDtor: {
+      const CXXBindTemporaryExpr *bindExpr =
+        cast<CFGTemporaryDtor>(this)->getBindTemporaryExpr();
+      const CXXTemporary *temp = bindExpr->getTemporary();
+      return temp->getDestructor();
+    }
+    case CFGElement::BaseDtor:
+    case CFGElement::MemberDtor:
+
+      // Not yet supported.
+      return 0;
+  }
+}
+
+bool CFGImplicitDtor::isNoReturn() const {
+  if (const CXXDestructorDecl *cdecl = getDestructorDecl()) {
+    QualType ty = cdecl->getType();
+    return cast<FunctionType>(ty)->getNoReturnAttr();
+  }
+  return false;
 }
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp?rev=126875&r1=126874&r2=126875&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp (original)
+++ cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp Wed Mar  2 14:32:29 2011
@@ -129,12 +129,27 @@
     // normal.  We need to look pass the destructors for the return
     // statement (if it exists).
     CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend();
+    bool hasNoReturnDtor = false;
+    
     for ( ; ri != re ; ++ri) {
       CFGElement CE = *ri;
+
+      // FIXME: The right solution is to just sever the edges in the
+      // CFG itself.
+      if (const CFGImplicitDtor *iDtor = ri->getAs<CFGImplicitDtor>())
+        if (iDtor->isNoReturn()) {
+          hasNoReturnDtor = true;
+          HasFakeEdge = true;
+          break;
+        }
+      
       if (isa<CFGStmt>(CE))
         break;
     }
     
+    if (hasNoReturnDtor)
+      continue;
+    
     // No more CFGElements in the block?
     if (ri == re) {
       if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) {

Modified: cfe/trunk/test/SemaCXX/return-noreturn.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/return-noreturn.cpp?rev=126875&r1=126874&r2=126875&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/return-noreturn.cpp (original)
+++ cfe/trunk/test/SemaCXX/return-noreturn.cpp Wed Mar  2 14:32:29 2011
@@ -1,18 +1,29 @@
 // RUN: %clang_cc1 %s -fsyntax-only -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code
-// XFAIL: *
 
 // A destructor may be marked noreturn and should still influence the CFG.
-namespace PR6884 {
-  struct abort_struct {
-    abort_struct() {} // Make this non-POD so the destructor is invoked.
-    ~abort_struct() __attribute__((noreturn));
-  };
+void pr6884_abort() __attribute__((noreturn));
 
-  int f() {
-    abort_struct();
-  }
+struct pr6884_abort_struct {
+  pr6884_abort_struct() {}
+  ~pr6884_abort_struct() __attribute__((noreturn)) { pr6884_abort(); }
+};
+
+int pr6884_f(int x) {
+  switch (x) { default: pr6884_abort(); }
+}
+
+int pr6884_g(int x) {
+  switch (x) { default: pr6884_abort_struct(); }
+}
+
+int pr6884_g_positive(int x) {
+  switch (x) { default: ; }
+} // expected-warning {{control reaches end of non-void function}}
 
-  int f2() {
-    abort_struct s;
+int pr6884_h(int x) {
+  switch (x) {
+    default: {
+      pr6884_abort_struct a;
+    }
   }
 }





More information about the cfe-commits mailing list