r370767 - [analyzer] Add a checker option to detect nested dead stores

Kristof Umann via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 3 08:22:44 PDT 2019


Author: szelethus
Date: Tue Sep  3 08:22:43 2019
New Revision: 370767

URL: http://llvm.org/viewvc/llvm-project?rev=370767&view=rev
Log:
[analyzer] Add a checker option to detect nested dead stores

Enables the users to specify an optional flag which would warn for more dead
stores.
Previously it ignored if the dead store happened e.g. in an if condition.

if ((X = generate())) { // dead store to X
}

This patch introduces the `WarnForDeadNestedAssignments` option to the checker,
which is `false` by default - so this change would not affect any previous
users.
I have updated the code, tests and the docs as well. If I missed something, tell
me.

I also ran the analysis on Clang which generated 14 more reports compared to the
unmodified version. All of them seemed reasonable for me.

Related previous patches:
rGf224820b45c6847b91071da8d7ade59f373b96f3

Reviewers: NoQ, krememek, Szelethus, baloghadamsoftware

Reviewed By: Szelethus

Patch by Balázs Benics!

Differential Revision: https://reviews.llvm.org/D66733

Modified:
    cfe/trunk/docs/analyzer/checkers.rst
    cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
    cfe/trunk/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
    cfe/trunk/test/Analysis/analyzer-config.c
    cfe/trunk/test/Analysis/dead-stores.c
    cfe/trunk/test/Analysis/dead-stores.cpp
    cfe/trunk/test/Analysis/dead-stores.m

Modified: cfe/trunk/docs/analyzer/checkers.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/analyzer/checkers.rst?rev=370767&r1=370766&r2=370767&view=diff
==============================================================================
--- cfe/trunk/docs/analyzer/checkers.rst (original)
+++ cfe/trunk/docs/analyzer/checkers.rst Tue Sep  3 08:22:43 2019
@@ -319,6 +319,15 @@ Check for values stored to variables tha
    x = 1; // warn
  }
 
+The ``WarnForDeadNestedAssignments`` option enables the checker to emit
+warnings for nested dead assignments. You can disable with the
+``-analyzer-config deadcode.DeadStores:WarnForDeadNestedAssignments=false``.
+*Defaults to true*.
+
+Would warn for this e.g.:
+if ((y = make_int())) {
+}
+
 .. _nullability-checkers:
 
 nullability

Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=370767&r1=370766&r2=370767&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Tue Sep  3 08:22:43 2019
@@ -648,6 +648,14 @@ let ParentPackage = DeadCode in {
 def DeadStoresChecker : Checker<"DeadStores">,
   HelpText<"Check for values stored to variables that are never read "
            "afterwards">,
+  CheckerOptions<[
+    CmdLineOption<Boolean,
+                  "WarnForDeadNestedAssignments",
+                  "Warns for deadstores in nested assignments."
+                  "E.g.: if ((P = f())) where P is unused.",
+                  "true",
+                  Released>
+  ]>,
   Documentation<HasDocumentation>;
 
 } // end DeadCode

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp?rev=370767&r1=370766&r2=370767&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp Tue Sep  3 08:22:43 2019
@@ -130,6 +130,7 @@ class DeadStoreObs : public LiveVariable
   std::unique_ptr<ReachableCode> reachableCode;
   const CFGBlock *currentBlock;
   std::unique_ptr<llvm::DenseSet<const VarDecl *>> InEH;
+  const bool WarnForDeadNestedAssignments;
 
   enum DeadStoreKind { Standard, Enclosing, DeadIncrement, DeadInit };
 
@@ -137,9 +138,11 @@ public:
   DeadStoreObs(const CFG &cfg, ASTContext &ctx, BugReporter &br,
                const CheckerBase *checker, AnalysisDeclContext *ac,
                ParentMap &parents,
-               llvm::SmallPtrSet<const VarDecl *, 20> &escaped)
+               llvm::SmallPtrSet<const VarDecl *, 20> &escaped,
+               bool warnForDeadNestedAssignments)
       : cfg(cfg), Ctx(ctx), BR(br), Checker(checker), AC(ac), Parents(parents),
-        Escaped(escaped), currentBlock(nullptr) {}
+        Escaped(escaped), currentBlock(nullptr),
+        WarnForDeadNestedAssignments(warnForDeadNestedAssignments) {}
 
   ~DeadStoreObs() override {}
 
@@ -217,11 +220,16 @@ public:
         os << "Value stored to '" << *V << "' is never read";
         break;
 
+      // eg.: f((x = foo()))
       case Enclosing:
-        // Don't report issues in this case, e.g.: "if (x = foo())",
-        // where 'x' is unused later.  We have yet to see a case where
-        // this is a real bug.
-        return;
+        if (!WarnForDeadNestedAssignments)
+          return;
+        BugType = "Dead nested assignment";
+        os << "Although the value stored to '" << *V
+           << "' is used in the enclosing expression, the value is never "
+              "actually read from '"
+           << *V << "'";
+        break;
     }
 
     BR.EmitBasicReport(AC->getDecl(), Checker, BugType, "Dead store", os.str(),
@@ -474,6 +482,8 @@ public:
 namespace {
 class DeadStoresChecker : public Checker<check::ASTCodeBody> {
 public:
+  bool WarnForDeadNestedAssignments = true;
+
   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
                         BugReporter &BR) const {
 
@@ -491,15 +501,20 @@ public:
       ParentMap &pmap = mgr.getParentMap(D);
       FindEscaped FS;
       cfg.VisitBlockStmts(FS);
-      DeadStoreObs A(cfg, BR.getContext(), BR, this, AC, pmap, FS.Escaped);
+      DeadStoreObs A(cfg, BR.getContext(), BR, this, AC, pmap, FS.Escaped,
+                     WarnForDeadNestedAssignments);
       L->runOnAllBlocks(A);
     }
   }
 };
 }
 
