CarlosAlbertoEnciso created this revision.
CarlosAlbertoEnciso added reviewers: rsmith, erichkeane, probinson, dblaikie.
CarlosAlbertoEnciso added a project: clang.
Herald added subscribers: cfe-commits, JDevlieghere, aprantl.

Add -Wunused-using, a warning that finds unused using declarations.
Also added an alias -Wunused-usings.

This patch uses a similar approach as the work done for the typedefs
as discussed in:

https://reviews.llvm.org/rC217298

It uses the 'used' and 'referenced' available bits for the declarations.

As consequence of a previous work on Debug Information done by:

https://reviews.llvm.org/D6173

The size of the Debug Information increased by a considerable factor,
as discussed in:

http://clang-developers.42468.n3.nabble.com/r222220-causes-real-debug-info-bloat-td4045257.html

For the below test:

  namespace nsp {
    void foo();
  }
  
  using foo;

A debug information entries are generated for the namespace
and for the using declaration.

In order to reduce the debug information for those specific cases,
the work is divided in 2 parts:

- Emit a warning for the unused using
- Do not generate debug information for the unused using

The current patch deals with the first part and it covers global
and local detection of unused using declarations.

For the below test, I have marked the generated warnings

  namespace nsp {
    void foo();
    int var;
  }
  
  using foo;     <-- warning
  using var;     <-- warning  
  
  void bar() {
    using foo;     <-- warning
    using var;     <-- warning
  }

However, there is a specific case, where an unused using
escapes the warning.

Adding the following function 'bar'

  void bar() {
    nsp::var = 1;
  }

it causes the warning to the global unused 'using var'
not being issued, as the assignment sets the 'used' bit,
despite of using the qualified 'var'.

  namespace nsp {
    void foo();
    int var;
  }using var
  
  using foo;     <-- warning
  using var;     <-- MISSING warning  
  
  void bar() {
    using foo;     <-- warning
    using var;     <-- warning
  }
  
  void bar() {
    nsp::var = 1;
  }

Thanks for your view on this issue and on the general approach.


Repository:
  rC Clang

https://reviews.llvm.org/D44826

Files:
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/ExternalSemaSource.h
  include/clang/Sema/MultiplexExternalSemaSource.h
  include/clang/Sema/Sema.h
  include/clang/Serialization/ASTBitCodes.h
  include/clang/Serialization/ASTReader.h
  lib/Sema/MultiplexExternalSemaSource.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclCXX.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTWriter.cpp
  test/FixIt/fixit.cpp
  test/Modules/Inputs/module.map
  test/Modules/Inputs/warn-unused-using.h
  test/Modules/warn-unused-using.cpp
  test/SemaCXX/coreturn.cpp
  test/SemaCXX/warn-unused-using-serialize.cpp
  test/SemaCXX/warn-unused-using.cpp

