From 5d068499a7b43a5c9a4375f7a4cdbfc238e0b683 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Wed, 26 Jan 2011 04:49:52 +0000 Subject: [PATCH] Teach -Wreturn-type that destructors can appear after a 'return' in a CFGBlock. This accidentally was working before, but the false assumption that 'return' always appeared at the end of the block was uncovered by a recent change. llvm-svn: 124280 --- clang/lib/Sema/AnalysisBasedWarnings.cpp | 25 +++++++++++--------- clang/test/SemaCXX/warn-missing-noreturn.cpp | 10 ++++++++ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 2f02e158cbd7..99f19fca7847 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -121,26 +121,29 @@ static ControlFlowKind CheckFallThrough(AnalysisContext &AC) { const CFGBlock& B = **I; if (!live[B.getBlockID()]) continue; - if (B.size() == 0) { + + // Destructors can appear after the 'return' in the CFG. This is + // 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(); + for ( ; ri != re ; ++ri) { + CFGElement CE = *ri; + if (isa(CE)) + break; + } + + // No more CFGElements in the block? + if (ri == re) { if (B.getTerminator() && isa(B.getTerminator())) { HasAbnormalEdge = true; continue; } - // A labeled empty statement, or the entry block... HasPlainEdge = true; continue; } - CFGElement CE = B[B.size()-1]; - - if (!isa(CE)) { - HasPlainEdge = true; - continue; - } - CFGStmt CS = CE.getAs(); - if (!CS.isValid()) - continue; + CFGStmt CS = cast(*ri); Stmt *S = CS.getStmt(); if (isa(S)) { HasLiveReturn = true; diff --git a/clang/test/SemaCXX/warn-missing-noreturn.cpp b/clang/test/SemaCXX/warn-missing-noreturn.cpp index 08a20b627c54..4caff66af703 100644 --- a/clang/test/SemaCXX/warn-missing-noreturn.cpp +++ b/clang/test/SemaCXX/warn-missing-noreturn.cpp @@ -93,3 +93,13 @@ int rdar8875247_test() { rdar8875247 f; } // expected-warning{{control reaches end of non-void function}} +struct rdar8875247_B { + rdar8875247_B(); + ~rdar8875247_B(); +}; + +rdar8875247_B test_rdar8875247_B() { + rdar8875247_B f; + return f; +} // no-warning +