-void ento::registerDeadStoresChecker(CheckerManager &mgr) {
-  mgr.registerChecker<DeadStoresChecker>();
+void ento::registerDeadStoresChecker(CheckerManager &Mgr) {
+  auto Chk = Mgr.registerChecker<DeadStoresChecker>();
+
+  const AnalyzerOptions &AnOpts = Mgr.getAnalyzerOptions();
+  Chk->WarnForDeadNestedAssignments =
+      AnOpts.getCheckerBooleanOption(Chk, "WarnForDeadNestedAssignments");
 }
 
 bool ento::shouldRegisterDeadStoresChecker(const LangOptions &LO) {

Modified: cfe/trunk/test/Analysis/analyzer-config.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/analyzer-config.c?rev=370767&r1=370766&r2=370767&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/analyzer-config.c (original)
+++ cfe/trunk/test/Analysis/analyzer-config.c Tue Sep  3 08:22:43 2019
@@ -30,6 +30,7 @@
 // CHECK-NEXT: ctu-dir = ""
 // CHECK-NEXT: ctu-import-threshold = 100
 // CHECK-NEXT: ctu-index-name = externalDefMap.txt
+// CHECK-NEXT: deadcode.DeadStores:WarnForDeadNestedAssignments = true
 // CHECK-NEXT: debug.AnalysisOrder:* = false
 // CHECK-NEXT: debug.AnalysisOrder:Bind = false
 // CHECK-NEXT: debug.AnalysisOrder:EndFunction = false
@@ -93,4 +94,4 @@
 // CHECK-NEXT: unroll-loops = false
 // CHECK-NEXT: widen-loops = false
 // CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 90
+// CHECK-NEXT: num-entries = 91

Modified: cfe/trunk/test/Analysis/dead-stores.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/dead-stores.c?rev=370767&r1=370766&r2=370767&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/dead-stores.c (original)
+++ cfe/trunk/test/Analysis/dead-stores.c Tue Sep  3 08:22:43 2019
@@ -1,102 +1,110 @@
-// RUN: %clang_analyze_cc1 -Wunused-variable -analyzer-checker=core,deadcode.DeadStores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s
-// RUN: %clang_analyze_cc1 -Wunused-variable -analyzer-checker=core,deadcode.DeadStores -analyzer-store=region -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s
+// RUN: %clang_analyze_cc1 -Wunused-variable -fblocks -Wno-unreachable-code     \
+// RUN:  -analyzer-checker=core,deadcode.DeadStores                             \
+// RUN:  -analyzer-config deadcode.DeadStores:WarnForDeadNestedAssignments=false\
+// RUN:  -analyzer-opt-analyze-nested-blocks -verify=non-nested %s
+//
+// RUN: %clang_analyze_cc1 -Wunused-variable -fblocks -Wno-unreachable-code     \
+// RUN:  -analyzer-checker=core,deadcode.DeadStores                             \
+// RUN:  -analyzer-config deadcode.DeadStores:WarnForDeadNestedAssignments=false\
+// RUN:  -analyzer-opt-analyze-nested-blocks -verify=non-nested                 \
+// RUN:  -analyzer-store=region %s
+//
+// RUN: %clang_analyze_cc1 -Wunused-variable -fblocks -Wno-unreachable-code     \
+// RUN:  -analyzer-checker=core,deadcode.DeadStores                             \
+// RUN:  -analyzer-opt-analyze-nested-blocks -verify=non-nested,nested %s
 
 void f1() {
-  int k, y; // expected-warning{{unused variable 'k'}} expected-warning{{unused variable 'y'}}
-  int abc=1;
-  long idx=abc+3*5; // expected-warning {{never read}} expected-warning{{unused variable 'idx'}}
+  int k, y; // non-nested-warning {{unused variable 'k'}}
+            // non-nested-warning at -1 {{unused variable 'y'}}
+  int abc = 1;
+  long idx = abc + 3 * 5; // non-nested-warning {{never read}}
+                          // non-nested-warning at -1 {{unused variable 'idx'}}
 }
 
 void f2(void *b) {
- char *c = (char*)b; // no-warning
- char *d = b+1; // expected-warning {{never read}} expected-warning{{unused variable 'd'}}
- printf("%s", c); // expected-warning{{implicitly declaring library function 'printf' with type 'int (const char *, ...)'}} \
- // expected-note{{include the header <stdio.h> or explicitly provide a declaration for 'printf'}}
+  char *c = (char *)b; // no-warning
+  char *d = b + 1;     // non-nested-warning {{never read}}
+                       // non-nested-warning at -1 {{unused variable 'd'}}
+  printf("%s", c);
+  // non-nested-warning at -1 {{implicitly declaring library function 'printf' with type 'int (const char *, ...)'}}
+  // non-nested-note at -2 {{include the header <stdio.h> or explicitly provide a declaration for 'printf'}}
 }
 
 int f();
-
 void f3() {
   int r;
   if ((r = f()) != 0) { // no-warning
-    int y = r; // no-warning
+    int y = r;          // no-warning
     printf("the error is: %d\n", y);
   }
 }
 
 void f4(int k) {
-  
   k = 1;
-  
   if (k)
     f1();
-    
-  k = 2;  // expected-warning {{never read}}
+  k = 2; // non-nested-warning {{never read}}
 }
-  
-void f5() {
-
-  int x = 4; // no-warning
-  int *p = &x; // expected-warning{{never read}} expected-warning{{unused variable 'p'}}
 
+void f5() {
+  int x = 4;   // no-warning
+  int *p = &x; // non-nested-warning {{never read}}
+               // non-nested-warning at -1 {{unused variable 'p'}}
 }
 
-//
 int f6() {
-  
   int x = 4;
   ++x; // no-warning
   return 1;
 }
 
-int f7(int *p) {  
+int f7(int *p) {
   // This is allowed for defensive programming.
-  p = 0; // no-warning  
+  p = 0; // no-warning
   return 1;
 }
 
-int f7b(int *p) {  
+int f7b(int *p) {
   // This is allowed for defensive programming.
-  p = (0); // no-warning  
+  p = (0); // no-warning
   return 1;
 }
 
-int f7c(int *p) {  
+int f7c(int *p) {
   // This is allowed for defensive programming.
-  p = (void*) 0; // no-warning  
+  p = (void *)0; // no-warning
   return 1;
 }
 
-int f7d(int *p) {  
+int f7d(int *p) {
   // This is allowed for defensive programming.
-  p = (void*) (0); // no-warning  
+  p = (void *)(0); // no-warning
   return 1;
 }
 
-// Don't warn for dead stores in nested expressions.  We have yet
-// to see a real bug in this scenario.
+// Warn for dead stores in nested expressions.
 int f8(int *p) {
   extern int *baz();
-  if ((p = baz())) // no-warning
+  if ((p = baz())) // nested-warning {{Although the value stored}}
     return 1;
   return 0;
 }
 
 int f9() {
   int x = 4;
-  x = x + 10; // expected-warning{{never read}}
+  x = x + 10; // non-nested-warning {{never read}}
   return 1;
 }
 
 int f10() {
   int x = 4;
-  x = 10 + x; // expected-warning{{never read}}
+  x = 10 + x; // non-nested-warning {{never read}}
   return 1;
 }
 
 int f11() {
   int x = 4;
-  return x++; // expected-warning{{never read}}
+  return x++; // non-nested-warning {{never read}}
 }
 
 int f11b() {
@@ -105,38 +113,38 @@ int f11b() {
 }
 
 int f12a(int y) {
-  int x = y;  // expected-warning{{unused variable 'x'}}
+  int x = y; // non-nested-warning {{unused variable 'x'}}
   return 1;
 }
+
 int f12b(int y) {
-  int x __attribute__((unused)) = y;  // no-warning
+  int x __attribute__((unused)) = y; // no-warning
   return 1;
 }
+
 int f12c(int y) {
   // Allow initialiation of scalar variables by parameters as a form of
   // defensive programming.
-  int x = y;  // no-warning
+  int x = y; // no-warning
   x = 1;
   return x;
 }
 
 // Filed with PR 2630.  This code should produce no warnings.
-int f13(void)
-{
+int f13(void) {
   int a = 1;
   int b, c = b = a + a;
 
   if (b > 0)
     return (0);
-
   return (a + b + c);
 }
 
 // Filed with PR 2763.
 int f14(int count) {
   int index, nextLineIndex;
-  for (index = 0; index < count; index = nextLineIndex+1) {
-    nextLineIndex = index+1;  // no-warning
+  for (index = 0; index < count; index = nextLineIndex + 1) {
+    nextLineIndex = index + 1; // no-warning
     continue;
   }
   return index;
@@ -144,16 +152,15 @@ int f14(int count) {
 
 // Test case for <rdar://problem/6248086>
 void f15(unsigned x, unsigned y) {
-  int count = x * y;   // no-warning
-  int z[count]; // expected-warning{{unused variable 'z'}}
+  int count = x * y; // no-warning
+  int z[count];      // non-nested-warning {{unused variable 'z'}}
 }
 
-// Don't warn for dead stores in nested expressions.  We have yet
-// to see a real bug in this scenario.
+// Warn for dead stores in nested expressions.
 int f16(int x) {
   x = x * 2;
-  x = sizeof(int [x = (x || x + 1) * 2])
-      ? 5 : 8;
+  x = sizeof(int[x = (x || x + 1) * 2]) ? 5 : 8;
+  // nested-warning at -1 {{Although the value stored}}
   return x;
 }
 
@@ -168,39 +175,39 @@ void f17() {
 // what that value is actually used.  In other words, don't say "Although the
 // value stored to 'x' is used...".
 int f18() {
-   int x = 0; // no-warning
-   if (1)
-      x = 10;  // expected-warning{{Value stored to 'x' is never read}}
-   while (1)
-      x = 10;  // expected-warning{{Value stored to 'x' is never read}}
-   // unreachable.
-   do
-      x = 10;   // no-warning
-   while (1);
-   return (x = 10); // no-warning
+  int x = 0; // no-warning
+  if (1)
+    x = 10; // non-nested-warning {{Value stored to 'x' is never read}}
+  while (1)
+    x = 10; // non-nested-warning {{Value stored to 'x' is never read}}
+  // unreachable.
+  do
+    x = 10; // no-warning
+  while (1);
+  return (x = 10); // no-warning
 }
 
 int f18_a() {
-   int x = 0; // no-warning
-   return (x = 10); // no-warning
+  int x = 0;       // no-warning
+  return (x = 10); // nested-warning {{Although the value stored}}
 }
 
 void f18_b() {
-   int x = 0; // no-warning
-   if (1)
-      x = 10;  // expected-warning{{Value stored to 'x' is never read}}
+  int x = 0; // no-warning
+  if (1)
+    x = 10; // non-nested-warning {{Value stored to 'x' is never read}}
 }
 
 void f18_c() {
   int x = 0;
   while (1)
-     x = 10;  // expected-warning{{Value stored to 'x' is never read}}
+    x = 10; // non-nested-warning {{Value stored to 'x' is never read}}
 }
 
 void f18_d() {
   int x = 0; // no-warning
   do
-     x = 10;   // expected-warning{{Value stored to 'x' is never read}}
+    x = 10; // non-nested-warning {{Value stored to 'x' is never read}}
   while (1);
 }
 
@@ -208,7 +215,7 @@ void f18_d() {
 //  http://llvm.org/bugs/show_bug.cgi?id=3514
 extern const int MyConstant;
 int f19(void) {
-  int x = MyConstant;  // no-warning
+  int x = MyConstant; // no-warning
   x = 1;
   return x;
 }
@@ -217,7 +224,7 @@ int f19b(void) { // This case is the sam
   const int MyConstant = 0;
   int x = MyConstant; // no-warning
   x = 1;
-  return x;  
+  return x;
 }
 
 void f20(void) {
@@ -228,8 +235,7 @@ void f20(void) {
 void halt() __attribute__((noreturn));
 int f21() {
   int x = 4;
-  
-  x = x + 1; // expected-warning{{never read}}
+  x = x + 1; // non-nested-warning {{never read}}
   if (1) {
     halt();
     (void)x;
@@ -261,7 +267,7 @@ void f22() {
   int y19 = 4;
   int y20 = 4;
 
-  x = x + 1; // expected-warning{{never read}}
+  x = x + 1; // non-nested-warning {{never read}}
   ++y1;
   ++y2;
   ++y3;
@@ -309,13 +315,13 @@ void f22() {
     } else
       (void)x;
     (void)x;
-  break;
+    break;
   case 4:
-    0 ? : ((void)y4, ({ return; }));
+    0 ?: ((void)y4, ({ return; }));
     (void)x;
     break;
   case 5:
-    1 ? : (void)x;
+    1 ?: (void)x;
     0 ? (void)x : ((void)y5, ({ return; }));
     (void)x;
     break;
@@ -326,11 +332,13 @@ void f22() {
   case 7:
     (void)(0 && x);
     (void)y7;
-    (void)(0 || (y8, ({ return; }), 1));  // expected-warning {{expression result unused}}
+    (void)(0 || (y8, ({ return; }), 1));
+    // non-nested-warning at -1 {{expression result unused}}
     (void)x;
     break;
   case 8:
-    (void)(1 && (y9, ({ return; }), 1));  // expected-warning {{expression result unused}}
+    (void)(1 && (y9, ({ return; }), 1));
+    // non-nested-warning at -1 {{expression result unused}}
     (void)x;
     break;
   case 9:
@@ -365,16 +373,16 @@ void f22() {
     for (;;) {
       (void)y16;
     }
-    (void)x;    
+    (void)x;
     break;
   case 15:
-    for (;1;) {
+    for (; 1;) {
       (void)y17;
     }
     (void)x;
     break;
   case 16:
-    for (;0;) {
+    for (; 0;) {
       (void)x;
     }
     (void)y18;
@@ -390,28 +398,34 @@ void f22() {
   }
 }
 
-void f23_aux(const char* s);
+void f23_aux(const char *s);
 void f23(int argc, char **argv) {
   int shouldLog = (argc > 1); // no-warning
-  ^{ 
-     if (shouldLog) f23_aux("I did too use it!\n");
-     else f23_aux("I shouldn't log.  Wait.. d'oh!\n");
+  ^{
+    if (shouldLog)
+      f23_aux("I did too use it!\n");
+    else
+      f23_aux("I shouldn't log.  Wait.. d'oh!\n");
   }();
 }
 
 void f23_pos(int argc, char **argv) {
-  int shouldLog = (argc > 1); // expected-warning{{Value stored to 'shouldLog' during its initialization is never read}} expected-warning{{unused variable 'shouldLog'}}
-  ^{ 
-     f23_aux("I did too use it!\n");
-  }();  
+  int shouldLog = (argc > 1);
+  // non-nested-warning at -1 {{Value stored to 'shouldLog' during its initialization is never read}}
+  // non-nested-warning at -2 {{unused variable 'shouldLog'}}
+  ^{
+    f23_aux("I did too use it!\n");
+  }();
 }
 
 void f24_A(int y) {
   // FIXME: One day this should be reported as dead since 'z = x + y' is dead.
   int x = (y > 2); // no-warning
-  ^ {
-      int z = x + y; // expected-warning{{Value stored to 'z' during its initialization is never read}} expected-warning{{unused variable 'z'}}
-  }();  
+  ^{
+    int z = x + y;
+    // non-nested-warning at -1 {{Value stored to 'z' during its initialization is never read}}
+    // non-nested-warning at -2 {{unused variable 'z'}}
+  }();
 }
 
 void f24_B(int y) {
@@ -426,7 +440,7 @@ void f24_B(int y) {
 int f24_C(int y) {
   // FIXME: One day this should be reported as dead since 'x' is just overwritten.
   __block int x = (y > 2); // no-warning
-  ^{ 
+  ^{
     x = 5; // no-warning
   }();
   return x;
@@ -434,32 +448,35 @@ int f24_C(int y) {
 
 int f24_D(int y) {
   __block int x = (y > 2); // no-warning
-  ^{ 
+  ^{
     if (y > 4)
       x = 5; // no-warning
   }();
   return x;
 }
 
-// This example shows that writing to a variable captured by a block means that it might
-// not be dead.
+// This example shows that writing to a variable captured by a block means that
+// it might not be dead.
 int f25(int y) {
   __block int x = (y > 2);
   __block int z = 0;
-  void (^foo)() = ^{ z = x + y; };
+  void (^foo)() = ^{
+    z = x + y;
+  };
   x = 4; // no-warning
   foo();
-  return z; 
+  return z;
 }
 
-// This test is mostly the same as 'f25', but shows that the heuristic of pruning out dead
-// stores for variables that are just marked '__block' is overly conservative.
+// This test is mostly the same as 'f25', but shows that the heuristic of
+// pruning out dead stores for variables that are just marked '__block' is
+// overly conservative.
 int f25_b(int y) {
   // FIXME: we should eventually report a dead store here.
   __block int x = (y > 2);
   __block int z = 0;
   x = 4; // no-warning
-  return z; 
+  return z;
 }
 
 int f26_nestedblocks() {
@@ -468,10 +485,10 @@ int f26_nestedblocks() {
   __block int y = 0;
   ^{
     int k;
-    k = 1; // expected-warning{{Value stored to 'k' is never read}}
+    k = 1; // non-nested-warning {{Value stored to 'k' is never read}}
     ^{
-        y = z + 1;
-     }();
+      y = z + 1;
+    }();
   }();
   return y;
 }
@@ -480,11 +497,13 @@ int f26_nestedblocks() {
 // placed within the increment code of for loops.
 void rdar8014335() {
   for (int i = 0 ; i != 10 ; ({ break; })) {
-    for ( ; ; ({ ++i; break; })) ; // expected-warning {{'break' is bound to current loop, GCC binds it to the enclosing loop}}
+    for (;; ({ ++i; break; }))
+      ;
+    // non-nested-warning at -2 {{'break' is bound to current loop, GCC binds it to the enclosing loop}}
     // Note that the next value stored to 'i' is never executed
     // because the next statement to be executed is the 'break'
     // in the increment code of the first loop.
-    i = i * 3; // expected-warning{{Value stored to 'i' is never read}}
+    i = i * 3; // non-nested-warning {{Value stored to 'i' is never read}}
   }
 }
 
@@ -517,10 +536,8 @@ void rdar8405222_aux(int i);
 void rdar8405222() {
   const int show = 0;
   int i = 0;
-    
   if (show)
-      i = 5; // no-warning
-
+    i = 5; // no-warning
   if (show)
     rdar8405222_aux(i);
 }
@@ -529,13 +546,13 @@ void rdar8405222() {
 // silencing heuristics.
 int radar11185138_foo() {
   int x, y;
-  x = y = 0; // expected-warning {{never read}}
+  x = y = 0; // non-nested-warning {{never read}}
   return y;
 }
 
 int rdar11185138_bar() {
   int y;
-  int x = y = 0; // no-warning
+  int x = y = 0; // nested-warning {{Although the value stored}}
   x = 2;
   y = 2;
   return x + y;
@@ -550,26 +567,58 @@ int *radar11185138_baz() {
 int getInt();
 int *getPtr();
 void testBOComma() {
-  int x0 = (getInt(), 0); // expected-warning{{unused variable 'x0'}}
-  int x1 = (getInt(), getInt()); // expected-warning {{Value stored to 'x1' during its initialization is never read}} // expected-warning{{unused variable 'x1'}}
-  int x2 = (getInt(), getInt(), getInt()); //expected-warning{{Value stored to 'x2' during its initialization is never read}} // expected-warning{{unused variable 'x2'}}
+  int x0 = (getInt(), 0); // non-nested-warning {{unused variable 'x0'}}
+  int x1 = (getInt(), getInt());
+  // non-nested-warning at -1 {{Value stored to 'x1' during its initialization is never read}}
+  // non-nested-warning at -2 {{unused variable 'x1'}}
+
+  int x2 = (getInt(), getInt(), getInt());
+  // non-nested-warning at -1 {{Value stored to 'x2' during its initialization is never read}}
+  // non-nested-warning at -2 {{unused variable 'x2'}}
+
   int x3;
-  x3 = (getInt(), getInt(), 0); // expected-warning{{Value stored to 'x3' is never read}}
-  int x4 = (getInt(), (getInt(), 0)); // expected-warning{{unused variable 'x4'}}
+  x3 = (getInt(), getInt(), 0);
+  // non-nested-warning at -1 {{Value stored to 'x3' is never read}}
+
+  int x4 = (getInt(), (getInt(), 0));
+  // non-nested-warning at -1 {{unused variable 'x4'}}
+
   int y;
-  int x5 = (getInt(), (y = 0)); // expected-warning{{unused variable 'x5'}}
-  int x6 = (getInt(), (y = getInt())); //expected-warning {{Value stored to 'x6' during its initialization is never read}} // expected-warning{{unused variable 'x6'}}
-  int x7 = 0, x8 = getInt(); //expected-warning {{Value stored to 'x8' during its initialization is never read}} // expected-warning{{unused variable 'x8'}} // expected-warning{{unused variable 'x7'}}
-  int x9 = getInt(), x10 = 0; //expected-warning {{Value stored to 'x9' during its initialization is never read}} // expected-warning{{unused variable 'x9'}}  // expected-warning{{unused variable 'x10'}}
-  int m = getInt(), mm, mmm; //expected-warning {{Value stored to 'm' during its initialization is never read}} // expected-warning{{unused variable 'm'}} // expected-warning{{unused variable 'mm'}} // expected-warning{{unused variable 'mmm'}}
-  int n, nn = getInt(); //expected-warning {{Value stored to 'nn' during its initialization is never read}} // expected-warning{{unused variable 'n'}} // expected-warning{{unused variable 'nn'}}
+  int x5 = (getInt(), (y = 0));
+  // non-nested-warning at -1 {{unused variable 'x5'}}
+  // nested-warning at -2 {{Although the value stored}}
+
+  int x6 = (getInt(), (y = getInt()));
+  // non-nested-warning at -1 {{Value stored to 'x6' during its initialization is never read}}
+  // non-nested-warning at -2 {{unused variable 'x6'}}
+  // nested-warning at -3 {{Although the value stored}}
+
+  int x7 = 0, x8 = getInt();
+  // non-nested-warning at -1 {{Value stored to 'x8' during its initialization is never read}}
+  // non-nested-warning at -2 {{unused variable 'x8'}}
+  // non-nested-warning at -3 {{unused variable 'x7'}}
+
+  int x9 = getInt(), x10 = 0;
+  // non-nested-warning at -1 {{Value stored to 'x9' during its initialization is never read}}
+  // non-nested-warning at -2 {{unused variable 'x9'}}
+  // non-nested-warning at -3 {{unused variable 'x10'}}
+
+  int m = getInt(), mm, mmm;
+  // non-nested-warning at -1 {{Value stored to 'm' during its initialization is never read}}
+  // non-nested-warning at -2 {{unused variable 'm'}}
+  // non-nested-warning at -3 {{unused variable 'mm'}}
+  // non-nested-warning at -4 {{unused variable 'mmm'}}
+
+  int n, nn = getInt();
+  // non-nested-warning at -1 {{Value stored to 'nn' during its initialization is never read}}
+  // non-nested-warning at -2 {{unused variable 'n'}}
+  // non-nested-warning at -3 {{unused variable 'nn'}}
 
   int *p;
   p = (getPtr(), (int *)0); // no warning
-
 }
 
 void testVolatile() {
-    volatile int v;
-    v = 0; // no warning
+  volatile int v;
+  v = 0; // no warning
 }

Modified: cfe/trunk/test/Analysis/dead-stores.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/dead-stores.cpp?rev=370767&r1=370766&r2=370767&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/dead-stores.cpp (original)
+++ cfe/trunk/test/Analysis/dead-stores.cpp Tue Sep  3 08:22:43 2019
@@ -1,15 +1,26 @@
-// RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++11 -analyzer-checker=deadcode.DeadStores -verify -Wno-unreachable-code %s
-// RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++11 -analyzer-store=region -analyzer-checker=deadcode.DeadStores -verify -Wno-unreachable-code %s
+// RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++11    \
+// RUN:  -analyzer-checker=deadcode.DeadStores -Wno-unreachable-code            \
+// RUN:  -analyzer-config deadcode.DeadStores:WarnForDeadNestedAssignments=false\
+// RUN:  -verify=non-nested %s
+//
+// RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++11    \
+// RUN:  -analyzer-store=region -analyzer-checker=deadcode.DeadStores           \
+// RUN:  -analyzer-config deadcode.DeadStores:WarnForDeadNestedAssignments=false\
+// RUN:  -Wno-unreachable-code -verify=non-nested %s
+//
+// RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++11    \
+// RUN:  -analyzer-checker=deadcode.DeadStores -Wno-unreachable-code            \
+// RUN:  -verify=non-nested,nested %s
 
 //===----------------------------------------------------------------------===//
 // Basic dead store checking (but in C++ mode).
 //===----------------------------------------------------------------------===//
 
 int j;
+int make_int();
 void test1() {
   int x = 4;
-
-  x = x + 1; // expected-warning{{never read}}
+  x = x + 1; // non-nested-warning {{never read}}
 
   switch (j) {
   case 1:
@@ -17,6 +28,11 @@ void test1() {
     (void)x;
     break;
   }
+
+  int y;
+  (void)y;
+  if ((y = make_int())) // nested-warning {{Although the value stored}}
+    return;
 }
 
 //===----------------------------------------------------------------------===//
@@ -25,6 +41,7 @@ void test1() {
 
 class Test2 {
   int &x;
+
 public:
   Test2(int &y) : x(y) {}
   ~Test2() { ++x; }
@@ -66,17 +83,17 @@ void test2_b() {
 //===----------------------------------------------------------------------===//
 
 void test3_a(int x) {
-   x = x + 1; // expected-warning{{never read}}
+  x = x + 1; // non-nested-warning {{never read}}
 }
 
 void test3_b(int &x) {
-  x = x + 1; // no-warninge
+  x = x + 1; // no-warning
 }
 
 void test3_c(int x) {
   int &y = x;
-  // Shows the limitation of dead stores tracking.  The write is really
-  // dead since the value cannot escape the function.
+  // Shows the limitation of dead stores tracking. The write is really dead
+  // since the value cannot escape the function.
   ++y; // no-warning
 }
 
@@ -94,7 +111,7 @@ void test3_e(int &x) {
 //===----------------------------------------------------------------------===//
 
 static void test_new(unsigned n) {
-  char **p = new char* [n]; // expected-warning{{never read}}
+  char **p = new char *[n]; // non-nested-warning {{never read}}
 }
 
 //===----------------------------------------------------------------------===//
@@ -102,11 +119,11 @@ static void test_new(unsigned n) {
 //===----------------------------------------------------------------------===//
 
 namespace foo {
-  int test_4(int x) {
-    x = 2; // expected-warning{{Value stored to 'x' is never read}}
-    x = 2;
-    return x;
-  }
+int test_4(int x) {
+  x = 2; // non-nested-warning {{Value stored to 'x' is never read}}
+  x = 2;
+  return x;
+}
 }
 
 //===----------------------------------------------------------------------===//
@@ -119,42 +136,39 @@ int test_5() {
   try {
     x = 2; // no-warning
     test_5_Aux();
-  }
-  catch (int z) {
+  } catch (int z) {
     return x + z;
   }
   return 1;
 }
 
-
 int test_6_aux(unsigned x);
-
 void test_6() {
-  unsigned currDestLen = 0;  // no-warning
+  unsigned currDestLen = 0; // no-warning
   try {
     while (test_6_aux(currDestLen)) {
       currDestLen += 2; // no-warning
-    } 
+    }
+  } catch (void *) {
   }
-  catch (void *) {}
 }
 
 void test_6b() {
-  unsigned currDestLen = 0;  // no-warning
+  unsigned currDestLen = 0; // no-warning
   try {
     while (test_6_aux(currDestLen)) {
-      currDestLen += 2; // expected-warning {{Value stored to 'currDestLen' is never read}}
+      currDestLen += 2;
+      // non-nested-warning at -1 {{Value stored to 'currDestLen' is never read}}
       break;
-    } 
+    }
+  } catch (void *) {
   }
-  catch (void *) {}
 }
 
-
 void testCXX11Using() {
   using Int = int;
   Int value;
-  value = 1; // expected-warning {{never read}}
+  value = 1; // non-nested-warning {{never read}}
 }
 
 //===----------------------------------------------------------------------===//
@@ -177,13 +191,14 @@ int radar_13213575() {
 template <class T>
 void test_block_in_dependent_context(typename T::some_t someArray) {
   ^{
-     int i = someArray[0]; // no-warning
+    int i = someArray[0]; // no-warning
   }();
 }
 
 void test_block_in_non_dependent_context(int *someArray) {
   ^{
-     int i = someArray[0]; // expected-warning {{Value stored to 'i' during its initialization is never read}}
+    int i = someArray[0];
+    // non-nested-warning at -1 {{Value stored to 'i' during its initialization is never read}}
   }();
 }
 

Modified: cfe/trunk/test/Analysis/dead-stores.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/dead-stores.m?rev=370767&r1=370766&r2=370767&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/dead-stores.m (original)
+++ cfe/trunk/test/Analysis/dead-stores.m Tue Sep  3 08:22:43 2019
@@ -1,5 +1,4 @@
 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -analyzer-checker=deadcode.DeadStores,osx.cocoa.RetainCount -fblocks -verify -Wno-objc-root-class %s
-// expected-no-diagnostics
 
 typedef signed char BOOL;
 typedef unsigned int NSUInteger;
@@ -72,7 +71,8 @@ void foo_rdar8527823();
 
 @implementation Rdar7947686_B
 - (id) init {
-  id x = (self = [super init]); // no-warning
+  id x = (self = [super init]);
+  // expected-warning at -1 {{Although the value stored to 'self'}}
   return x;
 }
 @end




More information about the cfe-commits mailing list