Index: test/SemaCXX/warn-unused-using.cpp
===================================================================
--- test/SemaCXX/warn-unused-using.cpp
+++ test/SemaCXX/warn-unused-using.cpp
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -fsyntax-only -Wunused-using -verify -std=c++1y %s
+
+namespace nsp {
+  void Print();
+  int var;
+  typedef int INT;
+  typedef char CHAR;
+  typedef float FLOAT;
+}
+
+using nsp::Print; // expected-warning {{unused using 'Print'}}
+using nsp::var; // expected-warning {{unused using 'var'}}
+
+void Foo() {
+  using nsp::Print; // expected-warning {{unused using 'Print'}}
+  {
+    using nsp::var; // expected-warning {{unused using 'var'}}
+    {
+      using nsp::INT; // expected-warning {{unused using 'INT'}}
+      using nsp::FLOAT; // expected-warning {{unused using 'FLOAT'}}
+    }
+  }
+}
+
+void Bar() {
+  using nsp::FLOAT; // no diag
+  FLOAT f;
+  f = 2.0;
+}
+
+struct A {
+  virtual void Foo(double x) const;
+};
+struct B : A {
+  using A::Foo;  // expected-warning {{unused using 'Foo'}}
+  virtual void Foo(double x) const;
+};
+
+void one() {
+  B b;
+  b.Foo(1.0);
+}
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-using"
+using nsp::CHAR; // no diag
+#pragma clang diagnostic pop
+
+using nsp::CHAR;  // expected-warning {{unused using 'CHAR'}}
Index: test/SemaCXX/warn-unused-using-serialize.cpp
===================================================================
--- test/SemaCXX/warn-unused-using-serialize.cpp
+++ test/SemaCXX/warn-unused-using-serialize.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang -x c++-header -c -Wunused-using %s -o %t.gch -Werror
+// RUN: %clang -DBE_THE_SOURCE -c -Wunused-using -include %t %s -o /dev/null 2>&1 | FileCheck %s
+// RUN: %clang -DBE_THE_SOURCE -c -Wunused-using -include %t %s -o /dev/null 2>&1 | FileCheck %s
+
+#ifndef BE_THE_SOURCE
+namespace nsp {
+  typedef int INT;
+}
+//inline void foo() {
+// The warning should fire every time the pch file is used, not when it's built.
+// CHECK: warning: unused using 'INT'
+  using nsp::INT;
+//}
+#endif
Index: test/SemaCXX/coreturn.cpp
===================================================================
--- test/SemaCXX/coreturn.cpp
+++ test/SemaCXX/coreturn.cpp
@@ -2,7 +2,7 @@
 #include "Inputs/std-coroutine.h"
 
 using std::experimental::suspend_always;
-using std::experimental::suspend_never;
+using std::experimental::suspend_never; // expected-warning {{unused using 'suspend_never'}}
 
 struct awaitable {
   bool await_ready();
Index: test/Modules/warn-unused-using.cpp
===================================================================
--- test/Modules/warn-unused-using.cpp
+++ test/Modules/warn-unused-using.cpp
@@ -0,0 +1,9 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -Wunused-using -x objective-c++ -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs %s -fsyntax-only 2>&1 | FileCheck %s -check-prefix=CHECK_1
+// RUN: %clang_cc1 -Wunused-using -x objective-c++ -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs %s -fsyntax-only 2>&1 | FileCheck %s -check-prefix=CHECK_2 --allow-empty
+
+// For modules, the warning should only fire the first time, when the module is
+// built.
+// CHECK_1: warning: unused using 'INT'
+// CHECK_2-NOT: warning: unused using 'INT'
+@import warn_unused_using;
Index: test/Modules/Inputs/warn-unused-using.h
===================================================================
--- test/Modules/Inputs/warn-unused-using.h
+++ test/Modules/Inputs/warn-unused-using.h
@@ -0,0 +1,6 @@
+namespace nsp {
+  typedef int INT;
+}
+inline void foo() {
+  using nsp::INT;
+}
Index: test/Modules/Inputs/module.map
===================================================================
--- test/Modules/Inputs/module.map
+++ test/Modules/Inputs/module.map
@@ -307,6 +307,10 @@
   header "warn-unused-local-typedef.h"
 }
 
