]> granicus.if.org Git - clang/commitdiff
Implementing unused function warning.
authorTanya Lattner <tonic@nondot.org>
Fri, 12 Feb 2010 00:07:30 +0000 (00:07 +0000)
committerTanya Lattner <tonic@nondot.org>
Fri, 12 Feb 2010 00:07:30 +0000 (00:07 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95940 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Frontend/PCHBitCodes.h
include/clang/Frontend/PCHReader.h
lib/Frontend/PCHReader.cpp
lib/Frontend/PCHWriter.cpp
lib/Sema/Sema.cpp
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaExpr.cpp
test/Sema/warn-unused-function.c [new file with mode: 0644]

index af861ff96ffc7a41b8f81fedb7ab6643503a4ce0..0eb694cb9124a61e68a52e2369df6cbb72871853 100644 (file)
@@ -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;
index 578ce2a9e1b8831044821413321b4f8535cca2a0..e22d37ba34f5b36bae142e834c4cdf1b0bf77f3f 100644 (file)
@@ -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.
index 9665ce189f4aadc39c2ad356125ea33343d14d6d..065006fce5c4a30fa239df614ae6fb63c18138da 100644 (file)
@@ -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.
index 2a22132ea844138aaf60dd97259b7d9be2af16a2..f6f4a78c13e453fdc5175ac7ec4cdf52b8bca8a8 100644 (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
index c7e6058d6552c31ddd90ef020bf29d3389e2da59..4c99dbe245048f7b780b63194ab5ea3122c1e6b9 100644 (file)
@@ -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,
index e9a1d9c5fc178d9a4eae8411424677ae8448ff4c..38c842eede5711aef0388156c2525bb6582571df 100644 (file)
@@ -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();
+  
 }
 
 
index a835c477e28059bfec3a960ea598bd142a80311c..0ee16cae95107291d6c786081449caca8c98524c 100644 (file)
@@ -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 {
index e6b047a959d4ff7aff0b92e4cfcb28a5b6b59ab4..feb9f8511cd6a524f921db7d84daab93bd2e1b76 100644 (file)
@@ -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;
 }
 
index 0563428b18a983d94a27878c415928aea4e17364..940c3d3e7ffaae58a3c9c7b45f14d1bc51febdde 100644 (file)
@@ -7293,6 +7293,7 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
     
     // FIXME: keep track of references to static functions
     Function->setUsed(true);
+   
     return;
   }
 
diff --git a/test/Sema/warn-unused-function.c b/test/Sema/warn-unused-function.c
new file mode 100644 (file)
index 0000000..178527f
--- /dev/null
@@ -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() { } 
\ No newline at end of file