[cfe-commits] r111086 - in /cfe/trunk: include/clang/Sema/Sema.h lib/AST/ASTContext.cpp lib/Sema/Sema.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/Sema/warn-unused-function.c test/SemaCXX/warn-unused-filescoped.cpp

Argyrios Kyrtzidis akyrtzi at gmail.com
Sat Aug 14 18:15:20 PDT 2010


Author: akirtzidis
Date: Sat Aug 14 20:15:20 2010
New Revision: 111086

URL: http://llvm.org/viewvc/llvm-project?rev=111086&view=rev
Log:
Commit improved version of 111026 & 111027.

Unused warnings for functions:
-static functions
-functions in anonymous namespace
-class methods in anonymous namespace
-class method specializations in anonymous namespace
-function specializations in anonymous namespace

Unused warnings for variables:
-static variables
-variables in anonymous namespace
-static data members in anonymous namespace
-static data members specializations in anonymous namespace

Reveals lots of opportunities for dead code removal in llvm codebase that will
interest my esteemed colleagues.

Added:
    cfe/trunk/test/SemaCXX/warn-unused-filescoped.cpp
Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/Sema/warn-unused-function.c

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=111086&r1=111085&r2=111086&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Sat Aug 14 20:15:20 2010
@@ -349,7 +349,7 @@
   std::vector<VarDecl *> TentativeDefinitions;
 
   /// \brief The set of file scoped decls seen so far that have not been used
-  /// and must warn if not used.
+  /// and must warn if not used. Only contains the first declaration.
   std::vector<const DeclaratorDecl*> UnusedFileScopedDecls;
 
   class AccessedEntity {
@@ -1877,6 +1877,10 @@
                                             MultiStmtArg Handlers);
   void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock);
 
+  bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const;
+  
+  /// \brief If it's a file scoped decl that must warn if not used, keep track
+  /// of it.
   void MarkUnusedFileScopedDecl(const DeclaratorDecl *D);
 
   /// DiagnoseUnusedExprResult - If the statement passed in is an expression

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=111086&r1=111085&r2=111086&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Sat Aug 14 20:15:20 2010
@@ -5640,7 +5640,8 @@
   // FIXME: Handle references.
   if (const RecordType *RT = VD->getType()->getAs<RecordType>()) {
     if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
-      if (!RD->hasTrivialConstructor() || !RD->hasTrivialDestructor())
+      if (RD->hasDefinition() &&
+          (!RD->hasTrivialConstructor() || !RD->hasTrivialDestructor()))
         return true;
     }
   }

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=111086&r1=111085&r2=111086&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Sat Aug 14 20:15:20 2010
@@ -235,6 +235,42 @@
 void Sema::DeleteStmt(StmtTy *S) {
 }
 
+/// \brief Used to prune the decls of Sema's UnusedFileScopedDecls vector.
+static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
+  if (D->isUsed())
+    return true;
+
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    // UnusedFileScopedDecls stores the first declaration.
+    // The declaration may have become definition so check again.
+    const FunctionDecl *DeclToCheck;
+    if (FD->hasBody(DeclToCheck))
+      return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
+
+    // Later redecls may add new information resulting in not having to warn,
+    // so check again.
+    DeclToCheck = FD->getMostRecentDeclaration();
+    if (DeclToCheck != FD)
+      return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
+  }
+
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    // UnusedFileScopedDecls stores the first declaration.
+    // The declaration may have become definition so check again.
+    const VarDecl *DeclToCheck = VD->getDefinition(); 
+    if (DeclToCheck)
+      return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
+
+    // Later redecls may add new information resulting in not having to warn,
+    // so check again.
+    DeclToCheck = VD->getMostRecentDeclaration();
+    if (DeclToCheck != VD)
+      return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
+  }
+
+  return false;
+}
+
 /// ActOnEndOfTranslationUnit - This is called at the very end of the
 /// translation unit when EOF is reached and all but the top-level scope is
 /// popped.
@@ -263,10 +299,10 @@
     }
   
   // Remove file scoped decls that turned out to be used.