+module warn_unused_using {
+  header "warn-unused-using.h"
+}
+
 module using_decl {
   module a { header "using-decl-a.h" export * }
   module b { header "using-decl-b.h" export * }
Index: test/FixIt/fixit.cpp
===================================================================
--- test/FixIt/fixit.cpp
+++ test/FixIt/fixit.cpp
@@ -1,12 +1,12 @@
-// RUN: %clang_cc1 -pedantic -Wall -Wno-comment -verify -fcxx-exceptions -x c++ -std=c++98 %s
+// RUN: %clang_cc1 -pedantic -Wall -Wno-unused-using -Wno-comment -verify -fcxx-exceptions -x c++ -std=c++98 %s
 // RUN: cp %s %t-98
-// RUN: not %clang_cc1 -pedantic -Wall -Wno-comment -fcxx-exceptions -fixit -x c++ -std=c++98 %t-98
-// RUN: %clang_cc1 -fsyntax-only -pedantic -Wall -Werror -Wno-comment -fcxx-exceptions -x c++ -std=c++98 %t-98
+// RUN: not %clang_cc1 -pedantic -Wall -Wno-unused-using -Wno-comment -fcxx-exceptions -fixit -x c++ -std=c++98 %t-98
+// RUN: %clang_cc1 -fsyntax-only -pedantic -Wall -Werror -Wno-unused-using -Wno-comment -fcxx-exceptions -x c++ -std=c++98 %t-98
 // RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -x c++ -std=c++11 %s 2>&1 | FileCheck %s
-// RUN: %clang_cc1 -pedantic -Wall -Wno-comment -verify -fcxx-exceptions -x c++ -std=c++11 %s
+// RUN: %clang_cc1 -pedantic -Wall -Wno-unused-using -Wno-comment -verify -fcxx-exceptions -x c++ -std=c++11 %s
 // RUN: cp %s %t-11
-// RUN: not %clang_cc1 -pedantic -Wall -Wno-comment -fcxx-exceptions -fixit -x c++ -std=c++11 %t-11
-// RUN: %clang_cc1 -fsyntax-only -pedantic -Wall -Werror -Wno-comment -fcxx-exceptions -x c++ -std=c++11 %t-11
+// RUN: not %clang_cc1 -pedantic -Wall -Wno-unused-using -Wno-comment -fcxx-exceptions -fixit -x c++ -std=c++11 %t-11
+// RUN: %clang_cc1 -fsyntax-only -pedantic -Wall -Werror -Wno-unused-using -Wno-comment -fcxx-exceptions -x c++ -std=c++11 %t-11
 
 /* This is a test of the various code modification hints that are
    provided as part of warning or extension diagnostics. All of the
Index: lib/Serialization/ASTWriter.cpp
===================================================================
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -1137,6 +1137,7 @@
   RECORD(MSSTRUCT_PRAGMA_OPTIONS);
   RECORD(POINTERS_TO_MEMBERS_PRAGMA_OPTIONS);
   RECORD(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES);
+  RECORD(UNUSED_USING_CANDIDATES);
   RECORD(DELETE_EXPRS_TO_ANALYZE);
   RECORD(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH);
   RECORD(PP_CONDITIONAL_STACK);
@@ -4715,6 +4716,11 @@
   for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates)
     AddDeclRef(TD, UnusedLocalTypedefNameCandidates);
 
+  // Build a record containing all of the UnusedUsingCandidates.
+  RecordData UnusedUsingCandidates;
+  for (const UsingDecl *UD : SemaRef.UnusedUsingCandidates)
+    AddDeclRef(UD, UnusedUsingCandidates);
+
   // Build a record containing all of pending implicit instantiations.
   RecordData PendingInstantiations;
   for (const auto &I : SemaRef.PendingInstantiations) {
@@ -5035,6 +5041,10 @@
     Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES,
                       UnusedLocalTypedefNameCandidates);
 
+  // Write the record containing potentially unused usings.
+  if (!UnusedUsingCandidates.empty())
+    Stream.EmitRecord(UNUSED_USING_CANDIDATES, UnusedUsingCandidates);
+
   // Write the record containing pending implicit instantiations.
   if (!PendingInstantiations.empty())
     Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations);
Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -3447,6 +3447,11 @@
             getGlobalDeclID(F, Record[I]));
       break;
 
+    case UNUSED_USING_CANDIDATES:
+      for (unsigned I = 0, N = Record.size(); I != N; ++I)
+        UnusedUsingCandidates.push_back(getGlobalDeclID(F, Record[I]));
+      break;
+
     case CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH:
       if (Record.size() != 1) {
         Error("invalid cuda pragma options record");
@@ -8090,6 +8095,17 @@
   UnusedLocalTypedefNameCandidates.clear();
 }
 
+void ASTReader::ReadUnusedUsingCandidates(
+    llvm::SmallSetVector<const UsingDecl *, 4> &Decls) {
+  for (unsigned I = 0, N = UnusedUsingCandidates.size(); I != N; ++I) {
+    UsingDecl *D = dyn_cast_or_null<UsingDecl>(
+        GetDecl(UnusedUsingCandidates[I]));
+    if (D)
+      Decls.insert(D);
+  }
+  UnusedUsingCandidates.clear();
+}
+
 void ASTReader::ReadReferencedSelectors(
        SmallVectorImpl<std::pair<Selector, SourceLocation>> &Sels) {
   if (ReferencedSelectorsData.empty())
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -9167,14 +9167,20 @@
     }
   }
 
-  NamedDecl *UD =
+  NamedDecl *ND =
       BuildUsingDeclaration(S, AS, UsingLoc, TypenameLoc.isValid(), TypenameLoc,
                             SS, TargetNameInfo, EllipsisLoc, AttrList,
                             /*IsInstantiation*/false);
