]> granicus.if.org Git - clang/commitdiff
Only generate code for static functions and global variables that are actually used.
authorNate Begeman <natebegeman@mac.com>
Sun, 20 Apr 2008 06:29:50 +0000 (06:29 +0000)
committerNate Begeman <natebegeman@mac.com>
Sun, 20 Apr 2008 06:29:50 +0000 (06:29 +0000)
Warn about unused static functions and variables.
This fixes PR1998.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49987 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticKinds.def
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h

index 8fdf716aea6676fcf4c634a7510eeaace58586a3..459121003226f2c4c247e14fc1d711a4384fbe41 100644 (file)
@@ -1036,4 +1036,10 @@ DIAG(ext_return_missing_expr, EXTENSION,
 DIAG(ext_return_has_expr, EXTENSION,
      "void function '%0' should not return a value")
 
+//===----------------------------------------------------------------------===//
+// Codegen
+//===----------------------------------------------------------------------===//
+
+DIAG(warn_unused_static, WARNING, "static '%0' defined but not used")
+
 #undef DIAG
index da38698ab61382c92d59e8a0f10bc62003fc3f0a..51d0a89cea396f21b4d8a8b5d0752b6a89419774 100644 (file)
@@ -44,6 +44,7 @@ CodeGenModule::~CodeGenModule() {
   llvm::Function *ObjCInitFunction = Runtime->ModuleInitFunction();
   if (ObjCInitFunction)
     AddGlobalCtor(ObjCInitFunction);
+  EmitStatics();
   EmitGlobalCtors();
   EmitAnnotations();
   delete Runtime;
@@ -167,8 +168,8 @@ llvm::Constant *CodeGenModule::GetAddrOfFunctionDecl(const FunctionDecl *D,
   // If it doesn't already exist, just create and return an entry.
   if (F == 0) {
     // FIXME: param attributes for sext/zext etc.
-    F = llvm::Function::Create(FTy, llvm::Function::ExternalLinkage, D->getName(),
-                           &getModule());
+    F = llvm::Function::Create(FTy, llvm::Function::ExternalLinkage,
+                               D->getName(), &getModule());
 
     // Set the appropriate calling convention for the Function.
     if (D->getAttr<FastCallAttr>())
@@ -298,8 +299,58 @@ void CodeGenModule::EmitObjCMethod(const ObjCMethodDecl *OMD) {
 
 void CodeGenModule::EmitFunction(const FunctionDecl *FD) {
   // If this is not a prototype, emit the body.
-  if (FD->getBody())
+  if (FD->getBody()) {
+    // If the function is a static, defer code generation until later so we can
+    // easily omit unused statics.
+    if (FD->getStorageClass() == FunctionDecl::Static) {
+      StaticDecls.push_back(FD);
+      return;
+    }
     CodeGenFunction(*this).GenerateCode(FD);
+  }
+}
+
+void CodeGenModule::EmitStatics() {
+  // Emit code for each used static decl encountered.  Since a previously unused
+  // static decl may become used during the generation of code for a static
+  // function, iterate until no changes are made.
+  bool Changed;
+  do {
+    Changed = false;
+    for (unsigned i = 0, e = StaticDecls.size(); i != e; ++i) {
+      // Check the map of used decls for our static. If not found, continue.
+      const Decl *D = StaticDecls[i];
+      if (GlobalDeclMap[D] == 0)
+        continue;
+      
+      // If this is a function decl, generate code for the static function if it
+      // has a body.  Otherwise, we must have a var decl for a static global
+      // variable.
+      if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+        if (FD->getBody())
+          CodeGenFunction(*this).GenerateCode(FD);
+      } else {
+        const VarDecl *VD = cast<VarDecl>(D);
+        EmitGlobalVarInit(VD);
+      }
+      // Erase the used decl from the list.
+      StaticDecls[i] = StaticDecls.back();
+      StaticDecls.pop_back();
+      --i;
+      --e;
+      
+      // Remember that we made a change.
+      Changed = true;
+    }
+  } while (Changed);
+  
+  // Warn about all statics that are still unused at end of code generation.
+  for (unsigned i = 0, e = StaticDecls.size(); i != e; ++i) {
+    const Decl *D = StaticDecls[i];
+    std::string Msg = cast<NamedDecl>(D)->getName();
+    getDiags().Report(Context.getFullLoc(D->getLocation()), 
+                      diag::warn_unused_static, &Msg, 1);
+  }
 }
 
 llvm::Constant *CodeGenModule::EmitGlobalInit(const Expr *Expr) {
@@ -351,11 +402,22 @@ llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV,
 }
 
 void CodeGenModule::EmitGlobalVar(const VarDecl *D) {
+  // If the VarDecl is a static, defer code generation until later so we can
+  // easily omit unused statics.
+  if (D->getStorageClass() == VarDecl::Static) {
+    StaticDecls.push_back(D);
+    return;
+  }
+
   // If this is just a forward declaration of the variable, don't emit it now,
   // allow it to be emitted lazily on its first use.
   if (D->getStorageClass() == VarDecl::Extern && D->getInit() == 0)
     return;
   
+  EmitGlobalVarInit(D);
+}
+
+void CodeGenModule::EmitGlobalVarInit(const VarDecl *D) {
   // Get the global, forcing it to be a direct reference.
   llvm::GlobalVariable *GV = 
     cast<llvm::GlobalVariable>(GetAddrOfGlobalVar(D, true));
@@ -468,8 +530,9 @@ llvm::Function *CodeGenModule::getBuiltinLibFunction(unsigned BuiltinID) {
   }
 
   // FIXME: param attributes for sext/zext etc.
-  return FunctionSlot = llvm::Function::Create(Ty, llvm::Function::ExternalLinkage,
-                                           Name, &getModule());
+  return FunctionSlot = 
+    llvm::Function::Create(Ty, llvm::Function::ExternalLinkage, Name,
+                           &getModule());
 }
 
 llvm::Function *CodeGenModule::getIntrinsic(unsigned IID,const llvm::Type **Tys,
index d40e35e00ce71e47bef8eb2df1b589daeb625c4a..aa676d6fdc686ba38f0eef021d557f119b66433c 100644 (file)
@@ -59,6 +59,8 @@ class CodeGenModule {
   llvm::Function *MemCpyFn;
   llvm::Function *MemSetFn;
   llvm::DenseMap<const Decl*, llvm::Constant*> GlobalDeclMap;
+  std::vector<const Decl*> StaticDecls;
+  
   std::vector<llvm::Constant*> GlobalCtors;
   std::vector<llvm::Constant*> Annotations;
     
@@ -103,10 +105,12 @@ public:
   void EmitGlobalCtors(void);
   void AddAnnotation(llvm::Constant *C) { Annotations.push_back(C); }
   void EmitAnnotations(void);
+  void EmitStatics(void);
 
   void EmitObjCMethod(const ObjCMethodDecl *OMD);
   void EmitFunction(const FunctionDecl *FD);
   void EmitGlobalVar(const VarDecl *D);
+  void EmitGlobalVarInit(const VarDecl *D);
   void EmitGlobalVarDeclarator(const VarDecl *D);
   void UpdateCompletedType(const TagDecl *D);
   llvm::Constant *EmitGlobalInit(const Expr *E);