hazohelet created this revision.
hazohelet added reviewers: aaron.ballman, tbaeder, shafik.
Herald added a project: All.
hazohelet requested review of this revision.
Herald added a project: clang.

This patch marks the declarations with initializations in condition expressions 
such as
`if (int var = init)` as unused and unreferenced so that `-Wunused` can warn on 
them.

Fixes https://github.com/llvm/llvm-project/issues/61681


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D152495

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/AST/DeclBase.h
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/AST/ast-dump-if-json.cpp
  clang/test/AST/ast-dump-stmt-json.cpp
  clang/test/AST/ast-dump-stmt.cpp
  clang/test/SemaCXX/warn-unused-variables.cpp

Index: clang/test/SemaCXX/warn-unused-variables.cpp
===================================================================
--- clang/test/SemaCXX/warn-unused-variables.cpp
+++ clang/test/SemaCXX/warn-unused-variables.cpp
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify %s
-// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -Wno-c++1z-extensions -verify -std=c++11 %s
 template<typename T> void f() {
   T t;
   t = 17;
@@ -294,3 +294,36 @@
 }
 
 } // namespace gh54489
+
+namespace inside_condition {
+  void ifs() {
+    if (int hoge = 0) // expected-warning {{unused variable 'hoge'}}
+      return;
+    if (const int const_hoge = 0) // expected-warning {{unused variable 'const_hoge'}}
+      return;
+    else if (int fuga = 0)
+      (void)fuga;
+    else if (int used = 1; int catched = used) // expected-warning {{unused variable 'catched'}}
+      return;
+    else if (int refed = 1; int used = refed)
+      (void)used;
+    else if (int unused1 = 2; int unused2 = 3) // expected-warning {{unused variable 'unused1'}} \
+                                               // expected-warning {{unused variable 'unused2'}}
+      return;
+    else if (int unused = 4; int used = 5) // expected-warning {{unused variable 'unused'}}
+      (void)used;
+    else if (int used = 6; int unused = 7) // expected-warning {{unused variable 'unused'}}
+      (void)used;
+    else if (int used1 = 8; int used2 = 9)
+      (void)(used1 + used2);
+  }
+
+  void fors() {
+    for (int i = 0;int unused = 0;); // expected-warning {{unused variable 'i'}} \
+                                     // expected-warning {{unused variable 'unused'}}
+    for (int i = 0;int used = 0;) // expected-warning {{unused variable 'i'}}
+      (void)used;
+      while(int var = 1) // expected-warning {{unused variable 'var'}}
+        return;
+  }
+} // namespace inside_condition
Index: clang/test/AST/ast-dump-stmt.cpp
===================================================================
--- clang/test/AST/ast-dump-stmt.cpp
+++ clang/test/AST/ast-dump-stmt.cpp
@@ -179,7 +179,7 @@
   // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:8, col:16> col:12 used i 'int' cinit
   // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:16> 'int' 0
   // CHECK-NEXT: DeclStmt
-  // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:19, col:27> col:23 used j 'int' cinit
+  // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:19, col:27> col:23 j 'int' cinit
   // CHECK-NEXT: ImplicitCastExpr
   // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:27> 'int' lvalue Var 0x{{[^ ]*}} 'i' 'int'
   // CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} <col:23> 'bool' <IntegralToBoolean>
Index: clang/test/AST/ast-dump-stmt-json.cpp
===================================================================
--- clang/test/AST/ast-dump-stmt-json.cpp
+++ clang/test/AST/ast-dump-stmt-json.cpp
@@ -4167,7 +4167,6 @@
 // CHECK-NEXT:            "tokLen": 1
 // CHECK-NEXT:           }
 // CHECK-NEXT:          },
-// CHECK-NEXT:          "isUsed": true,
 // CHECK-NEXT:          "name": "j",
 // CHECK-NEXT:          "type": {
 // CHECK-NEXT:           "qualType": "int"
Index: clang/test/AST/ast-dump-if-json.cpp
===================================================================
--- clang/test/AST/ast-dump-if-json.cpp
+++ clang/test/AST/ast-dump-if-json.cpp
@@ -709,7 +709,6 @@
 // CHECK-NEXT:        "tokLen": 2
 // CHECK-NEXT:       }
 // CHECK-NEXT:      },
-// CHECK-NEXT:      "isUsed": true,
 // CHECK-NEXT:      "name": "i",
 // CHECK-NEXT:      "type": {
 // CHECK-NEXT:       "qualType": "int"
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -3998,6 +3998,11 @@
       ConditionVar, ConditionVar->getType().getNonReferenceType(), VK_LValue,
       ConditionVar->getLocation());
 
+  // Ensure that `-Wunused-variable` will be emitted for condition variables
+  // that are not referenced or used later. e.g.: if (int var = init());
+  ConditionVar->setReferenced(false);
+  ConditionVar->setIsUsed(false);
+
   switch (CK) {
   case ConditionKind::Boolean:
     return CheckBooleanCondition(StmtLoc, Condition.get());
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -2843,13 +2843,6 @@
     }
   }
 
-  // FIXME: We should be able to assert this for FunctionDecls as well!
-  // FIXME: We should be able to assert this for all DeclRefExprs, not just
-  // those with a valid source location.
-  assert((ND->isUsed(false) || !isa<VarDecl>(ND) || E->isNonOdrUse() ||
-          !E->getLocation().isValid()) &&
-         "Should not use decl without marking it used!");
-
   if (ND->hasAttr<WeakRefAttr>()) {
     const auto *VD = cast<ValueDecl>(ND);
     ConstantAddress Aliasee = CGM.GetWeakRefReference(VD);
Index: clang/include/clang/AST/DeclBase.h
===================================================================
--- clang/include/clang/AST/DeclBase.h
+++ clang/include/clang/AST/DeclBase.h
@@ -588,7 +588,7 @@
   ///
   /// This should only be used immediately after creating a declaration.
   /// It intentionally doesn't notify any listeners.
-  void setIsUsed() { getCanonicalDecl()->Used = true; }
+  void setIsUsed(bool U = true) { getCanonicalDecl()->Used = U; }
 
   /// Mark the declaration used, in the sense of odr-use.
   ///
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -337,6 +337,10 @@
   can be controlled using ``-fcaret-diagnostics-max-lines=``.
 - Clang no longer emits ``-Wunused-variable`` warnings for variables declared
   with ``__attribute__((cleanup(...)))`` to match GCC's behavior.
+- Clang now warns on unused variables declaread and initialized in condition
+  expressions.
+  (`#61681: <https://github.com/llvm/llvm-project/issues/61681>`_)
+
 
 Bug Fixes in This Version
 -------------------------
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to