Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -112,6 +112,45 @@ '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; + + namespace a = n; + + using namespace n; + using namespace a; + + Gives the following warnings: + + :: + + ./test.cpp:3:10: warning: unused using declaration 'C' [-Wunused-using] + using n::C; + ^ + ./test.cpp:5:11: warning: unused namespace alias 'a' [-Wunused-using] + namespace a = n; + ^ + ./test.cpp:7:17: warning: unused using directive 'n' [-Wunused-using] + using namespace n; + ^ + ./test.cpp:8:17: warning: unused using directive 'a' [-Wunused-using] + using namespace a; + ^ + 4 warnings generated. + + To fix, simply remove the unused using statement or use ``-Wno-unused-using``. + - ... Deprecated Compiler Flags Index: include/clang/Basic/DiagnosticGroups.td =================================================================== --- include/clang/Basic/DiagnosticGroups.td +++ include/clang/Basic/DiagnosticGroups.td @@ -575,6 +575,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">; @@ -705,6 +706,7 @@ // UnusedMemberFunction, (clean-up llvm before enabling) UnusedPrivateField, UnusedLambdaCapture, UnusedLocalTypedef, UnusedValue, UnusedVariable, + UnusedUsing, UnusedPropertyIvar]>, DiagCategory<"Unused Entity Issue">; Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -279,6 +279,15 @@ def warn_unused_local_typedef : Warning< "unused %select{typedef|type alias}0 %1">, InGroup, DefaultIgnore; +def warn_unused_using_declaration : Warning< + "unused using declaration %0">, + InGroup, DefaultIgnore; +def warn_unused_using_directive : Warning< + "unused using directive %0">, + InGroup, DefaultIgnore; +def warn_unused_using_alias : Warning< + "unused namespace alias %0">, + InGroup, 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/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 &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 &Decls) {} + virtual void ReadUnusedNamedDeclCandidates( + llvm::SmallSetVector &Decls) {} /// Read the set of referenced selectors known to the /// external Sema source. 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 &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 &Decls) override; + void ReadUnusedNamedDeclCandidates( + llvm::SmallSetVector &Decls) override; /// Read the set of referenced selectors known to the /// external Sema source. 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 - UnusedLocalTypedefNameCandidates; + /// Set containing all typedefs and usings that are likely unused. + llvm::SmallSetVector + 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/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(D) || + isa(D) || + isa(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/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/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 UnusedLocalTypedefNameCandidates; + SmallVector UnusedNamedDeclCandidates; /// Our current depth in #pragma cuda force_host_device begin/end /// macros. @@ -1989,8 +1989,8 @@ void ReadExtVectorDecls(SmallVectorImpl &Decls) override; - void ReadUnusedLocalTypedefNameCandidates( - llvm::SmallSetVector &Decls) override; + void ReadUnusedNamedDeclCandidates( + llvm::SmallSetVector &Decls) override; void ReadReferencedSelectors( SmallVectorImpl> &Sels) override; 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 &Decls) { +void MultiplexExternalSemaSource::ReadUnusedNamedDeclCandidates( + llvm::SmallSetVector &Decls) { for(size_t i = 0; i < Sources.size(); ++i) - Sources[i]->ReadUnusedLocalTypedefNameCandidates(Decls); + Sources[i]->ReadUnusedNamedDeclCandidates(Decls); } void MultiplexExternalSemaSource::ReadReferencedSelectors( Index: lib/Sema/Sema.cpp =================================================================== --- lib/Sema/Sema.cpp +++ lib/Sema/Sema.cpp @@ -807,17 +807,28 @@ 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(TD) << TD->getDeclName(); + if (isa(ND)) + Diag(ND->getLocation(), diag::warn_unused_local_typedef) + << isa(ND) << ND->getDeclName(); + else if (isa(ND)) + Diag(ND->getLocation(), diag::warn_unused_using_declaration) + << ND->getDeclName(); + else if (isa(ND)) { + auto *UD = dyn_cast(ND); + Diag(ND->getLocation(), diag::warn_unused_using_directive) + << UD->getNominatedNamespaceAsWritten()->getDeclName(); + } else + Diag(ND->getLocation(), diag::warn_unused_using_alias) + << ND->getDeclName(); } - UnusedLocalTypedefNameCandidates.clear(); + UnusedNamedDeclCandidates.clear(); } /// This is called before the very first declaration in the translation unit @@ -1007,7 +1018,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 +1138,7 @@ } } - emitAndClearUnusedLocalTypedefWarnings(); + emitAndClearUnusedNamedDeclWarnings(); } if (!Diags.isIgnored(diag::warn_unused_private_field, SourceLocation())) { Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -1673,7 +1673,7 @@ if (!WithinFunction) return false; - if (isa(D)) + if (isa(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(D)) { - // typedefs can be referenced later on, so the diagnostics are emitted - // at end-of-translation-unit. - UnusedLocalTypedefNameCandidates.insert(TD); + if (isa(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/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -9334,8 +9334,10 @@ Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange(); } - if (UDir) + if (UDir) { ProcessDeclAttributeList(S, UDir, AttrList); + UnusedNamedDeclCandidates.insert(UDir); + } return UDir; } @@ -9434,8 +9436,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(UD)) + UnusedNamedDeclCandidates.insert(UD); + } return UD; } @@ -10611,6 +10616,10 @@ AliasDecl->setPreviousDecl(Prev); PushOnScopeChains(AliasDecl, S); + + if (AliasDecl) + UnusedNamedDeclCandidates.insert(AliasDecl); + return AliasDecl; } 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 &Decls) { - for (unsigned I = 0, N = UnusedLocalTypedefNameCandidates.size(); I != N; +void ASTReader::ReadUnusedNamedDeclCandidates( + llvm::SmallSetVector &Decls) { + for (unsigned I = 0, N = UnusedNamedDeclCandidates.size(); I != N; ++I) { - TypedefNameDecl *D = dyn_cast_or_null( - GetDecl(UnusedLocalTypedefNameCandidates[I])); - if (D) - Decls.insert(D); + if (auto *ND = dyn_cast_or_null( + GetDecl(UnusedNamedDeclCandidates[I]))) + Decls.insert(ND); } - UnusedLocalTypedefNameCandidates.clear(); + UnusedNamedDeclCandidates.clear(); } void ASTReader::ReadReferencedSelectors( 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: 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: 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/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/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 declaration 'CHAR' +// CHECK_1: warning: unused using declaration 'INT' +// CHECK_2-NOT: warning: unused using declaration 'CHAR' +// CHECK_2-NOT: warning: unused using declaration 'INT' +@import warn_unused_using; 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/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 declaration 'suspend_never'}} struct awaitable { bool await_ready(); 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,33 @@ +// 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 namespace alias 'ND'}} +} + +void Fc() { + namespace NA = N; // expected-warning {{unused namespace alias 'NA'}} + using namespace NA; // expected-warning {{unused using directive 'NA'}} + N::var = 3; +} + +void Fd() { + namespace NA = N; // Referenced + namespace NB = NA; // Referenced + NB::var = 4; +} + 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,38 @@ +// 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 namespace alias 'N_A'}} + { + namespace N_AB = N_A::B; // expected-warning {{unused namespace alias 'N_AB'}} + { + namespace N_ABC = N_AB::C; // expected-warning {{unused namespace alias 'N_ABC'}} + { + A::B::C::Integer var; + } + } + } + } +} + Index: test/SemaCXX/referenced_using_all.cpp =================================================================== --- test/SemaCXX/referenced_using_all.cpp +++ test/SemaCXX/referenced_using_all.cpp @@ -0,0 +1,47 @@ +// 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 declaration 'Char'}} +using A::Integer; // Referenced +using A::Float; // expected-warning {{unused using declaration 'Float'}} + +namespace B { + using A::Char; // Referenced + template + 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 declaration '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(1,'a'); +} + 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,47 @@ +// 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 declaration 'Integer'}} +using N::Record; // expected-warning {{unused using declaration 'Record'}} +using N::var1; // expected-warning {{unused using declaration 'var1'}} +using N::var2; // expected-warning {{unused using declaration 'var2'}} +using N::func1; // expected-warning {{unused using declaration 'func1'}} +using N::func2; // expected-warning {{unused using declaration 'func2'}} + +void Foo() { + using N::Integer; // expected-warning {{unused using declaration '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 declaration 'var1'}} + N::var1 = 3; + + using N::var2; // Referenced + var2 = 4; + + using N::func1; // expected-warning {{unused using declaration 'func1'}} + N::func1(); + + using N::func2; // Referenced + func2(); +} + 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,21 @@ +// 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 declaration '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 declaration 'Char'}} + return 0; +} + Index: test/SemaCXX/referenced_using_directive.cpp =================================================================== --- test/SemaCXX/referenced_using_directive.cpp +++ test/SemaCXX/referenced_using_directive.cpp @@ -0,0 +1,27 @@ +// 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 directive 'N'}} + N::var = 1; +} + +void Fc() { + using namespace N; // Referenced + Integer var = 1; +} + +void Fd() { + using namespace N; // expected-warning {{unused using directive 'N'}} + N::Integer var = 1; +} + Index: test/SemaCXX/referenced_using_options.cpp =================================================================== --- test/SemaCXX/referenced_using_options.cpp +++ test/SemaCXX/referenced_using_options.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wall -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wunused -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wunused-using -verify %s + +namespace N { + typedef int Integer; +} + +using N::Integer; // expected-warning {{unused using declaration 'Integer'}} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-using" +using N::Integer; // no warning +#pragma clang diagnostic pop + +using N::Integer; // expected-warning {{unused using declaration 'Integer'}} +