From b17327d7b6c0077ff176f138f283a04867fdf707 Mon Sep 17 00:00:00 2001 From: Paul Robinson Date: Wed, 27 Apr 2016 17:37:12 +0000 Subject: [PATCH] PR21823: 'nodebug' attribute on global/static variables. Make 'nodebug' on a global/static variable suppress all debug info for the variable. Previously it would only suppress info for the associated initializer function, if any. Differential Revision: http://reviews.llvm.org/D19567 llvm-svn: 267746 --- clang/include/clang/Basic/Attr.td | 2 +- clang/include/clang/Basic/AttrDocs.td | 9 +++++ clang/lib/CodeGen/CGDebugInfo.cpp | 6 +++ clang/test/CodeGenCXX/debug-info-nodebug.cpp | 55 ++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGenCXX/debug-info-nodebug.cpp diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 1ae2c57..1f86b09 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -973,7 +973,7 @@ def NoCommon : InheritableAttr { def NoDebug : InheritableAttr { let Spellings = [GCC<"nodebug">]; - let Documentation = [Undocumented]; + let Documentation = [NoDebugDocs]; } def NoDuplicate : InheritableAttr { diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index a67fd75..b1b9e44 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -494,6 +494,15 @@ Query for this feature with ``__has_attribute(objc_method_family)``. }]; } +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 = [{ diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index b44ddc4..29f5971 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1014,6 +1014,8 @@ void CGDebugInfo::CollectRecordFields( // the corresponding declarations in the source program. for (const auto *I : record->decls()) if (const auto *V = dyn_cast(I)) { + if (V->hasAttr()) + continue; // Reuse the existing static member declaration if one exists auto MI = StaticDataMemberCache.find(V->getCanonicalDecl()); if (MI != StaticDataMemberCache.end()) { @@ -3390,6 +3392,8 @@ llvm::DIGlobalVariable *CGDebugInfo::CollectAnonRecordDecls( void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, const VarDecl *D) { assert(DebugKind >= codegenoptions::LimitedDebugInfo); + if (D->hasAttr()) + return; // Create global variable debug descriptor. llvm::DIFile *Unit = nullptr; llvm::DIScope *DContext = nullptr; @@ -3422,6 +3426,8 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, llvm::Constant *Init) { assert(DebugKind >= codegenoptions::LimitedDebugInfo); + if (VD->hasAttr()) + return; // Create the descriptor for the variable. llvm::DIFile *Unit = getOrCreateFile(VD->getLocation()); StringRef Name = VD->getName(); diff --git a/clang/test/CodeGenCXX/debug-info-nodebug.cpp b/clang/test/CodeGenCXX/debug-info-nodebug.cpp new file mode 100644 index 0000000..e2f5fb6 --- /dev/null +++ b/clang/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" -- 2.7.4