-  UnusedFileScopedDecls.erase(std::remove_if(UnusedFileScopedDecls.begin(), 
-                                             UnusedFileScopedDecls.end(), 
-                             std::bind2nd(std::mem_fun(&DeclaratorDecl::isUsed),
-                                          true)), 
+  UnusedFileScopedDecls.erase(std::remove_if(UnusedFileScopedDecls.begin(),
+                                             UnusedFileScopedDecls.end(),
+                              std::bind1st(std::ptr_fun(ShouldRemoveFromUnused),
+                                           this)),
                               UnusedFileScopedDecls.end());
 
   if (!CompleteTranslationUnit) {
@@ -336,11 +372,19 @@
   for (std::vector<const DeclaratorDecl*>::iterator
          I = UnusedFileScopedDecls.begin(),
          E = UnusedFileScopedDecls.end(); I != E; ++I) {
-    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I))
-      Diag(FD->getLocation(), diag::warn_unused_function) << FD->getDeclName();
-    else
-      Diag((*I)->getLocation(), diag::warn_unused_variable)
-            << cast<VarDecl>(*I)->getDeclName();
+    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
+      const FunctionDecl *DiagD;
+      if (!FD->hasBody(DiagD))
+        DiagD = FD;
+      Diag(DiagD->getLocation(), diag::warn_unused_function)
+            << DiagD->getDeclName();
+    } else {
+      const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition();
+      if (!DiagD)
+        DiagD = cast<VarDecl>(*I);
+      Diag(DiagD->getLocation(), diag::warn_unused_variable)
+            << DiagD->getDeclName();
+    }
   }
 
   TUScope = 0;

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=111086&r1=111085&r2=111086&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Aug 14 20:15:20 2010
@@ -521,25 +521,71 @@
   F.done();
 }
 
-static bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) {
+bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
+  assert(D);
+
+  if (D->isInvalidDecl() || D->isUsed() || D->hasAttr<UnusedAttr>())
+    return false;
+
+  // Ignore class templates.
+  if (D->getDeclContext()->isDependentContext())
+    return false;
+
+  // We warn for unused decls internal to the translation unit.
+  if (D->getLinkage() == ExternalLinkage)
+    return false;
+
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+      if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+        return false;
+
+      if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+        if (MD->isVirtual())
+          return false;
+      } else {
+        // 'static inline' functions are used in headers; don't warn.
+        if (FD->getStorageClass() == FunctionDecl::Static &&
+            FD->isInlineSpecified())
+          return false;
+      }
+
+    if (FD->isThisDeclarationADefinition())
+      return !Context.DeclMustBeEmitted(FD);
+    return true;
+   }
+
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    if (VD->isStaticDataMember() &&
+        VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+      return false;
+
+    if ( VD->isFileVarDecl() &&
+        !VD->getType().isConstant(Context))
+      return !Context.DeclMustBeEmitted(VD);
+  }
+
+   return false;
+ }
+
+ void Sema::MarkUnusedFileScopedDecl(const DeclaratorDecl *D) {
+  if (!D)
+    return;
+
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
-    // Warn for static, non-inlined function definitions that
-    // have not been used.
-    // FIXME: Also include static functions declared but not defined.
-    return (!FD->isInvalidDecl() 
-         && !FD->isInlined() && FD->getLinkage() == InternalLinkage
-         && !FD->isUsed() && !FD->hasAttr<UnusedAttr>()
-         && !FD->hasAttr<ConstructorAttr>()
-         && !FD->hasAttr<DestructorAttr>());
+    const FunctionDecl *First = FD->getFirstDeclaration();
+    if (FD != First && ShouldWarnIfUnusedFileScopedDecl(First))
+      return; // First should already be in the vector.
   }
-  
-  return false;
-}
 
-void Sema::MarkUnusedFileScopedDecl(const DeclaratorDecl *D) {
-  if (ShouldWarnIfUnusedFileScopedDecl(D))
-    UnusedFileScopedDecls.push_back(D);
-}
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    const VarDecl *First = VD->getFirstDeclaration();
+    if (VD != First && ShouldWarnIfUnusedFileScopedDecl(First))
+      return; // First should already be in the vector.
+  }
+
+   if (ShouldWarnIfUnusedFileScopedDecl(D))
+     UnusedFileScopedDecls.push_back(D);
+ }
 
 static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
   if (D->isInvalidDecl())
@@ -2743,6 +2789,8 @@
   if (NewVD->getLinkage() == ExternalLinkage && !DC->isRecord())
     AddPushedVisibilityAttribute(NewVD);
 
+  MarkUnusedFileScopedDecl(NewVD);
+
   return NewVD;
 }
 
@@ -3638,8 +3686,7 @@
   if (FunctionTemplate)
     return FunctionTemplate;
 
