]> granicus.if.org Git - clang/commitdiff
-Wunreachable-code: refine recognition of unreachable "sigil" to cope with implicit...
authorTed Kremenek <kremenek@apple.com>
Wed, 16 Apr 2014 07:26:09 +0000 (07:26 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 16 Apr 2014 07:26:09 +0000 (07:26 +0000)
Fixes <rdar://problem/16631033>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206360 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
lib/AST/Expr.cpp
lib/Analysis/ReachableCode.cpp
test/SemaCXX/warn-unreachable.cpp

index ee5f5b70200fc14870efbe28df747e156749041a..729f8ba7dee69377d3073600d86ca8b0978ed889 100644 (file)
@@ -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<Expr*>(this)->IgnoreParenCasts();
   }
+  /// Strip off casts, but keep parentheses.
+  const Expr *IgnoreCasts() const LLVM_READONLY {
+    return const_cast<Expr*>(this)->IgnoreCasts();
+  }
+
   const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const LLVM_READONLY {
     return const_cast<Expr*>(this)->IgnoreParenNoopCasts(Ctx);
   }
index f023fe804b6b2fc9550d81e545cabf4318d0258a..4ddd0a239aa968f25474b7fde5bd2ff6e18275d4 100644 (file)
@@ -2400,6 +2400,27 @@ Expr *Expr::IgnoreParenCasts() {
   }
 }
 
+Expr *Expr::IgnoreCasts() {
+  Expr *E = this;
+  while (true) {
+    if (CastExpr *P = dyn_cast<CastExpr>(E)) {
+      E = P->getSubExpr();
+      continue;
+    }
+    if (MaterializeTemporaryExpr *Materialize
+        = dyn_cast<MaterializeTemporaryExpr>(E)) {
+      E = Materialize->GetTemporaryExpr();
+      continue;
+    }
+    if (SubstNonTypeTemplateParmExpr *NTTP
+        = dyn_cast<SubstNonTypeTemplateParmExpr>(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
index 3cc8ae4a08109fb07c90b75c845c5a23750cf6b1..8be1af7cef3d3fcf5c211770b2a2bf37c01a75fa 100644 (file)
@@ -139,6 +139,9 @@ static bool isConfigurationValue(const Stmt *S,
   if (!S)
     return false;
 
+  if (const Expr *Ex = dyn_cast<Expr>(S))
+    S = Ex->IgnoreCasts();
+
   // Special case looking for the sigil '()' around an integer literal.
   if (const ParenExpr *PE = dyn_cast<ParenExpr>(S))
     if (!PE->getLocStart().isMacroID())
@@ -146,7 +149,7 @@ static bool isConfigurationValue(const Stmt *S,
                                   IncludeIntegers, true);
 
   if (const Expr *Ex = dyn_cast<Expr>(S))
-    S = Ex->IgnoreParenCasts();
+    S = Ex->IgnoreCasts();
 
   bool IgnoreYES_NO = false;
 
index 744825e226f203ffc79368c0120019fd55f77950..b08467ab51e63dc08e611eb2adb4568766bfd0a0 100644 (file)
@@ -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}}