-  if (UD)
-    PushOnScopeChains(UD, S, /*AddToContext*/ false);
+  if (ND) {
+    PushOnScopeChains(ND, S, /*AddToContext*/ false);
+    if (auto *UD = dyn_cast<UsingDecl>(ND))
+      // In the case of global usings they can be referenced later on, so the
+      // diagnostics are emitted at end-of-translation-unit.
+      if (!UD->getParentFunctionOrMethod())
+        UnusedUsingCandidates.insert(UD);
+  }
 
-  return UD;
+  return ND;
 }
 
 /// \brief Determine whether a using declaration considers the given
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -1679,6 +1679,9 @@
   if (isa<TypedefNameDecl>(D))
     return true;
 
+  if (isa<UsingShadowDecl>(D))
+    return true;
+
   // White-list anything that isn't a local variable.
   if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D))
     return false;
@@ -1772,6 +1775,16 @@
     return;
   }
 
+  if (auto *USD = dyn_cast<UsingShadowDecl>(D)) {
+    // Check if the using shadow target was used or referenced.
+    const NamedDecl *ND = USD->getTargetDecl();
+    if (!(ND->isUsed() || ND->isReferenced())) {
+      const UsingDecl *UD = USD->getUsingDecl();
+      Diag(UD->getLocation(), diag::warn_unused_using) << UD->getDeclName();
+    }
+    return;
+  }
+
   FixItHint Hint;
   GenerateFixForUnusedDecl(D, Context, Hint);
 
Index: lib/Sema/Sema.cpp
===================================================================
--- lib/Sema/Sema.cpp
+++ lib/Sema/Sema.cpp
@@ -812,6 +812,43 @@
   UnusedLocalTypedefNameCandidates.clear();
 }
 
+// Emit warnings on unused using references.
+void Sema::emitAndClearUnusedUsingWarnings() {
+  if (ExternalSource)
+    ExternalSource->ReadUnusedUsingCandidates(UnusedUsingCandidates);
+  for (const UsingDecl *UD : UnusedUsingCandidates) {
+    // Skip if the using declaration is in a system header.
+    SourceLocation loc = UD->getLocation();
+    // We only care about the expansion location.
+    loc = SourceMgr.getExpansionLoc(loc);
+    FileID file = SourceMgr.getFileID(loc);
+    if (file.isValid()) {
+      // Retrieve file information.
+      bool invalid = false;
+      const SrcMgr::SLocEntry &sloc = SourceMgr.getSLocEntry(file, &invalid);
+      if (!invalid && sloc.isFile()) {
+        const SrcMgr::FileInfo &fileInfo = sloc.getFile();
+        if (SrcMgr::isSystem(fileInfo.getFileCharacteristic()))
+          continue;
+      }
+    }
+    // For the case when a using shadow declaration is being hidden, just
+    // get the location from the declaration itself.
+    //   struct Base { void foo(int); };
+    //   struct Derived : Base {
+    //     using Base::foo;
+    //     void foo(int);
+    //   };
+    // Check if the referenced definition has been used or referenced.
+    const NamedDecl *ND = (UD->shadow_size() > 0)
+                        ? UD->shadow_begin()->getTargetDecl() : UD;
+    if (ND->isUsed() || ND->isReferenced())
+      continue;
+    Diag(UD->getLocation(), diag::warn_unused_using) << UD->getDeclName();
+  }
+  UnusedUsingCandidates.clear();
+}
+
 /// This is called before the very first declaration in the translation unit
 /// is parsed. Note that the ASTContext may have already injected some
 /// declarations.
