mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-27 06:36:46 +00:00
Implementing unused function warning.
llvm-svn: 95940
This commit is contained in:
parent
a90f7ca591
commit
90073804fb
@ -87,7 +87,9 @@ def warn_decl_in_param_list : Warning<
|
||||
"declaration of %0 will not be visible outside of this function">;
|
||||
def err_array_star_in_function_definition : Error<
|
||||
"variable length array must be bound in function definition">;
|
||||
|
||||
def warn_unused_function : Warning<"unused function %0">,
|
||||
InGroup<UnusedFunction>, DefaultIgnore;
|
||||
|
||||
def warn_implicit_function_decl : Warning<
|
||||
"implicit declaration of function %0">,
|
||||
InGroup<ImplicitFunctionDeclare>, DefaultIgnore;
|
||||
|
@ -221,7 +221,11 @@ namespace clang {
|
||||
|
||||
/// \brief Record code for the version control branch and revision
|
||||
/// information of the compiler used to build this PCH file.
|
||||
VERSION_CONTROL_BRANCH_REVISION = 21
|
||||
VERSION_CONTROL_BRANCH_REVISION = 21,
|
||||
|
||||
/// \brief Record code for the array of unused static functions.
|
||||
UNUSED_STATIC_FUNCS = 22
|
||||
|
||||
};
|
||||
|
||||
/// \brief Record types used within a source manager block.
|
||||
|
@ -306,6 +306,10 @@ private:
|
||||
/// \brief The set of tentative definitions stored in the the PCH
|
||||
/// file.
|
||||
llvm::SmallVector<uint64_t, 16> TentativeDefinitions;
|
||||
|
||||
/// \brief The set of tentative definitions stored in the the PCH
|
||||
/// file.
|
||||
llvm::SmallVector<uint64_t, 16> UnusedStaticFuncs;
|
||||
|
||||
/// \brief The set of locally-scoped external declarations stored in
|
||||
/// the the PCH file.
|
||||
|
@ -1332,6 +1332,14 @@ PCHReader::ReadPCHBlock() {
|
||||
TentativeDefinitions.swap(Record);
|
||||
break;
|
||||
|
||||
case pch::UNUSED_STATIC_FUNCS:
|
||||
if (!UnusedStaticFuncs.empty()) {
|
||||
Error("duplicate UNUSED_STATIC_FUNCS record in PCH file");
|
||||
return Failure;
|
||||
}
|
||||
UnusedStaticFuncs.swap(Record);
|
||||
break;
|
||||
|
||||
case pch::LOCALLY_SCOPED_EXTERNAL_DECLS:
|
||||
if (!LocallyScopedExternalDecls.empty()) {
|
||||
Error("duplicate LOCALLY_SCOPED_EXTERNAL_DECLS record in PCH file");
|
||||
@ -2479,6 +2487,13 @@ void PCHReader::InitializeSema(Sema &S) {
|
||||
VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I]));
|
||||
SemaObj->TentativeDefinitions.push_back(Var);
|
||||
}
|
||||
|
||||
// If there were any unused static functions, deserialize them and add to
|
||||
// Sema's list of unused static functions.
|
||||
for (unsigned I = 0, N = UnusedStaticFuncs.size(); I != N; ++I) {
|
||||
FunctionDecl *FD = cast<FunctionDecl>(GetDecl(UnusedStaticFuncs[I]));
|
||||
SemaObj->UnusedStaticFuncs.push_back(FD);
|
||||
}
|
||||
|
||||
// If there were any locally-scoped external declarations,
|
||||
// deserialize them and add them to Sema's table of locally-scoped
|
||||
|
@ -545,6 +545,7 @@ void PCHWriter::WriteBlockInfoBlock() {
|
||||
RECORD(SPECIAL_TYPES);
|
||||
RECORD(STATISTICS);
|
||||
RECORD(TENTATIVE_DEFINITIONS);
|
||||
RECORD(UNUSED_STATIC_FUNCS);
|
||||
RECORD(LOCALLY_SCOPED_EXTERNAL_DECLS);
|
||||
RECORD(SELECTOR_OFFSETS);
|
||||
RECORD(METHOD_POOL);
|
||||
@ -1982,6 +1983,11 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
|
||||
AddDeclRef(SemaRef.TentativeDefinitions[i], TentativeDefinitions);
|
||||
}
|
||||
|
||||
// Build a record containing all of the static unused functions in this file.
|
||||
RecordData UnusedStaticFuncs;
|
||||
for (unsigned i=0, e = SemaRef.UnusedStaticFuncs.size(); i !=e; ++i)
|
||||
AddDeclRef(SemaRef.UnusedStaticFuncs[i], UnusedStaticFuncs);
|
||||
|
||||
// Build a record containing all of the locally-scoped external
|
||||
// declarations in this header file. Generally, this record will be
|
||||
// empty.
|
||||
@ -2083,6 +2089,10 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
|
||||
if (!TentativeDefinitions.empty())
|
||||
Stream.EmitRecord(pch::TENTATIVE_DEFINITIONS, TentativeDefinitions);
|
||||
|
||||
// Write the record containing unused static functions.
|
||||
if (!UnusedStaticFuncs.empty())
|
||||
Stream.EmitRecord(pch::UNUSED_STATIC_FUNCS, UnusedStaticFuncs);
|
||||
|
||||
// Write the record containing locally-scoped external definitions.
|
||||
if (!LocallyScopedExternalDecls.empty())
|
||||
Stream.EmitRecord(pch::LOCALLY_SCOPED_EXTERNAL_DECLS,
|
||||
|
@ -185,6 +185,12 @@ void Sema::DeleteStmt(StmtTy *S) {
|
||||
/// popped.
|
||||
void Sema::ActOnEndOfTranslationUnit() {
|
||||
|
||||
// Remove functions that turned out to be used.
|
||||
UnusedStaticFuncs.erase(std::remove_if(UnusedStaticFuncs.begin(),
|
||||
UnusedStaticFuncs.end(),
|
||||
std::mem_fun(&FunctionDecl::isUsed)),
|
||||
UnusedStaticFuncs.end());
|
||||
|
||||
while (1) {
|
||||
// C++: Perform implicit template instantiations.
|
||||
//
|
||||
@ -265,6 +271,15 @@ void Sema::ActOnEndOfTranslationUnit() {
|
||||
Consumer.CompleteTentativeDefinition(VD);
|
||||
|
||||
}
|
||||
|
||||
// Output warning for unused functions.
|
||||
for (std::vector<FunctionDecl*>::iterator
|
||||
F = UnusedStaticFuncs.begin(),
|
||||
FEnd = UnusedStaticFuncs.end();
|
||||
F != FEnd;
|
||||
++F)
|
||||
Diag((*F)->getLocation(), diag::warn_unused_function) << (*F)->getDeclName();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -276,6 +276,9 @@ public:
|
||||
/// \brief All the tentative definitions encountered in the TU.
|
||||
std::vector<VarDecl *> TentativeDefinitions;
|
||||
|
||||
/// \brief The set of static functions seen so far that have not been used.
|
||||
std::vector<FunctionDecl*> UnusedStaticFuncs;
|
||||
|
||||
/// An enum describing the kind of diagnostics to use when checking
|
||||
/// access.
|
||||
enum AccessDiagnosticsKind {
|
||||
|
@ -3129,6 +3129,15 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||
if (FunctionTemplate)
|
||||
return FunctionTemplate;
|
||||
|
||||
|
||||
// Keep track of static, non-inlined function definitions that
|
||||
// have not been used. We will warn later.
|
||||
// FIXME: Also include static functions declared but not defined.
|
||||
if (!NewFD->isInvalidDecl() && IsFunctionDefinition
|
||||
&& !NewFD->isInlined() && NewFD->getLinkage() == InternalLinkage
|
||||
&& !NewFD->isUsed())
|
||||
UnusedStaticFuncs.push_back(NewFD);
|
||||
|
||||
return NewFD;
|
||||
}
|
||||
|
||||
|
@ -7293,6 +7293,7 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
|
||||
|
||||
// FIXME: keep track of references to static functions
|
||||
Function->setUsed(true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
16
clang/test/Sema/warn-unused-function.c
Normal file
16
clang/test/Sema/warn-unused-function.c
Normal file
@ -0,0 +1,16 @@
|
||||
// RUN: %clang_cc1 -fsyntax-only -Wunused-function -verify %s
|
||||
|
||||
void foo() {}
|
||||
static void f2() {}
|
||||
static void f1() {f2();} // expected-warning{{unused}}
|
||||
|
||||
static int f0() { return 17; } // expected-warning{{unused}}
|
||||
int x = sizeof(f0());
|
||||
|
||||
static void f3();
|
||||
extern void f3() { } // expected-warning{{unused}}
|
||||
|
||||
// FIXME: This will trigger a warning when it should not.
|
||||
// Update once PR6281 is fixed.
|
||||
//inline static void f4();
|
||||
//void f4() { }
|
Loading…
x
Reference in New Issue
Block a user