forked from OSchip/llvm-project
Reland "Warn about unused static file scope function template declarations."
This patch reinstates r299930, reverted in r299956, as a separate diagnostic option (-Wunused-template). llvm-svn: 302518
This commit is contained in:
parent
5a741dd8a6
commit
64e1e1ea0a
clang
include/clang/Basic
lib/Sema
test/SemaCXX
|
@ -486,6 +486,7 @@ def UnneededInternalDecl : DiagGroup<"unneeded-internal-declaration">;
|
|||
def UnneededMemberFunction : DiagGroup<"unneeded-member-function">;
|
||||
def UnusedPrivateField : DiagGroup<"unused-private-field">;
|
||||
def UnusedFunction : DiagGroup<"unused-function", [UnneededInternalDecl]>;
|
||||
def UnusedTemplate : DiagGroup<"unused-template", [UnneededInternalDecl]>;
|
||||
def UnusedMemberFunction : DiagGroup<"unused-member-function",
|
||||
[UnneededMemberFunction]>;
|
||||
def UnusedLabel : DiagGroup<"unused-label">;
|
||||
|
@ -627,6 +628,7 @@ def Conversion : DiagGroup<"conversion",
|
|||
def Unused : DiagGroup<"unused",
|
||||
[UnusedArgument, UnusedFunction, UnusedLabel,
|
||||
// UnusedParameter, (matches GCC's behavior)
|
||||
// UnusedTemplate, (clean-up libc++ before enabling)
|
||||
// UnusedMemberFunction, (clean-up llvm before enabling)
|
||||
UnusedPrivateField, UnusedLambdaCapture,
|
||||
UnusedLocalTypedef, UnusedValue, UnusedVariable,
|
||||
|
|
|
@ -303,6 +303,8 @@ def note_empty_parens_zero_initialize : Note<
|
|||
"replace parentheses with an initializer to declare a variable">;
|
||||
def warn_unused_function : Warning<"unused function %0">,
|
||||
InGroup<UnusedFunction>, DefaultIgnore;
|
||||
def warn_unused_template : Warning<"unused %select{function|variable}0 template %1">,
|
||||
InGroup<UnusedTemplate>, DefaultIgnore;
|
||||
def warn_unused_member_function : Warning<"unused member function %0">,
|
||||
InGroup<UnusedMemberFunction>, DefaultIgnore;
|
||||
def warn_used_but_marked_unused: Warning<"%0 was marked unused but was used">,
|
||||
|
|
|
@ -477,6 +477,13 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
|
|||
return true;
|
||||
|
||||
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.
|
||||
// The declaration may have become definition so check again.
|
||||
const FunctionDecl *DeclToCheck;
|
||||
|
@ -500,6 +507,13 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
|
|||
VD->isUsableInConstantExpressions(SemaRef->Context))
|
||||
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.
|
||||
// The declaration may have become definition so check again.
|
||||
const VarDecl *DeclToCheck = VD->getDefinition();
|
||||
|
@ -905,10 +919,14 @@ void Sema::ActOnEndOfTranslationUnit() {
|
|||
<< /*function*/0 << DiagD->getDeclName();
|
||||
}
|
||||
} else {
|
||||
Diag(DiagD->getLocation(),
|
||||
isa<CXXMethodDecl>(DiagD) ? diag::warn_unused_member_function
|
||||
: diag::warn_unused_function)
|
||||
<< DiagD->getDeclName();
|
||||
if (FD->getDescribedFunctionTemplate())
|
||||
Diag(DiagD->getLocation(), diag::warn_unused_template)
|
||||
<< /*function*/0 << DiagD->getDeclName();
|
||||
else
|
||||
Diag(DiagD->getLocation(),
|
||||
isa<CXXMethodDecl>(DiagD) ? diag::warn_unused_member_function
|
||||
: diag::warn_unused_function)
|
||||
<< DiagD->getDeclName();
|
||||
}
|
||||
} else {
|
||||
const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition();
|
||||
|
@ -924,7 +942,11 @@ void Sema::ActOnEndOfTranslationUnit() {
|
|||
Diag(DiagD->getLocation(), diag::warn_unused_const_variable)
|
||||
<< DiagD->getDeclName();
|
||||
} else {
|
||||
Diag(DiagD->getLocation(), diag::warn_unused_variable)
|
||||
if (DiagD->getDescribedVarTemplate())
|
||||
Diag(DiagD->getLocation(), diag::warn_unused_template)
|
||||
<< /*variable*/1 << DiagD->getDeclName();
|
||||
else
|
||||
Diag(DiagD->getLocation(), diag::warn_unused_variable)
|
||||
<< DiagD->getDeclName();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8923,6 +8923,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
if (FunctionTemplate) {
|
||||
if (NewFD->isInvalidDecl())
|
||||
FunctionTemplate->setInvalidDecl();
|
||||
MarkUnusedFileScopedDecl(NewFD);
|
||||
return FunctionTemplate;
|
||||
}
|
||||
}
|
||||
|
@ -11023,8 +11024,7 @@ static bool hasDependentAlignment(VarDecl *VD) {
|
|||
|
||||
/// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform
|
||||
/// any semantic actions necessary after any initializer has been attached.
|
||||
void
|
||||
Sema::FinalizeDeclaration(Decl *ThisDecl) {
|
||||
void Sema::FinalizeDeclaration(Decl *ThisDecl) {
|
||||
// Note that we are no longer parsing the initializer for this declaration.
|
||||
ParsingInitForAutoVars.erase(ThisDecl);
|
||||
|
||||
|
@ -11189,9 +11189,8 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
|
|||
if (DC->getRedeclContext()->isFileContext() && VD->isExternallyVisible())
|
||||
AddPushedVisibilityAttribute(VD);
|
||||
|
||||
// FIXME: Warn on unused templates.
|
||||
if (VD->isFileVarDecl() && !VD->getDescribedVarTemplate() &&
|
||||
!isa<VarTemplatePartialSpecializationDecl>(VD))
|
||||
// FIXME: Warn on unused var template partial specializations.
|
||||
if (VD->isFileVarDecl() && !isa<VarTemplatePartialSpecializationDecl>(VD))
|
||||
MarkUnusedFileScopedDecl(VD);
|
||||
|
||||
// Now we have parsed the initializer and can update the table of magic
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// 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-template -Wunused-member-function -Wno-unused-local-typedefs -Wno-c++11-extensions -std=c++98 %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-template -Wunused-member-function -Wno-unused-local-typedefs -std=c++14 %s
|
||||
|
||||
#ifdef HEADER
|
||||
|
||||
|
@ -65,7 +65,7 @@ namespace {
|
|||
template <> void TS<int>::m() { } // expected-warning{{unused}}
|
||||
|
||||
template <typename T>
|
||||
void tf() { }
|
||||
void tf() { } // expected-warning{{unused}}
|
||||
template <> void tf<int>() { } // expected-warning{{unused}}
|
||||
|
||||
struct VS {
|
||||
|
@ -200,6 +200,18 @@ void bar() { void func() __attribute__((used)); }
|
|||
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 {
|
||||
#if __cplusplus >= 201103L
|
||||
// FIXME: We should warn on both of these.
|
||||
|
|
Loading…
Reference in New Issue