@@ -981,6 +1018,7 @@
     // Warnings emitted in ActOnEndOfTranslationUnit() should be emitted for
     // modules when they are built, not every time they are used.
     emitAndClearUnusedLocalTypedefWarnings();
+    emitAndClearUnusedUsingWarnings();
 
     // Modules don't need any of the checking below.
     if (!PP.isIncrementalProcessingEnabled())
@@ -1101,6 +1139,7 @@
     }
 
     emitAndClearUnusedLocalTypedefWarnings();
+    emitAndClearUnusedUsingWarnings();
   }
 
   if (!Diags.isIgnored(diag::warn_unused_private_field, SourceLocation())) {
Index: lib/Sema/MultiplexExternalSemaSource.cpp
===================================================================
--- lib/Sema/MultiplexExternalSemaSource.cpp
+++ lib/Sema/MultiplexExternalSemaSource.cpp
@@ -273,6 +273,12 @@
     Sources[i]->ReadUnusedLocalTypedefNameCandidates(Decls);
 }
 
+void MultiplexExternalSemaSource::ReadUnusedUsingCandidates(
+    llvm::SmallSetVector<const UsingDecl*, 4> &Decls) {
+  for(size_t i = 0; i < Sources.size(); ++i)
+    Sources[i]->ReadUnusedUsingCandidates(Decls);
+}
+
 void MultiplexExternalSemaSource::ReadReferencedSelectors(
                   SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) {
   for(size_t i = 0; i < Sources.size(); ++i)
Index: include/clang/Serialization/ASTReader.h
===================================================================
--- include/clang/Serialization/ASTReader.h
+++ include/clang/Serialization/ASTReader.h
@@ -828,6 +828,11 @@
   /// Sema tracks these to emit warnings.
   SmallVector<uint64_t, 16> UnusedLocalTypedefNameCandidates;
 
+  /// \brief The IDs of all potentially unused using names in the chain.
+  ///
+  /// Sema tracks these to emit warnings.
+  SmallVector<uint64_t, 16> UnusedUsingCandidates;
+
   /// \brief Our current depth in #pragma cuda force_host_device begin/end
   /// macros.
   unsigned ForceCUDAHostDeviceDepth = 0;
@@ -1987,6 +1992,9 @@
   void ReadUnusedLocalTypedefNameCandidates(
       llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) override;
 
+  void ReadUnusedUsingCandidates(
+      llvm::SmallSetVector<const UsingDecl *, 4> &Decls) override;
+
   void ReadReferencedSelectors(
            SmallVectorImpl<std::pair<Selector, SourceLocation>> &Sels) override;
 
Index: include/clang/Serialization/ASTBitCodes.h
===================================================================
--- include/clang/Serialization/ASTBitCodes.h
+++ include/clang/Serialization/ASTBitCodes.h
@@ -648,7 +648,10 @@
       PP_CONDITIONAL_STACK = 62,
 
       /// \brief A table of skipped ranges within the preprocessing record.
-      PPD_SKIPPED_RANGES = 63
+      PPD_SKIPPED_RANGES = 63,
+
+      /// \brief Record code for potentially unused usings.
+      UNUSED_USING_CANDIDATES = 64
     };
 
     /// \brief Record types used within a source manager block.
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -555,6 +555,9 @@
   llvm::SmallSetVector<const TypedefNameDecl *, 4>
       UnusedLocalTypedefNameCandidates;
 
+  /// \brief Set containing all usings that are likely unused.
+  llvm::SmallSetVector<const UsingDecl*, 4> UnusedUsingCandidates;
+
   /// \brief Delete-expressions to be analyzed at the end of translation unit
   ///
   /// This list contains class members, and locations of delete-expressions
@@ -1290,6 +1293,7 @@
   ModuleLoader &getModuleLoader() const;
 
   void emitAndClearUnusedLocalTypedefWarnings();
