probinson created this revision.
probinson added reviewers: dblaikie, aprantl.
probinson added a subscriber: cfe-commits.

'nodebug' on a function will currently suppress all debug info for the function 
and its contents.
'nodebug on a static-duration variable will currently suppress debug info for 
the associated static initializer function (if any).
This patch suppresses all debug info for the variable, as requested in PR21823.

As a follow-up I'd like to expand applicability of 'nodebug' to any variable, 
and non-static data members.


http://reviews.llvm.org/D19567

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  lib/CodeGen/CGDebugInfo.cpp
  test/CodeGenCXX/debug-info-nodebug.cpp

Index: test/CodeGenCXX/debug-info-nodebug.cpp
===================================================================
--- test/CodeGenCXX/debug-info-nodebug.cpp
+++ test/CodeGenCXX/debug-info-nodebug.cpp
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -DSETNODEBUG=0 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s --check-prefix=YESINFO
+// RUN: %clang_cc1 -DSETNODEBUG=1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s --check-prefix=NOINFO
+
+#if SETNODEBUG
+#define NODEBUG __attribute__((nodebug))
+#else
+#define NODEBUG
+#endif
+
+// Simple global variable declaration and definition.
+// Use the declaration so it gets emitted.
+NODEBUG int global_int_decl;
+NODEBUG int global_int_def = global_int_decl;
+// YESINFO-DAG: !DIGlobalVariable(name: "global_int_decl"
+// NOINFO-NOT:  !DIGlobalVariable(name: "global_int_decl"
+// YESINFO-DAG: !DIGlobalVariable(name: "global_int_def"
+// NOINFO-NOT:  !DIGlobalVariable(name: "global_int_def"
+
+// Const global variable. Use it so it gets emitted.
+NODEBUG static const int const_global_int_def = 1;
+void func1(int);
+void func2() { func1(const_global_int_def); }
+// YESINFO-DAG: !DIGlobalVariable(name: "const_global_int_def"
+// NOINFO-NOT:  !DIGlobalVariable(name: "const_global_int_def"
+
+// Global variable with a more involved type.
+// If the variable has no debug info, the type should not appear either.
+struct S1 {
+  int a;
+  int b;
+};
+NODEBUG S1 global_struct = { 2, 3 };
+// YESINFO-DAG: !DICompositeType({{.*}} name: "S1"
+// NOINFO-NOT:  !DICompositeType({{.*}} name: "S1"
+// YESINFO-DAG: !DIGlobalVariable(name: "global_struct"
+// NOINFO-NOT:  !DIGlobalVariable(name: "global_struct"
+
+// Static data members. Const member needs a use.
+struct S2 {
+  NODEBUG static int static_member;
+  NODEBUG static const int static_const_member = 4;
+};
+int S2::static_member = 5;
+int junk = S2::static_const_member;
+// YESINFO-DAG: !DIGlobalVariable(name: "static_member"
+// NOINFO-NOT:  !DIGlobalVariable(name: "static_member"
+// YESINFO-DAG: !DIDerivedType({{.*}} name: "static_const_member"
+// NOINFO-NOT:  !DIDerivedType({{.*}} name: "static_const_member"
+
+// Function-local static variable.
+void func3() {
+  NODEBUG static int func_local = 6;
+}
+// YESINFO-DAG: !DIGlobalVariable(name: "func_local"
+// NOINFO-NOT:  !DIGlobalVariable(name: "func_local"
Index: lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- lib/CodeGen/CGDebugInfo.cpp
+++ lib/CodeGen/CGDebugInfo.cpp
@@ -1014,6 +1014,8 @@
     // the corresponding declarations in the source program.
     for (const auto *I : record->decls())
       if (const auto *V = dyn_cast<VarDecl>(I)) {
+        if (V->hasAttr<NoDebugAttr>())
+          continue;
         // Reuse the existing static member declaration if one exists
         auto MI = StaticDataMemberCache.find(V->getCanonicalDecl());
         if (MI != StaticDataMemberCache.end()) {
@@ -3391,6 +3393,8 @@
 void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
                                      const VarDecl *D) {
   assert(DebugKind >= codegenoptions::LimitedDebugInfo);
+  if (D->hasAttr<NoDebugAttr>())
+    return;
   // Create global variable debug descriptor.
   llvm::DIFile *Unit = nullptr;
   llvm::DIScope *DContext = nullptr;
@@ -3423,6 +3427,8 @@
 void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
                                      llvm::Constant *Init) {
   assert(DebugKind >= codegenoptions::LimitedDebugInfo);
+  if (VD->hasAttr<NoDebugAttr>())
+    return;
   // Create the descriptor for the variable.
   llvm::DIFile *Unit = getOrCreateFile(VD->getLocation());
   StringRef Name = VD->getName();
Index: include/clang/Basic/AttrDocs.td
===================================================================
--- include/clang/Basic/AttrDocs.td
+++ include/clang/Basic/AttrDocs.td
@@ -494,6 +494,15 @@
   }];
 }
 
+def NoDebugDocs : Documentation {
+  let Category = DocCatVariable;
+  let Content = [{
+The ``nodebug`` attribute allows you to suppress debugging information for a
+function, or for a variable declared with static storage duration, such as
+globals, class static data members, and static locals.
+  }];
+}
+
 def NoDuplicateDocs : Documentation {
   let Category = DocCatFunction;
   let Content = [{
Index: include/clang/Basic/Attr.td
===================================================================
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -973,7 +973,7 @@
 
 def NoDebug : InheritableAttr {
   let Spellings = [GCC<"nodebug">];
-  let Documentation = [Undocumented];
+  let Documentation = [NoDebugDocs];
 }
 
 def NoDuplicate : InheritableAttr {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to