-  if (IsFunctionDefinition)
-    MarkUnusedFileScopedDecl(NewFD);
+  MarkUnusedFileScopedDecl(NewFD);
 
   return NewFD;
 }

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=111086&r1=111085&r2=111086&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Sat Aug 14 20:15:20 2010
@@ -4360,8 +4360,10 @@
   
   // Mark the prior declaration as an explicit specialization, so that later
   // clients know that this is an explicit specialization.
-  if (!isFriend)
+  if (!isFriend) {
     SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
+    MarkUnusedFileScopedDecl(Specialization);
+  }
   
   // Turn the given function declaration into a function template
   // specialization, with the template arguments from the previous
@@ -4514,6 +4516,7 @@
     cast<FunctionDecl>(Member)->setInstantiationOfMemberFunction(
                                         cast<CXXMethodDecl>(InstantiatedFrom),
                                                   TSK_ExplicitSpecialization);
+    MarkUnusedFileScopedDecl(InstantiationFunction);
   } else if (isa<VarDecl>(Member)) {
     VarDecl *InstantiationVar = cast<VarDecl>(Instantiation);
     if (InstantiationVar->getTemplateSpecializationKind() ==
@@ -4526,6 +4529,7 @@
     Context.setInstantiatedFromStaticDataMember(cast<VarDecl>(Member),
                                                 cast<VarDecl>(InstantiatedFrom),
                                                 TSK_ExplicitSpecialization);
+    MarkUnusedFileScopedDecl(InstantiationVar);
   } else {
     assert(isa<CXXRecordDecl>(Member) && "Only member classes remain");
     CXXRecordDecl *InstantiationClass = cast<CXXRecordDecl>(Instantiation);

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=111086&r1=111085&r2=111086&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sat Aug 14 20:15:20 2010
@@ -449,7 +449,7 @@
   // Diagnose unused local variables.
   if (!Var->isInvalidDecl() && Owner->isFunctionOrMethod() && !Var->isUsed())
     SemaRef.DiagnoseUnusedDecl(Var);
-  
+
   return Var;
 }
 
@@ -1415,7 +1415,7 @@
     else
       Owner->addDecl(DeclToAdd);
   }
-
+  
   return Method;
 }
 

Modified: cfe/trunk/test/Sema/warn-unused-function.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-unused-function.c?rev=111086&r1=111085&r2=111086&view=diff
==============================================================================
--- cfe/trunk/test/Sema/warn-unused-function.c (original)
+++ cfe/trunk/test/Sema/warn-unused-function.c Sat Aug 14 20:15:20 2010
@@ -35,3 +35,12 @@
 
 __attribute__((destructor)) static void bar3(void);
 void bar3(void) { }
+
+static void f10(void); // expected-warning{{unused}}
+static void f10(void);
+
+static void f11(void);
+static void f11(void) { }  // expected-warning{{unused}}
+
+static void f12(void) { }  // expected-warning{{unused}}
+static void f12(void);

Added: cfe/trunk/test/SemaCXX/warn-unused-filescoped.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-unused-filescoped.cpp?rev=111086&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-unused-filescoped.cpp (added)
+++ cfe/trunk/test/SemaCXX/warn-unused-filescoped.cpp Sat Aug 14 20:15:20 2010
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wunused %s
+
+static void f1(); // expected-warning{{unused}}
+
+namespace {
+  void f2();  // expected-warning{{unused}}
+
+  void f3() { }  // expected-warning{{unused}}
+
+  struct S {
+    void m1() { }  // expected-warning{{unused}}
+    void m2();  // expected-warning{{unused}}
+    void m3();
+  };
+
+  template <typename T>
+  struct TS {
+    void m();
+  };
+  template <> void TS<int>::m() { }  // expected-warning{{unused}}
+
+  template <typename T>
+  void tf() { }
+  template <> void tf<int>() { }  // expected-warning{{unused}}
+  
+  struct VS {
+    virtual void vm() { }
+  };
+  
+  struct SVS : public VS {
+    void vm() { }
+  };
+}
+
+void S::m3() { }  // expected-warning{{unused}}
+
+static inline void f4() { }
+const unsigned int cx = 0;
+
+static int x1;  // expected-warning{{unused}}
+
+namespace {
+  int x2;  // expected-warning{{unused}}
+  
+  struct S2 {
+    static int x;  // expected-warning{{unused}}
+  };
+
+  template <typename T>
+  struct TS2 {
+    static int x;
+  };
+  template <> int TS2<int>::x;  // expected-warning{{unused}}
+}





More information about the cfe-commits mailing list