r314733 - PR33839: Fix -Wunused handling for structured binding declarations.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 2 15:43:37 PDT 2017


Author: rsmith
Date: Mon Oct  2 15:43:36 2017
New Revision: 314733

URL: http://llvm.org/viewvc/llvm-project?rev=314733&view=rev
Log:
PR33839: Fix -Wunused handling for structured binding declarations.

We warn about a structured binding declaration being unused only if none of its
bindings are used.

Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/SemaCXX/unused.cpp

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=314733&r1=314732&r2=314733&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Oct  2 15:43:36 2017
@@ -1604,7 +1604,24 @@ static bool ShouldDiagnoseUnusedDecl(con
   if (D->isInvalidDecl())
     return false;
 
-  if (D->isReferenced() || D->isUsed() || D->hasAttr<UnusedAttr>() ||
+  bool Referenced = false;
+  if (auto *DD = dyn_cast<DecompositionDecl>(D)) {
+    // For a decomposition declaration, warn if none of the bindings are
+    // referenced, instead of if the variable itself is referenced (which
+    // it is, by the bindings' expressions).
+    for (auto *BD : DD->bindings()) {
+      if (BD->isReferenced()) {
+        Referenced = true;
+        break;
+      }
+    }
+  } else if (!D->getDeclName()) {
+    return false;
+  } else if (D->isReferenced() || D->isUsed()) {
+    Referenced = true;
+  }
+
+  if (Referenced || D->hasAttr<UnusedAttr>() ||
       D->hasAttr<ObjCPreciseLifetimeAttr>())
     return false;
 
@@ -1727,7 +1744,7 @@ void Sema::DiagnoseUnusedDecl(const Name
   else
     DiagID = diag::warn_unused_variable;
 
-  Diag(D->getLocation(), DiagID) << D->getDeclName() << Hint;
+  Diag(D->getLocation(), DiagID) << D << Hint;
 }
 
 static void CheckPoppedLabel(LabelDecl *L, Sema &S) {
@@ -1757,8 +1774,6 @@ void Sema::ActOnPopScope(SourceLocation
     assert(isa<NamedDecl>(TmpD) && "Decl isn't NamedDecl?");
     NamedDecl *D = cast<NamedDecl>(TmpD);
 
-    if (!D->getDeclName()) continue;
-
     // Diagnose unused variables in this scope.
     if (!S->hasUnrecoverableErrorOccurred()) {
       DiagnoseUnusedDecl(D);
@@ -1766,6 +1781,8 @@ void Sema::ActOnPopScope(SourceLocation
         DiagnoseUnusedNestedTypedefs(RD);
     }
 
+    if (!D->getDeclName()) continue;
+
     // If this was a forward reference to a label, verify it was defined.
     if (LabelDecl *LD = dyn_cast<LabelDecl>(D))
       CheckPoppedLabel(LD, *this);
@@ -6164,7 +6181,6 @@ NamedDecl *Sema::ActOnVariableDeclarator
   IdentifierInfo *II = Name.getAsIdentifierInfo();
 
   if (D.isDecompositionDeclarator()) {
-    AddToScope = false;
     // Take the name of the first declarator as our name for diagnostic
     // purposes.
     auto &Decomp = D.getDecompositionDeclarator();

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=314733&r1=314732&r2=314733&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Oct  2 15:43:36 2017
@@ -829,7 +829,10 @@ Sema::ActOnDecompositionDeclarator(Scope
   NamedDecl *New =
       ActOnVariableDeclarator(S, D, DC, TInfo, Previous,
                               MultiTemplateParamsArg(), AddToScope, Bindings);
-  CurContext->addHiddenDecl(New);
+  if (AddToScope) {
+    S->AddDecl(New);
+    CurContext->addHiddenDecl(New);
+  }
 
   if (isInOpenMPDeclareTargetContext())
     checkDeclIsAllowedInOpenMPTarget(nullptr, New);

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=314733&r1=314732&r2=314733&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Oct  2 15:43:36 2017
@@ -677,6 +677,7 @@ TemplateDeclInstantiator::VisitTypeAlias
 Decl *TemplateDeclInstantiator::VisitBindingDecl(BindingDecl *D) {
   auto *NewBD = BindingDecl::Create(SemaRef.Context, Owner, D->getLocation(),
                                     D->getIdentifier());
+  NewBD->setReferenced(D->isReferenced());
   SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewBD);
   return NewBD;
 }

Modified: cfe/trunk/test/SemaCXX/unused.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/unused.cpp?rev=314733&r1=314732&r2=314733&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/unused.cpp (original)
+++ cfe/trunk/test/SemaCXX/unused.cpp Mon Oct  2 15:43:36 2017
@@ -1,6 +1,7 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wunused %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 -Wunused %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wunused %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wunused %s
 
 // PR4103 : Make sure we don't get a bogus unused expression warning
 namespace PR4103 {
@@ -8,7 +9,7 @@ namespace PR4103 {
     char foo;
   };
   class APSInt : public APInt {
-    char bar;
+    char bar; // expected-warning {{private field 'bar' is not used}}
   public:
     APSInt &operator=(const APSInt &RHS);
   };
@@ -69,3 +70,44 @@ namespace UnresolvedLookup {
     }
   };
 }
+
+#if __cplusplus >= 201703L
+namespace PR33839 {
+  void a() {
+    struct X { int a, b; } x;
+    auto [a, b] = x; // expected-warning {{unused variable '[a, b]'}}
+    auto [c, d] = x;
+    (void)d;
+  }
+
+  template<typename T> void f() {
+    struct A { int n; } a[1];
+    for (auto [x] : a) {
+      (void)x;
+    }
+    auto [y] = a[0]; // expected-warning {{unused}}
+  }
+  template<bool b> void g() {
+    struct A { int n; } a[1];
+    for (auto [x] : a) {
+      if constexpr (b)
+        (void)x;
+    }
+
+    auto [y] = a[0];
+    if constexpr (b)
+      (void)y; // ok, even when b == false
+  }
+  template<typename T> void h() {
+    struct A { int n; } a[1];
+    for (auto [x] : a) { // expected-warning {{unused variable '[x]'}}
+    }
+  }
+  void use() { 
+    f<int>(); // expected-note {{instantiation of}}
+    g<true>();
+    g<false>();
+    h<int>(); // expected-note {{instantiation of}}
+  }
+}
+#endif




More information about the cfe-commits mailing list