Fix test case in summary. Address comments.
http://reviews.llvm.org/D9454
Files:
include/clang/AST/DeclCXX.h
lib/AST/DeclCXX.cpp
lib/Analysis/CFG.cpp
test/SemaCXX/attr-noreturn.cpp
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/AST/DeclCXX.h
===================================================================
--- include/clang/AST/DeclCXX.h
+++ include/clang/AST/DeclCXX.h
@@ -2380,6 +2380,10 @@
return cast<CXXDestructorDecl>(getFirstDecl())->OperatorDelete;
}
+ // Returns true if this destructor, or any implicitly invoked destructors,
+ // are marked noreturn.
+ bool isAnyDestructorNoReturn() const;
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == CXXDestructor; }
Index: lib/AST/DeclCXX.cpp
===================================================================
--- lib/AST/DeclCXX.cpp
+++ lib/AST/DeclCXX.cpp
@@ -1899,6 +1899,31 @@
}
}
+bool CXXDestructorDecl::isAnyDestructorNoReturn() const {
+ // Destructor is noreturn
+ if (isNoReturn())
+ return true;
+
+ // Check base classes destructor for noreturn
+ const CXXRecordDecl *Record = getParent();
+ for (const auto &Base : Record->bases())
+ if (Base.getType()
+ ->getAsCXXRecordDecl()
+ ->getDestructor()
+ ->isAnyDestructorNoReturn())
+ return true;
+
+ // Check fields for noreturn
+ for (const auto *Field : Record->fields())
+ if (const CXXRecordDecl *RD =
+ Field->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl())
+ if (RD->getDestructor()->isAnyDestructorNoReturn())
+ return true;
+
+ // All destructors are not noreturn
+ return false;
+}
+
void CXXConversionDecl::anchor() { }
CXXConversionDecl *
Index: lib/Analysis/CFG.cpp
===================================================================
--- lib/Analysis/CFG.cpp
+++ lib/Analysis/CFG.cpp
@@ -1180,7 +1180,7 @@
Ty = Context->getBaseElementType(Ty);
const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor();
- if (Dtor->isNoReturn())
+ if (Dtor->isAnyDestructorNoReturn())
Block = createNoReturnBlock();
else
autoCreateBlock();
@@ -3682,7 +3682,7 @@
const CXXDestructorDecl *Dtor = E->getTemporary()->getDestructor();
- if (Dtor->isNoReturn()) {
+ if (Dtor->isAnyDestructorNoReturn()) {
// If the destructor is marked as a no-return destructor, we need to
// create a new block for the destructor which does not have as a
// successor anything built thus far. Control won't flow out of this
Index: test/SemaCXX/attr-noreturn.cpp
===================================================================
--- test/SemaCXX/attr-noreturn.cpp
+++ test/SemaCXX/attr-noreturn.cpp
@@ -17,6 +17,132 @@
}
}
+namespace destructor_tests {
+ __attribute__((noreturn)) void fail();
+
+ struct A {
+ ~A() __attribute__((noreturn)) { fail(); }
+ };
+ struct B {
+ B() {}
+ ~B() __attribute__((noreturn)) { fail(); }
+ };
+ struct C : A {};
+ struct D : B {};
+ struct E : virtual A {};
+ struct F : A, virtual B {};
+ struct G : E {};
+ struct H : virtual D {};
+ struct I : A {};
+ struct J : I {};
+ struct K : virtual A {};
+ struct L : K {};
+ struct M : virtual C {};
+ struct N : M {};
+ struct O { N n; };
+
+ __attribute__((noreturn)) void test_1() { A a; }
+ __attribute__((noreturn)) void test_2() { B b; }
+ __attribute__((noreturn)) void test_3() { C c; }
+ __attribute__((noreturn)) void test_4() { D d; }
+ __attribute__((noreturn)) void test_5() { E e; }
+ __attribute__((noreturn)) void test_6() { F f; }
+ __attribute__((noreturn)) void test_7() { G g; }
+ __attribute__((noreturn)) void test_8() { H h; }
+ __attribute__((noreturn)) void test_9() { I i; }
+ __attribute__((noreturn)) void test_10() { J j; }
+ __attribute__((noreturn)) void test_11() { K k; }
+ __attribute__((noreturn)) void test_12() { L l; }
+ __attribute__((noreturn)) void test_13() { M m; }
+ __attribute__((noreturn)) void test_14() { N n; }
+ __attribute__((noreturn)) void test_15() { O o; }
+
+ __attribute__((noreturn)) void test_16() { const A& a = A(); }
+ __attribute__((noreturn)) void test_17() { const B& b = B(); }
+ __attribute__((noreturn)) void test_18() { const C& c = C(); }
+ __attribute__((noreturn)) void test_19() { const D& d = D(); }
+ __attribute__((noreturn)) void test_20() { const E& e = E(); }
+ __attribute__((noreturn)) void test_21() { const F& f = F(); }
+ __attribute__((noreturn)) void test_22() { const G& g = G(); }
+ __attribute__((noreturn)) void test_23() { const H& h = H(); }
+ __attribute__((noreturn)) void test_24() { const I& i = I(); }
+ __attribute__((noreturn)) void test_25() { const J& j = J(); }
+ __attribute__((noreturn)) void test_26() { const K& k = K(); }
+ __attribute__((noreturn)) void test_27() { const L& l = L(); }
+ __attribute__((noreturn)) void test_28() { const M& m = M(); }
+ __attribute__((noreturn)) void test_29() { const N& n = N(); }
+ __attribute__((noreturn)) void test_30() { const O& o = O(); }
+
+ struct AA {};
+ struct BB { BB() {} ~BB() {} };
+ struct CC : AA {};
+ struct DD : BB {};
+ struct EE : virtual AA {};
+ struct FF : AA, virtual BB {};
+ struct GG : EE {};
+ struct HH : virtual DD {};
+ struct II : AA {};
+ struct JJ : II {};
+ struct KK : virtual AA {};
+ struct LL : KK {};
+ struct MM : virtual CC {};
+ struct NN : MM {};
+ struct OO { NN n; };
+
+ __attribute__((noreturn)) void test_31() {
+ AA a;
+ BB b;
+ CC c;
+ DD d;
+ EE e;
+ FF f;
+ GG g;
+ HH h;
+ II i;
+ JJ j;
+ KK k;
+ LL l;
+ MM m;
+ NN n;
+ OO o;
+
+ const AA& aa = AA();
+ const BB& bb = BB();
+ const CC& cc = CC();
+ const DD& dd = DD();
+ const EE& ee = EE();
+ const FF& ff = FF();
+ const GG& gg = GG();
+ const HH& hh = HH();
+ const II& ii = II();
+ const JJ& jj = JJ();
+ const KK& kk = KK();
+ const LL& ll = LL();
+ const MM& mm = MM();
+ const NN& nn = NN();
+ const OO& oo = OO();
+ } // expected-warning {{function declared 'noreturn' should not return}}
+
+ struct P {
+ ~P() __attribute__((noreturn)) { fail(); }
+ void foo() {}
+ };
+ struct Q : P { };
+ __attribute__((noreturn)) void test31() {
+ P().foo();
+ }
+ __attribute__((noreturn)) void test32() {
+ Q().foo();
+ }
+
+ struct R {
+ A a[5];
+ };
+ __attribute__((noreturn)) void test33() {
+ R r;
+ }
+}
+
// PR5620
void f0() __attribute__((__noreturn__));
void f1(void (*)());
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits