Skip to content
Snippets Groups Projects
Commit e13796b8 authored by Vassil Vassilev's avatar Vassil Vassilev
Browse files

Warn about unused static file scope function template declarations.

Reviewed by Richard Smith (D29877)!



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@299930 91177308-0d34-0410-b5e6-96231b3b80d8
parent e0be7bc0
No related branches found
No related tags found
No related merge requests found
...@@ -470,6 +470,13 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) { ...@@ -470,6 +470,13 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
return true; return true;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
// If this is a function template and none of its specializations is used,
// we should warn.
if (FunctionTemplateDecl *Template = FD->getDescribedFunctionTemplate())
for (const auto *Spec : Template->specializations())
if (ShouldRemoveFromUnused(SemaRef, Spec))
return true;
// UnusedFileScopedDecls stores the first declaration. // UnusedFileScopedDecls stores the first declaration.
// The declaration may have become definition so check again. // The declaration may have become definition so check again.
const FunctionDecl *DeclToCheck; const FunctionDecl *DeclToCheck;
...@@ -493,6 +500,13 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) { ...@@ -493,6 +500,13 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
VD->isUsableInConstantExpressions(SemaRef->Context)) VD->isUsableInConstantExpressions(SemaRef->Context))
return true; return true;
if (VarTemplateDecl *Template = VD->getDescribedVarTemplate())
// If this is a variable template and none of its specializations is used,
// we should warn.
for (const auto *Spec : Template->specializations())
if (ShouldRemoveFromUnused(SemaRef, Spec))
return true;
// UnusedFileScopedDecls stores the first declaration. // UnusedFileScopedDecls stores the first declaration.
// The declaration may have become definition so check again. // The declaration may have become definition so check again.
const VarDecl *DeclToCheck = VD->getDefinition(); const VarDecl *DeclToCheck = VD->getDefinition();
......
...@@ -8887,6 +8887,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, ...@@ -8887,6 +8887,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (FunctionTemplate) { if (FunctionTemplate) {
if (NewFD->isInvalidDecl()) if (NewFD->isInvalidDecl())
FunctionTemplate->setInvalidDecl(); FunctionTemplate->setInvalidDecl();
MarkUnusedFileScopedDecl(NewFD);
return FunctionTemplate; return FunctionTemplate;
} }
} }
...@@ -10987,8 +10988,7 @@ static bool hasDependentAlignment(VarDecl *VD) { ...@@ -10987,8 +10988,7 @@ static bool hasDependentAlignment(VarDecl *VD) {
   
/// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform /// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform
/// any semantic actions necessary after any initializer has been attached. /// any semantic actions necessary after any initializer has been attached.
void void Sema::FinalizeDeclaration(Decl *ThisDecl) {
Sema::FinalizeDeclaration(Decl *ThisDecl) {
// Note that we are no longer parsing the initializer for this declaration. // Note that we are no longer parsing the initializer for this declaration.
ParsingInitForAutoVars.erase(ThisDecl); ParsingInitForAutoVars.erase(ThisDecl);
   
...@@ -11153,9 +11153,8 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) { ...@@ -11153,9 +11153,8 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
if (DC->getRedeclContext()->isFileContext() && VD->isExternallyVisible()) if (DC->getRedeclContext()->isFileContext() && VD->isExternallyVisible())
AddPushedVisibilityAttribute(VD); AddPushedVisibilityAttribute(VD);
   
// FIXME: Warn on unused templates. // FIXME: Warn on unused var template partial specializations.
if (VD->isFileVarDecl() && !VD->getDescribedVarTemplate() && if (VD->isFileVarDecl() && !isa<VarTemplatePartialSpecializationDecl>(VD))
!isa<VarTemplatePartialSpecializationDecl>(VD))
MarkUnusedFileScopedDecl(VD); MarkUnusedFileScopedDecl(VD);
   
// Now we have parsed the initializer and can update the table of magic // Now we have parsed the initializer and can update the table of magic
......
// RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-member-function -Wno-unused-local-typedefs -Wno-c++11-extensions -std=c++98 %s // RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-member-function -Wno-unused-local-typedefs -Wno-c++11-extensions -std=c++98 %s
// RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-member-function -Wno-unused-local-typedefs -std=c++11 %s // RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-member-function -Wno-unused-local-typedefs -std=c++14 %s
#ifdef HEADER #ifdef HEADER
...@@ -65,7 +65,7 @@ namespace { ...@@ -65,7 +65,7 @@ namespace {
template <> void TS<int>::m() { } // expected-warning{{unused}} template <> void TS<int>::m() { } // expected-warning{{unused}}
template <typename T> template <typename T>
void tf() { } void tf() { } // expected-warning{{unused}}
template <> void tf<int>() { } // expected-warning{{unused}} template <> void tf<int>() { } // expected-warning{{unused}}
struct VS { struct VS {
...@@ -200,6 +200,18 @@ void bar() { void func() __attribute__((used)); } ...@@ -200,6 +200,18 @@ void bar() { void func() __attribute__((used)); }
static void func() {} static void func() {}
} }
namespace test9 {
template<typename T>
static void completeRedeclChainForTemplateSpecialization() { } // expected-warning {{unused}}
}
namespace test10 {
#if __cplusplus >= 201103L
template<class T>
constexpr T pi = T(3.14); // expected-warning {{unused}}
#endif
}
namespace pr19713 { namespace pr19713 {
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
// FIXME: We should warn on both of these. // FIXME: We should warn on both of these.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment