diff options
| author | Ted Kremenek <kremenek@apple.com> | 2011-03-02 20:32:29 +0000 |
|---|---|---|
| committer | Ted Kremenek <kremenek@apple.com> | 2011-03-02 20:32:29 +0000 |
| commit | e06a55c6b9a278705d723da399eb72eb6a23ddc2 (patch) | |
| tree | 0ccdc1be6a0ca716bf7e046ebbbd527a5338f1f0 | |
| parent | bd6f7f9770728a425388c8d4d9b1aec4a5fac5e1 (diff) | |
| download | bcm5719-llvm-e06a55c6b9a278705d723da399eb72eb6a23ddc2.tar.gz bcm5719-llvm-e06a55c6b9a278705d723da399eb72eb6a23ddc2.zip | |
Introduce CFGImplicitDtor::isNoReturn() to query whether a destructor actually returns. Use this for -Wreturn-type to prune false positives reported in PR 6884.
llvm-svn: 126875
| -rw-r--r-- | clang/include/clang/Analysis/CFG.h | 1 | ||||
| -rw-r--r-- | clang/lib/Analysis/CFG.cpp | 35 | ||||
| -rw-r--r-- | clang/lib/Sema/AnalysisBasedWarnings.cpp | 15 | ||||
| -rw-r--r-- | clang/test/SemaCXX/return-noreturn.cpp | 33 |
4 files changed, 72 insertions, 12 deletions
diff --git a/clang/include/clang/Analysis/CFG.h b/clang/include/clang/Analysis/CFG.h index d135286d30f..992b32a6d74 100644 --- a/clang/include/clang/Analysis/CFG.h +++ b/clang/include/clang/Analysis/CFG.h @@ -130,6 +130,7 @@ protected: public: const CXXDestructorDecl *getDestructorDecl() const; + bool isNoReturn() const; static bool classof(const CFGElement *E) { Kind kind = E->getKind(); diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 13576539348..2818cf6d620 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -2773,7 +2773,40 @@ CFG* CFG::buildCFG(const Decl *D, Stmt* Statement, ASTContext *C, } 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; } //===----------------------------------------------------------------------===// diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 6a422242a9d..84efbd50d1a 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -129,12 +129,27 @@ static ControlFlowKind CheckFallThrough(AnalysisContext &AC) { // 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())) { diff --git a/clang/test/SemaCXX/return-noreturn.cpp b/clang/test/SemaCXX/return-noreturn.cpp index 7e0a69c266b..890fb9017ca 100644 --- a/clang/test/SemaCXX/return-noreturn.cpp +++ b/clang/test/SemaCXX/return-noreturn.cpp @@ -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; + } } } |

