From: Ted Kremenek Date: Wed, 26 Jan 2011 04:49:52 +0000 (+0000) Subject: Teach -Wreturn-type that destructors can appear X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5811f5978feaa7b89bd89e174fa7ad077b48413e;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124280 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 2f02e158cb..99f19fca78 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/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/test/SemaCXX/warn-missing-noreturn.cpp b/test/SemaCXX/warn-missing-noreturn.cpp index 08a20b627c..4caff66af7 100644 --- a/test/SemaCXX/warn-missing-noreturn.cpp +++ b/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 +