CarlosAlbertoEnciso updated this revision to Diff 148578.
CarlosAlbertoEnciso edited the summary of this revision.
CarlosAlbertoEnciso added a comment.
This patch addresses the reviewers comments:
1. Merge the -Wunused-local-typedefs and -Wunused-usings implementations
2. Update the Release Notes
3. Review the test cases
https://reviews.llvm.org/D44826
Files:
docs/ReleaseNotes.rst
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/Sema/SemaInternal.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/PCH/cxx-templates.cpp
test/SemaCXX/coreturn.cpp
test/SemaCXX/referenced_alias_declaration_1.cpp
test/SemaCXX/referenced_alias_declaration_2.cpp
test/SemaCXX/referenced_using_all.cpp
test/SemaCXX/referenced_using_declaration_1.cpp
test/SemaCXX/referenced_using_declaration_2.cpp
test/SemaCXX/referenced_using_directive.cpp
Index: test/SemaCXX/referenced_using_directive.cpp
===================================================================
--- test/SemaCXX/referenced_using_directive.cpp
+++ test/SemaCXX/referenced_using_directive.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wunused-using -verify %s
+
+namespace N {
+ typedef int Integer;
+ int var;
+}
+
+void Fa() {
+ using namespace N; // Referenced
+ var = 1;
+}
+
+void Fb() {
+ using namespace N; // expected-warning {{unused using '<using-directive>'}}
+ N::var = 1;
+}
+
+void Fc() {
+ using namespace N; // Referenced
+ Integer var = 1;
+}
+
+void Fd() {
+ using namespace N; // expected-warning {{unused using '<using-directive>'}}
+ N::Integer var = 1;
+}
Index: test/SemaCXX/referenced_using_declaration_2.cpp
===================================================================
--- test/SemaCXX/referenced_using_declaration_2.cpp
+++ test/SemaCXX/referenced_using_declaration_2.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wunused-using -verify %s
+
+namespace N {
+ typedef int Integer;
+ typedef char Char;
+}
+
+using N::Integer; // expected-warning {{unused using 'Integer'}}
+using N::Char; // Referenced
+
+void Foo(int p1, N::Integer p2, Char p3) {
+ N::Integer var;
+ var = 0;
+}
+
+using N::Integer; // Referenced
+Integer Bar() {
+ using N::Char; // expected-warning {{unused using 'Char'}}
+ return 0;
+}
Index: test/SemaCXX/referenced_using_declaration_1.cpp
===================================================================
--- test/SemaCXX/referenced_using_declaration_1.cpp
+++ test/SemaCXX/referenced_using_declaration_1.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wunused-using -verify %s
+
+namespace N {
+ // Types.
+ typedef int Integer;
+ struct Record {
+ int a;
+ };
+
+ // Variables.
+ int var1;
+ int var2;
+
+ // Functions.
+ void func1();
+ void func2();
+}
+
+using N::Integer; // expected-warning {{unused using 'Integer'}}
+using N::Record; // expected-warning {{unused using 'Record'}}
+using N::var1; // expected-warning {{unused using 'var1'}}
+using N::var2; // expected-warning {{unused using 'var2'}}
+using N::func1; // expected-warning {{unused using 'func1'}}
+using N::func2; // expected-warning {{unused using 'func2'}}
+
+void Foo() {
+ using N::Integer; // expected-warning {{unused using 'Integer'}}
+ N::Integer int_var;
+ int_var = 1;
+
+ using N::Record; // Referenced
+ Record rec_var;
+ rec_var.a = 2;
+
+ using N::var1; // expected-warning {{unused using 'var1'}}
+ N::var1 = 3;
+
+ using N::var2; // Referenced
+ var2 = 4;
+
+ using N::func1; // expected-warning {{unused using 'func1'}}
+ N::func1();
+
+ using N::func2; // Referenced
+ func2();
+}
Index: test/SemaCXX/referenced_using_all.cpp
===================================================================
--- test/SemaCXX/referenced_using_all.cpp
+++ test/SemaCXX/referenced_using_all.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wunused-using -verify %s
+
+namespace A {
+ typedef char Char;
+ typedef int Integer;
+ typedef float Float;
+ int var;
+}
+
+using A::Char; // expected-warning {{unused using 'Char'}}
+using A::Integer; // Referenced
+using A::Float; // expected-warning {{unused using 'Float'}}
+
+namespace B {
+ using A::Char; // Referenced
+ template <class T>
+ T FuncTempl(T p1,Char p2) {
+ using A::Float; // Referenced
+ typedef Float Type;
+ Integer I;
+ return p1;
+ }
+}
+
+using A::Char; // Referenced
+using A::Integer; // expected-warning {{unused using 'Integer'}}
+namespace ND1 = A;
+void foo() {
+ using A::Integer; // Referenced
+ namespace ND2 = ND1; // Referenced
+ {
+ Integer Ivar;
+ namespace ND3 = ND2; // Referenced
+ {
+ namespace ND4 = ND3; // Referenced
+ Char Cvar;
+ {
+ using ND4::var; // Referenced
+ var = 1;
+ }
+ }
+ }
+ using A::Char; // Referenced
+ using namespace::B; // Referenced
+ FuncTempl<Char>(1,'a');
+}
Index: test/SemaCXX/referenced_alias_declaration_2.cpp
===================================================================
--- test/SemaCXX/referenced_alias_declaration_2.cpp
+++ test/SemaCXX/referenced_alias_declaration_2.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wunused-using -verify %s
+
+namespace A {
+ namespace B {
+ namespace C {
+ typedef int Integer;
+ }
+ }
+}
+
+void foo() {
+ {
+ namespace N_A = A; // Referenced
+ {
+ namespace N_AB = N_A::B; // Referenced
+ {
+ namespace N_ABC = N_AB::C; // Referenced
+ {
+ using N_ABC::Integer; // Referenced
+ Integer var;
+ }
+ }
+ }
+ }
+ {
+ namespace N_A = A; // expected-warning {{unused using 'N_A'}}
+ {
+ namespace N_AB = N_A::B; // expected-warning {{unused using 'N_AB'}}
+ {
+ namespace N_ABC = N_AB::C; // expected-warning {{unused using 'N_ABC'}}
+ {
+ A::B::C::Integer var;
+ }
+ }
+ }
+ }
+}
Index: test/SemaCXX/referenced_alias_declaration_1.cpp
===================================================================
--- test/SemaCXX/referenced_alias_declaration_1.cpp
+++ test/SemaCXX/referenced_alias_declaration_1.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wunused-using -verify %s
+
+namespace N {
+ int var;
+}
+
+void Fa() {
+ namespace NN = N; // Referenced
+ using namespace NN; // Referenced
+ var = 1;
+}
+
+void Fb() {
+ namespace NA = N; // Referenced
+ namespace NB = NA; // Referenced
+ namespace NC = NB; // Referenced
+ using namespace NC; // Referenced
+ var = 2;
+ namespace ND = NC; // expected-warning {{unused using 'ND'}}
+}
+
+void Fc() {
+ namespace NA = N; // expected-warning {{unused using 'NA'}}
+ using namespace NA; // expected-warning {{unused using '<using-directive>'}}
+ N::var = 3;
+}
+
+void Fd() {
+ namespace NA = N; // Referenced
+ namespace NB = NA; // Referenced
+ NB::var = 4;
+}
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/PCH/cxx-templates.cpp
===================================================================
--- test/PCH/cxx-templates.cpp
+++ test/PCH/cxx-templates.cpp
@@ -5,12 +5,12 @@
// Test with pch.
// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -x c++-header -emit-pch -o %t %S/cxx-templates.h
// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -include-pch %t -verify %s -ast-dump -o -
-// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -include-pch %t %s -emit-llvm -o - -error-on-deserialized-decl doNotDeserialize -DNO_ERRORS | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -include-pch %t %s -emit-llvm -o - -DNO_ERRORS | FileCheck %s
// Test with modules.
// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -fmodules -x c++-header -emit-pch -o %t %S/cxx-templates.h
// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -fmodules -include-pch %t -verify %s -ast-dump -o -
-// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -fmodules -include-pch %t %s -emit-llvm -o - -error-on-deserialized-decl doNotDeserialize -DNO_ERRORS -fmodules-ignore-macro=NO_ERRORS | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -fmodules -include-pch %t %s -emit-llvm -o - -DNO_ERRORS -fmodules-ignore-macro=NO_ERRORS | FileCheck %s
// Test with pch and delayed template parsing.
// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fdelayed-template-parsing -fexceptions -x c++-header -emit-pch -o %t %S/cxx-templates.h
Index: test/Modules/warn-unused-using.cpp
===================================================================
--- test/Modules/warn-unused-using.cpp
+++ test/Modules/warn-unused-using.cpp
@@ -0,0 +1,11 @@
+// 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 'CHAR'
+// CHECK_1: warning: unused using 'INT'
+// CHECK_2-NOT: warning: unused using 'CHAR'
+// 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,10 @@
+namespace A {
+ typedef char CHAR;
+}
+namespace B {
+ typedef int INT;
+ using A::CHAR;
+}
+inline void foo() {
+ using B::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,7 +1137,7 @@
RECORD(OPTIMIZE_PRAGMA_OPTIONS);
RECORD(MSSTRUCT_PRAGMA_OPTIONS);
RECORD(POINTERS_TO_MEMBERS_PRAGMA_OPTIONS);
- RECORD(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES);
+ RECORD(UNUSED_NAMED_DECL_CANDIDATES);
RECORD(DELETE_EXPRS_TO_ANALYZE);
RECORD(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH);
RECORD(PP_CONDITIONAL_STACK);
@@ -4714,10 +4714,10 @@
}
}
- // Build a record containing all of the UnusedLocalTypedefNameCandidates.
- RecordData UnusedLocalTypedefNameCandidates;
- for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates)
- AddDeclRef(TD, UnusedLocalTypedefNameCandidates);
+ // Build a record containing all of the UnusedNameCandidates.
+ RecordData UnusedNamedDeclCandidates;
+ for (const NamedDecl *ND : SemaRef.UnusedNamedDeclCandidates)
+ AddDeclRef(ND, UnusedNamedDeclCandidates);
// Build a record containing all of pending implicit instantiations.
RecordData PendingInstantiations;
@@ -5035,9 +5035,9 @@
Stream.EmitRecord(VTABLE_USES, VTableUses);
// Write the record containing potentially unused local typedefs.
- if (!UnusedLocalTypedefNameCandidates.empty())
- Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES,
- UnusedLocalTypedefNameCandidates);
+ if (!UnusedNamedDeclCandidates.empty())
+ Stream.EmitRecord(UNUSED_NAMED_DECL_CANDIDATES,
+ UnusedNamedDeclCandidates);
// Write the record containing pending implicit instantiations.
if (!PendingInstantiations.empty())
Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -3442,10 +3442,9 @@
PointersToMembersPragmaLocation = ReadSourceLocation(F, Record[1]);
break;
- case UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES:
+ case UNUSED_NAMED_DECL_CANDIDATES:
for (unsigned I = 0, N = Record.size(); I != N; ++I)
- UnusedLocalTypedefNameCandidates.push_back(
- getGlobalDeclID(F, Record[I]));
+ UnusedNamedDeclCandidates.push_back(getGlobalDeclID(F, Record[I]));
break;
case CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH:
@@ -8088,16 +8087,15 @@
ExtVectorDecls.clear();
}
-void ASTReader::ReadUnusedLocalTypedefNameCandidates(
- llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) {
- for (unsigned I = 0, N = UnusedLocalTypedefNameCandidates.size(); I != N;
+void ASTReader::ReadUnusedNamedDeclCandidates(
+ llvm::SmallSetVector<const NamedDecl *, 4> &Decls) {
+ for (unsigned I = 0, N = UnusedNamedDeclCandidates.size(); I != N;
++I) {
- TypedefNameDecl *D = dyn_cast_or_null<TypedefNameDecl>(
- GetDecl(UnusedLocalTypedefNameCandidates[I]));
- if (D)
- Decls.insert(D);
+ if (auto *ND = dyn_cast_or_null<NamedDecl>(
+ GetDecl(UnusedNamedDeclCandidates[I])))
+ Decls.insert(ND);
}
- UnusedLocalTypedefNameCandidates.clear();
+ UnusedNamedDeclCandidates.clear();
}
void ASTReader::ReadReferencedSelectors(
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -9310,8 +9310,10 @@
Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
}
- if (UDir)
+ if (UDir) {
ProcessDeclAttributeList(S, UDir, AttrList);
+ UnusedNamedDeclCandidates.insert(UDir);
+ }
return UDir;
}
@@ -9410,8 +9412,11 @@
BuildUsingDeclaration(S, AS, UsingLoc, TypenameLoc.isValid(), TypenameLoc,
SS, TargetNameInfo, EllipsisLoc, AttrList,
/*IsInstantiation*/false);
- if (UD)
+ if (UD) {
PushOnScopeChains(UD, S, /*AddToContext*/ false);
+ if (isa<UsingDecl>(UD))
+ UnusedNamedDeclCandidates.insert(UD);
+ }
return UD;
}
@@ -10587,6 +10592,10 @@
AliasDecl->setPreviousDecl(Prev);
PushOnScopeChains(AliasDecl, S);
+
+ if (AliasDecl)
+ UnusedNamedDeclCandidates.insert(AliasDecl);
+
return AliasDecl;
}
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -1673,7 +1673,7 @@
if (!WithinFunction)
return false;
- if (isa<TypedefNameDecl>(D))
+ if (isa<TypedefNameDecl>(D) || DeclAccessNamespace(D))
return true;
// White-list anything that isn't a local variable.
@@ -1762,10 +1762,10 @@
if (!ShouldDiagnoseUnusedDecl(D))
return;
- if (auto *TD = dyn_cast<TypedefNameDecl>(D)) {
- // typedefs can be referenced later on, so the diagnostics are emitted
- // at end-of-translation-unit.
- UnusedLocalTypedefNameCandidates.insert(TD);
+ if (isa<TypedefNameDecl>(D) || DeclAccessNamespace(D)) {
+ // typedefs and usings can be referenced later on, so the diagnostics are
+ // emitted at end-of-translation-unit.
+ UnusedNamedDeclCandidates.insert(D);
return;
}
Index: lib/Sema/Sema.cpp
===================================================================
--- lib/Sema/Sema.cpp
+++ lib/Sema/Sema.cpp
@@ -807,17 +807,20 @@
return Complete;
}
-void Sema::emitAndClearUnusedLocalTypedefWarnings() {
+void Sema::emitAndClearUnusedNamedDeclWarnings() {
if (ExternalSource)
- ExternalSource->ReadUnusedLocalTypedefNameCandidates(
- UnusedLocalTypedefNameCandidates);
- for (const TypedefNameDecl *TD : UnusedLocalTypedefNameCandidates) {
- if (TD->isReferenced())
+ ExternalSource->ReadUnusedNamedDeclCandidates(
+ UnusedNamedDeclCandidates);
+ for (const NamedDecl *ND : UnusedNamedDeclCandidates) {
+ if (ND->isReferenced())
continue;
- Diag(TD->getLocation(), diag::warn_unused_local_typedef)
- << isa<TypeAliasDecl>(TD) << TD->getDeclName();
+ if (isa<TypedefNameDecl>(ND))
+ Diag(ND->getLocation(), diag::warn_unused_local_typedef)
+ << isa<TypeAliasDecl>(ND) << ND->getDeclName();
+ else
+ Diag(ND->getLocation(), diag::warn_unused_using) << ND->getDeclName();
}
- UnusedLocalTypedefNameCandidates.clear();
+ UnusedNamedDeclCandidates.clear();
}
/// This is called before the very first declaration in the translation unit
@@ -1007,7 +1010,7 @@
// Warnings emitted in ActOnEndOfTranslationUnit() should be emitted for
// modules when they are built, not every time they are used.
- emitAndClearUnusedLocalTypedefWarnings();
+ emitAndClearUnusedNamedDeclWarnings();
// Modules don't need any of the checking below.
if (!PP.isIncrementalProcessingEnabled())
@@ -1127,7 +1130,7 @@
}
}
- emitAndClearUnusedLocalTypedefWarnings();
+ emitAndClearUnusedNamedDeclWarnings();
}
if (!Diags.isIgnored(diag::warn_unused_private_field, SourceLocation())) {
Index: lib/Sema/MultiplexExternalSemaSource.cpp
===================================================================
--- lib/Sema/MultiplexExternalSemaSource.cpp
+++ lib/Sema/MultiplexExternalSemaSource.cpp
@@ -267,10 +267,10 @@
Sources[i]->ReadExtVectorDecls(Decls);
}
-void MultiplexExternalSemaSource::ReadUnusedLocalTypedefNameCandidates(
- llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) {
+void MultiplexExternalSemaSource::ReadUnusedNamedDeclCandidates(
+ llvm::SmallSetVector<const NamedDecl *, 4> &Decls) {
for(size_t i = 0; i < Sources.size(); ++i)
- Sources[i]->ReadUnusedLocalTypedefNameCandidates(Decls);
+ Sources[i]->ReadUnusedNamedDeclCandidates(Decls);
}
void MultiplexExternalSemaSource::ReadReferencedSelectors(
Index: include/clang/Serialization/ASTReader.h
===================================================================
--- include/clang/Serialization/ASTReader.h
+++ include/clang/Serialization/ASTReader.h
@@ -823,10 +823,10 @@
/// Fields containing data that is used for semantic analysis
//@{
- /// The IDs of all potentially unused typedef names in the chain.
+ /// The IDs of all potentially unused typedef and using names in the chain.
///
/// Sema tracks these to emit warnings.
- SmallVector<uint64_t, 16> UnusedLocalTypedefNameCandidates;
+ SmallVector<uint64_t, 16> UnusedNamedDeclCandidates;
/// Our current depth in #pragma cuda force_host_device begin/end
/// macros.
@@ -1989,8 +1989,8 @@
void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) override;
- void ReadUnusedLocalTypedefNameCandidates(
- llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) override;
+ void ReadUnusedNamedDeclCandidates(
+ llvm::SmallSetVector<const NamedDecl *, 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
@@ -615,8 +615,8 @@
/// Record code for \#pragma optimize options.
OPTIMIZE_PRAGMA_OPTIONS = 51,
- /// Record code for potentially unused local typedef names.
- UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES = 52,
+ /// Record code for potentially unused local typedef and using names.
+ UNUSED_NAMED_DECL_CANDIDATES = 52,
// ID 53 used to be a table of constructor initializer records.
Index: include/clang/Sema/SemaInternal.h
===================================================================
--- include/clang/Sema/SemaInternal.h
+++ include/clang/Sema/SemaInternal.h
@@ -60,6 +60,14 @@
return isDeviceSideDecl == LangOpts.CUDAIsDevice;
}
+// Helper function to check whether D is associated with namespace via one of
+// the variations: using-declaration, using-directive, alias-declaration.
+inline bool DeclAccessNamespace(const Decl *D) {
+ return isa<UsingDecl>(D) ||
+ isa<UsingDirectiveDecl>(D) ||
+ isa<NamespaceAliasDecl>(D);
+}
+
// Directly mark a variable odr-used. Given a choice, prefer to use
// MarkVariableReferenced since it does additional checks and then
// calls MarkVarDeclODRUsed.
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -553,9 +553,9 @@
/// Set containing all declared private fields that are not used.
NamedDeclSetType UnusedPrivateFields;
- /// Set containing all typedefs that are likely unused.
- llvm::SmallSetVector<const TypedefNameDecl *, 4>
- UnusedLocalTypedefNameCandidates;
+ /// Set containing all typedefs and usings that are likely unused.
+ llvm::SmallSetVector<const NamedDecl *, 4>
+ UnusedNamedDeclCandidates;
/// Delete-expressions to be analyzed at the end of translation unit
///
@@ -1291,7 +1291,7 @@
/// Retrieve the module loader associated with the preprocessor.
ModuleLoader &getModuleLoader() const;
- void emitAndClearUnusedLocalTypedefWarnings();
+ void emitAndClearUnusedNamedDeclWarnings();
void ActOnStartOfTranslationUnit();
void ActOnEndOfTranslationUnit();
Index: include/clang/Sema/MultiplexExternalSemaSource.h
===================================================================
--- include/clang/Sema/MultiplexExternalSemaSource.h
+++ include/clang/Sema/MultiplexExternalSemaSource.h
@@ -273,14 +273,15 @@
/// introduce the same declarations repeatedly.
void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl*> &Decls) override;
- /// Read the set of potentially unused typedefs known to the source.
+ /// Read the set of potentially unused typedefs and usings known to the
+ /// source.
///
/// The external source should append its own potentially unused local
/// typedefs 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 ReadUnusedLocalTypedefNameCandidates(
- llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) override;
+ void ReadUnusedNamedDeclCandidates(
+ llvm::SmallSetVector<const NamedDecl *, 4> &Decls) override;
/// 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
@@ -136,14 +136,15 @@
/// introduce the same declarations repeatedly.
virtual void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) {}
- /// Read the set of potentially unused typedefs known to the source.
+ /// Read the set of potentially unused typedefs and usings known to the
+ /// source.
///
/// The external source should append its own potentially unused local
/// typedefs 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 ReadUnusedLocalTypedefNameCandidates(
- llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) {}
+ virtual void ReadUnusedNamedDeclCandidates(
+ llvm::SmallSetVector<const NamedDecl *, 4> &Decls) {}
/// 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,9 @@
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
@@ -573,6 +573,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">;
@@ -703,6 +704,7 @@
// UnusedMemberFunction, (clean-up llvm before enabling)
UnusedPrivateField, UnusedLambdaCapture,
UnusedLocalTypedef, UnusedValue, UnusedVariable,
+ UnusedUsing,
UnusedPropertyIvar]>,
DiagCategory<"Unused Entity Issue">;
@@ -823,6 +825,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.
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -112,6 +112,34 @@
'no-strict' option, Clang attempts to match the overflowing behavior of the
target's native float-to-int conversion instructions.
+- :option:`-Wunused-using`.
+
+ -Wall now includes the new warning flag `-Wunused-using`, which emits a
+ warning on using statements that are not used. This may result in new
+ warnings in code that compiled cleanly with previous versions.
+
+ Example:
+
+ .. code-block:: c++
+
+ namespace n { class C; }
+ using n::C; // Never actually used.
+
+ Gives the following warning:
+
+ ::
+
+ ./test.cpp:2:10: warning: unused using 'C' [-Wunused-using]
+ using n::C;
+ ^
+ 1 warning generated.
+
+ The warnings will not result in compilation failure, unless `-Wall` is
+ used in conjunction with `-Werror` and as a result, the new warnings
+ are turned into new errors.
+
+ To fix, simply remove the unused using statement or use `-Wno-unused-using`.
+
- ...
Deprecated Compiler Flags
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits