From 11ab38baa112fe187f37dd67c684fcbb4aac23d7 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Wed, 16 Apr 2014 07:26:09 +0000 Subject: [PATCH] -Wunreachable-code: refine recognition of unreachable "sigil" to cope with implicit casts in C++. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206360 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 8 ++++++++ lib/AST/Expr.cpp | 21 +++++++++++++++++++++ lib/Analysis/ReachableCode.cpp | 5 ++++- test/SemaCXX/warn-unreachable.cpp | 30 ++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 1 deletion(-) diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index ee5f5b7020..729f8ba7de 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -699,6 +699,9 @@ public: /// or CastExprs, returning their operand. Expr *IgnoreParenCasts() LLVM_READONLY; + /// Ignore casts. Strip off any CastExprs, returning their operand. + Expr *IgnoreCasts() LLVM_READONLY; + /// IgnoreParenImpCasts - Ignore parentheses and implicit casts. Strip off /// any ParenExpr or ImplicitCastExprs, returning their operand. Expr *IgnoreParenImpCasts() LLVM_READONLY; @@ -760,6 +763,11 @@ public: const Expr *IgnoreParenCasts() const LLVM_READONLY { return const_cast(this)->IgnoreParenCasts(); } + /// Strip off casts, but keep parentheses. + const Expr *IgnoreCasts() const LLVM_READONLY { + return const_cast(this)->IgnoreCasts(); + } + const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const LLVM_READONLY { return const_cast(this)->IgnoreParenNoopCasts(Ctx); } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index f023fe804b..4ddd0a239a 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -2400,6 +2400,27 @@ Expr *Expr::IgnoreParenCasts() { } } +Expr *Expr::IgnoreCasts() { + Expr *E = this; + while (true) { + if (CastExpr *P = dyn_cast(E)) { + E = P->getSubExpr(); + continue; + } + if (MaterializeTemporaryExpr *Materialize + = dyn_cast(E)) { + E = Materialize->GetTemporaryExpr(); + continue; + } + if (SubstNonTypeTemplateParmExpr *NTTP + = dyn_cast(E)) { + E = NTTP->getReplacement(); + continue; + } + return E; + } +} + /// IgnoreParenLValueCasts - Ignore parentheses and lvalue-to-rvalue /// casts. This is intended purely as a temporary workaround for code /// that hasn't yet been rewritten to do the right thing about those diff --git a/lib/Analysis/ReachableCode.cpp b/lib/Analysis/ReachableCode.cpp index 3cc8ae4a08..8be1af7cef 100644 --- a/lib/Analysis/ReachableCode.cpp +++ b/lib/Analysis/ReachableCode.cpp @@ -139,6 +139,9 @@ static bool isConfigurationValue(const Stmt *S, if (!S) return false; + if (const Expr *Ex = dyn_cast(S)) + S = Ex->IgnoreCasts(); + // Special case looking for the sigil '()' around an integer literal. if (const ParenExpr *PE = dyn_cast(S)) if (!PE->getLocStart().isMacroID()) @@ -146,7 +149,7 @@ static bool isConfigurationValue(const Stmt *S, IncludeIntegers, true); if (const Expr *Ex = dyn_cast(S)) - S = Ex->IgnoreParenCasts(); + S = Ex->IgnoreCasts(); bool IgnoreYES_NO = false; diff --git a/test/SemaCXX/warn-unreachable.cpp b/test/SemaCXX/warn-unreachable.cpp index 744825e226..b08467ab51 100644 --- a/test/SemaCXX/warn-unreachable.cpp +++ b/test/SemaCXX/warn-unreachable.cpp @@ -327,6 +327,36 @@ void test_with_paren_silencing(int x) { calledFun(); } +void test_with_paren_silencing_impcast(int x) { + if (0) calledFun(); // expected-warning {{will never be executed}} expected-note {{silence by adding parentheses to mark code as explicitly dead}} + if ((0)) calledFun(); // no-warning + + if (1) // expected-note {{silence by adding parentheses to mark code as explicitly dead}} + calledFun(); + else + calledFun(); // expected-warning {{will never be executed}} + + if ((1)) + calledFun(); + else + calledFun(); // no-warning + + if (!1) // expected-note {{silence by adding parentheses to mark code as explicitly dead}} + calledFun(); // expected-warning {{code will never be executed}} + else + calledFun(); + + if ((!1)) + calledFun(); // no-warning + else + calledFun(); + + if (!(1)) + calledFun(); // no-warning + else + calledFun(); +} + void tautological_compare(bool x, int y) { if (x > 10) // expected-note {{silence}} calledFun(); // expected-warning {{will never be executed}} -- 2.40.0