+  void emitAndClearUnusedUsingWarnings();
 
   void ActOnStartOfTranslationUnit();
   void ActOnEndOfTranslationUnit();
Index: include/clang/Sema/MultiplexExternalSemaSource.h
===================================================================
--- include/clang/Sema/MultiplexExternalSemaSource.h
+++ include/clang/Sema/MultiplexExternalSemaSource.h
@@ -282,6 +282,15 @@
   void ReadUnusedLocalTypedefNameCandidates(
       llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) override;
 
+  /// \brief Read the set of potentially unused usings known to the source.
+  ///
+  /// The external source should append its own potentially unused usings
+  /// to the given vector of declarations. Note that this routine may be
+  /// invoked multiple times; the external source should take care not to
+  /// introduce the same declarations repeatedly.
+  void ReadUnusedUsingCandidates(
+      llvm::SmallSetVector<const UsingDecl*, 4> &Decls) override;
+
   /// \brief Read the set of referenced selectors known to the
   /// external Sema source.
   ///
Index: include/clang/Sema/ExternalSemaSource.h
===================================================================
--- include/clang/Sema/ExternalSemaSource.h
+++ include/clang/Sema/ExternalSemaSource.h
@@ -35,6 +35,7 @@
 class Scope;
 class Sema;
 class TypedefNameDecl;
+class UsingDecl;
 class ValueDecl;
 class VarDecl;
 struct LateParsedTemplate;
@@ -145,6 +146,15 @@
   virtual void ReadUnusedLocalTypedefNameCandidates(
       llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) {}
 
+  /// \brief Read the set of potentially unused usings known to the source.
+  ///
+  /// The external source should append its own potentially unused usings
+  /// to the given vector of declarations. Note that this routine may be
+  /// invoked multiple times; the external source should take care not to
+  /// introduce the same declarations repeatedly.
+  virtual void ReadUnusedUsingCandidates(
+      llvm::SmallSetVector<const UsingDecl*, 4> &Decls) {}
+
   /// \brief Read the set of referenced selectors known to the
   /// external Sema source.
   ///
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -279,6 +279,8 @@
 def warn_unused_local_typedef : Warning<
   "unused %select{typedef|type alias}0 %1">,
   InGroup<UnusedLocalTypedef>, DefaultIgnore;
+def warn_unused_using : Warning<"unused using %0">,
+  InGroup<UnusedUsing>, DefaultIgnore;
 def warn_unused_property_backing_ivar : 
   Warning<"ivar %0 which backs the property is not "
   "referenced in this property's accessor">,
Index: include/clang/Basic/DiagnosticGroups.td
===================================================================
--- include/clang/Basic/DiagnosticGroups.td
+++ include/clang/Basic/DiagnosticGroups.td
@@ -568,6 +568,7 @@
 def UnusedVariable : DiagGroup<"unused-variable",
                                [UnusedConstVariable]>;
 def UnusedLocalTypedef : DiagGroup<"unused-local-typedef">;
+def UnusedUsing : DiagGroup<"unused-using">;
 def UnusedPropertyIvar :  DiagGroup<"unused-property-ivar">;
 def UnusedGetterReturnValue : DiagGroup<"unused-getter-return-value">;
 def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">;
@@ -698,6 +699,7 @@
                         // UnusedMemberFunction, (clean-up llvm before enabling)
                         UnusedPrivateField, UnusedLambdaCapture,
                         UnusedLocalTypedef, UnusedValue, UnusedVariable,
+                        UnusedUsing,
                         UnusedPropertyIvar]>,
                         DiagCategory<"Unused Entity Issue">;
 
@@ -813,6 +815,8 @@
                 [VectorConversion]>; // -Wvector-conversions = -Wvector-conversion
 def : DiagGroup<"unused-local-typedefs", [UnusedLocalTypedef]>;
                 // -Wunused-local-typedefs = -Wunused-local-typedef
+def : DiagGroup<"unused-usings", [UnusedUsing]>;
+                // -Wunused-usings = -Wunused-using
 
 // A warning group for warnings that we want to have on by default in clang,
 // but which aren't on by default in GCC.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to