r202352 - [-Wunreachable-code] Don't warn about trivially unreachable return statements preceded by 'noreturn' functions.
Ted Kremenek
kremenek at apple.com
Wed Feb 26 22:32:32 PST 2014
Author: kremenek
Date: Thu Feb 27 00:32:32 2014
New Revision: 202352
URL: http://llvm.org/viewvc/llvm-project?rev=202352&view=rev
Log:
[-Wunreachable-code] Don't warn about trivially unreachable return statements preceded by 'noreturn' functions.
Modified:
cfe/trunk/lib/Analysis/ReachableCode.cpp
cfe/trunk/test/Sema/warn-unreachable.c
Modified: cfe/trunk/lib/Analysis/ReachableCode.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ReachableCode.cpp?rev=202352&r1=202351&r2=202352&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ReachableCode.cpp (original)
+++ cfe/trunk/lib/Analysis/ReachableCode.cpp Thu Feb 27 00:32:32 2014
@@ -262,6 +262,12 @@ static bool bodyEndsWithNoReturn(const C
return false;
}
+static bool bodyEndsWithNoReturn(const CFGBlock::AdjacentBlock &AB) {
+ const CFGBlock *Pred = AB.getPossiblyUnreachableBlock();
+ assert(!AB.isReachable() && Pred);
+ return bodyEndsWithNoReturn(Pred);
+}
+
static bool isBreakPrecededByNoReturn(const CFGBlock *B,
const Stmt *S) {
if (!isa<BreakStmt>(S) || B->pred_empty())
@@ -269,10 +275,53 @@ static bool isBreakPrecededByNoReturn(co
assert(B->empty());
assert(B->pred_size() == 1);
- const CFGBlock::AdjacentBlock &AB = *B->pred_begin();
- const CFGBlock *Pred = AB.getPossiblyUnreachableBlock();
- assert(!AB.isReachable() && Pred);
- return bodyEndsWithNoReturn(Pred);
+ return bodyEndsWithNoReturn(*B->pred_begin());
+}
+
+static bool isEnumConstant(const Expr *Ex) {
+ const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex);
+ if (!DR)
+ return false;
+ return isa<EnumConstantDecl>(DR->getDecl());
+}
+
+static bool isTrivialExpression(const Expr *Ex) {
+ return isa<IntegerLiteral>(Ex) || isa<StringLiteral>(Ex) ||
+ isEnumConstant(Ex);
+}
+
+static bool isTrivialReturnPrecededByNoReturn(const CFGBlock *B,
+ const Stmt *S) {
+ if (B->pred_empty())
+ return false;
+
+ const Expr *Ex = dyn_cast<Expr>(S);
+ if (!Ex)
+ return false;
+
+ Ex = Ex->IgnoreParenCasts();
+
+ if (!isTrivialExpression(Ex))
+ return false;
+
+ // Look to see if the block ends with a 'return', and see if 'S'
+ // is a substatement. The 'return' may not be the last element in
+ // the block because of destructors.
+ assert(!B->empty());
+ for (CFGBlock::const_reverse_iterator I = B->rbegin(), E = B->rend();
+ I != E; ++I) {
+ if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
+ if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) {
+ const Expr *RE = RS->getRetValue();
+ if (RE && RE->IgnoreParenCasts() == Ex)
+ break;
+ }
+ return false;
+ }
+ }
+
+ assert(B->pred_size() == 1);
+ return bodyEndsWithNoReturn(*B->pred_begin());
}
void DeadCodeScan::reportDeadCode(const CFGBlock *B,
@@ -284,6 +333,10 @@ void DeadCodeScan::reportDeadCode(const
if (isBreakPrecededByNoReturn(B, S))
return;
+ // Suppress trivial 'return' statements that are dead.
+ if (isTrivialReturnPrecededByNoReturn(B, S))
+ return;
+
// Was this an unreachable 'default' case? Such cases are covered
// by -Wcovered-switch-default, if the user so desires.
const Stmt *Label = B->getLabel();
Modified: cfe/trunk/test/Sema/warn-unreachable.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-unreachable.c?rev=202352&r1=202351&r2=202352&view=diff
==============================================================================
--- cfe/trunk/test/Sema/warn-unreachable.c (original)
+++ cfe/trunk/test/Sema/warn-unreachable.c Thu Feb 27 00:32:32 2014
@@ -187,3 +187,16 @@ void unreachable_in_default(MyEnum e) {
}
}
+// Don't warn about trivial dead returns.
+int trivial_dead_return() {
+ raze();
+ // Use the '()' to test that we unwrap such stuff
+ // when looking for dead code.
+ return ((0)); // no-warning
+}
+
+MyEnum trival_dead_return_enum() {
+ raze();
+ return Value1; // no-warning
+}
+
More information about the cfe-commits
mailing list