nickdesaulniers updated this revision to Diff 269981.
nickdesaulniers added a comment.

- update comment to CODEGENOPT
- avoid BooleanFFlag group


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80242/new/

https://reviews.llvm.org/D80242

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/docs/CommandGuide/clang.rst
  clang/docs/UsersManual.rst
  clang/include/clang/Basic/CodeGenOptions.def
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/CGDecl.cpp
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGen/debug-info-unused-types.c
  clang/test/CodeGen/debug-info-unused-types.cpp
  clang/test/Driver/debug-options.c

Index: clang/test/Driver/debug-options.c
===================================================================
--- clang/test/Driver/debug-options.c
+++ clang/test/Driver/debug-options.c
@@ -361,3 +361,7 @@
 // GEMBED_2:  error: invalid argument '-gembed-source' only allowed with '-gdwarf-5'
 // NOGEMBED_5-NOT:  "-gembed-source"
 // NOGEMBED_2-NOT:  error: invalid argument '-gembed-source' only allowed with '-gdwarf-5'
+//
+// RUN: %clang -### -fno-eliminate-unused-debug-types -c %s 2>&1 \
+// RUN:        | FileCheck -check-prefix=DEBUG_UNUSED_TYPES %s
+// DEBUG_UNUSED_TYPES: "-fno-eliminate-unused-debug-types"
Index: clang/test/CodeGen/debug-info-unused-types.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/debug-info-unused-types.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang++ -fno-eliminate-unused-debug-types -g -emit-llvm -S -o - %s | FileCheck %s
+// RUN: %clang++ -feliminate-unused-debug-types -g -emit-llvm -S -o - %s | FileCheck --check-prefix=NODBG %s
+// RUN: %clang++ -g -emit-llvm -S -o - %s | FileCheck --check-prefix=NODBG %s
+// RUN: %clang++ -emit-llvm -S -o - %s | FileCheck --check-prefix=NODBG %s
+using foo = int;
+class bar {};
+enum class baz { BAZ };
+
+void quux() {
+  using x = int;
+  class y {};
+  enum class z { Z };
+}
+
+// CHECK: !3 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "baz", file: !4, line: 7, baseType: !5, size: 32, flags: DIFlagEnumClass, elements: !6, identifier: "_ZTS3baz")
+// CHECK: !7 = !DIEnumerator(name: "BAZ", value: 0)
+// CHECK: !8 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "z", scope: !9, file: !4, line: 12, baseType: !5, size: 32, flags: DIFlagEnumClass, elements: !13)
+// CHECK: !14 = !DIEnumerator(name: "Z", value: 0)
+// CHECK: !16 = !DIDerivedType(tag: DW_TAG_typedef, name: "foo", file: !4, line: 5, baseType: !5)
+// CHECK: !17 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "bar", file: !4, line: 6, size: 8, flags: DIFlagTypePassByValue, elements: !12, identifier: "_ZTS3bar")
+// CHECK: !18 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "y", scope: !9, file: !4, line: 11, size: 8, flags: DIFlagTypePassByValue, elements: !12)
+
+// NODBG-NOT: !3 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "baz", file: !4, line: 7, baseType: !5, size: 32, flags: DIFlagEnumClass, elements: !6, identifier: "_ZTS3baz")
+// NODBG-NOT: !7 = !DIEnumerator(name: "BAZ", value: 0)
+// NODBG-NOT: !8 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "z", scope: !9, file: !4, line: 12, baseType: !5, size: 32, flags: DIFlagEnumClass, elements: !13)
+// NODBG-NOT: !14 = !DIEnumerator(name: "Z", value: 0)
+// NODBG-NOT: !16 = !DIDerivedType(tag: DW_TAG_typedef, name: "foo", file: !4, line: 5, baseType: !5)
+// NODBG-NOT: !17 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "bar", file: !4, line: 6, size: 8, flags: DIFlagTypePassByValue, elements: !12, identifier: "_ZTS3bar")
+// NODBG-NOT: !18 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "y", scope: !9, file: !4, line: 11, size: 8, flags: DIFlagTypePassByValue, elements: !12)
Index: clang/test/CodeGen/debug-info-unused-types.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/debug-info-unused-types.c
@@ -0,0 +1,44 @@
+// RUN: %clang -fno-eliminate-unused-debug-types -g -emit-llvm -S -o - %s | FileCheck %s
+// RUN: %clang -feliminate-unused-debug-types -g -emit-llvm -S -o - %s | FileCheck --check-prefix=NODBG %s
+// RUN: %clang -g -emit-llvm -S -o - %s | FileCheck --check-prefix=NODBG %s
+// RUN: %clang -emit-llvm -S -o - %s | FileCheck --check-prefix=NODBG %s
+typedef int my_int;
+struct foo {};
+enum bar { BAR };
+union baz {};
+
+void quux(void) {
+  typedef int x;
+  struct y {};
+  enum z { Z };
+  union w {};
+}
+
+// Check that debug info is emitted for the typedef, struct, enum, and union
+// when -fno-eliminate-unused-debug-types and -g are set.
+
+// CHECK: !3 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "bar", file: !4, line: 7, baseType: !5, size: 32, elements: !6)
+// CHECK: !7 = !DIEnumerator(name: "BAR", value: 0, isUnsigned: true)
+// CHECK: !8 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "z", scope: !9, file: !4, line: 13, baseType: !5, size: 32, elements: !13)
+// CHECK: !14 = !DIEnumerator(name: "Z", value: 0, isUnsigned: true)
+// CHECK: !16 = !DIDerivedType(tag: DW_TAG_typedef, name: "my_int", file: !4, line: 5, baseType: !17)
+// CHECK: !17 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+// CHECK: !18 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo", file: !4, line: 6, elements: !12)
+// CHECK: !19 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "baz", file: !4, line: 8, elements: !12)
+// CHECK: !20 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "y", scope: !9, file: !4, line: 12, elements: !12)
+// CHECK: !21 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "w", scope: !9, file: !4, line: 14, elements: !12)
+
+// Check that debug info is not emitted for the typedef, struct, enum, and
+// union when -fno-eliminate-unused-debug-types and -g are not set. These are
+// the same checks as above with `NODBG-NOT` rather than `CHECK`.
+
+// NODBG-NOT: !3 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "bar", file: !4, line: 7, baseType: !5, size: 32, elements: !6)
+// NODBG-NOT: !7 = !DIEnumerator(name: "BAR", value: 0, isUnsigned: true)
+// NODBG-NOT: !8 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "z", scope: !9, file: !4, line: 13, baseType: !5, size: 32, elements: !13)
+// NODBG-NOT: !14 = !DIEnumerator(name: "Z", value: 0, isUnsigned: true)
+// NODBG-NOT: !16 = !DIDerivedType(tag: DW_TAG_typedef, name: "my_int", file: !4, line: 5, baseType: !17)
+// NODBG-NOT: !17 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+// NODBG-NOT: !18 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo", file: !4, line: 6, elements: !12)
+// NODBG-NOT: !19 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "baz", file: !4, line: 8, elements: !12)
+// NODBG-NOT: !20 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "y", scope: !9, file: !4, line: 12, elements: !12)
+// NODBG-NOT: !21 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "w", scope: !9, file: !4, line: 14, elements: !12)
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -765,6 +765,7 @@
   Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs);
   Opts.DebugExplicitImport = Args.hasArg(OPT_dwarf_explicit_import);
   Opts.DebugFwdTemplateParams = Args.hasArg(OPT_debug_forward_template_params);
+  Opts.DebugUnusedTypes = Args.hasArg(OPT_fno_eliminate_unused_debug_types);
   Opts.EmbedSource = Args.hasArg(OPT_gembed_source);
   Opts.ForceDwarfFrameSection = Args.hasArg(OPT_fforce_dwarf_frame);
 
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -5192,6 +5192,8 @@
 
   // Forward -f (flag) options which we can pass directly.
   Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
+  Args.AddLastArg(CmdArgs, options::OPT_feliminate_unused_debug_types,
+                  options::OPT_fno_eliminate_unused_debug_types);
   Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
   Args.AddLastArg(CmdArgs, options::OPT_fdigraphs, options::OPT_fno_digraphs);
   Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -5371,16 +5371,21 @@
           Spec->hasDefinition())
         DI->completeTemplateDefinition(*Spec);
   } LLVM_FALLTHROUGH;
-  case Decl::CXXRecord:
-    if (CGDebugInfo *DI = getModuleDebugInfo())
-      if (auto *ES = D->getASTContext().getExternalSource())
+  case Decl::CXXRecord: {
+    CXXRecordDecl *CRD = cast<CXXRecordDecl>(D);
+    if (CGDebugInfo *DI = getModuleDebugInfo()) {
+      if (getCodeGenOpts().DebugUnusedTypes && CRD->hasDefinition())
+        DI->completeUnusedClass(*CRD);
+      else if (auto *ES = D->getASTContext().getExternalSource())
         if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never)
-          DI->completeUnusedClass(cast<CXXRecordDecl>(*D));
+          DI->completeUnusedClass(*CRD);
+    }
     // Emit any static data members, they may be definitions.
-    for (auto *I : cast<CXXRecordDecl>(D)->decls())
+    for (auto *I : CRD->decls())
       if (isa<VarDecl>(I) || isa<CXXRecordDecl>(I))
         EmitTopLevelDecl(I);
     break;
+  }
     // No code generation needed.
   case Decl::UsingShadow:
   case Decl::ClassTemplate:
@@ -5566,6 +5571,31 @@
     EmitOMPRequiresDecl(cast<OMPRequiresDecl>(D));
     break;
 
+  case Decl::Typedef:
+  case Decl::TypeAlias: // using foo = bar; [C++11]
+    if (CGDebugInfo *DI = getModuleDebugInfo())
+      if (getCodeGenOpts().DebugUnusedTypes) {
+        QualType QT = getContext().getTypedefType(cast<TypedefNameDecl>(D));
+        DI->EmitExplicitCastType(QT);
+      }
+    break;
+
+  case Decl::Record:
+    if (CGDebugInfo *DI = getModuleDebugInfo())
+      if (getCodeGenOpts().DebugUnusedTypes) {
+        QualType QT = getContext().getRecordType(cast<RecordDecl>(D));
+        DI->EmitExplicitCastType(QT);
+      }
+    break;
+
+  case Decl::Enum:
+    if (CGDebugInfo *DI = getModuleDebugInfo())
+      if (getCodeGenOpts().DebugUnusedTypes) {
+        QualType QT = getContext().getEnumType(cast<EnumDecl>(D));
+        DI->EmitExplicitCastType(QT);
+      }
+    break;
+
   default:
     // Make sure we handled everything we should, every other kind is a
     // non-top-level decl.  FIXME: Would be nice to have an isTopLevelDeclKind
Index: clang/lib/CodeGen/CGDecl.cpp
===================================================================
--- clang/lib/CodeGen/CGDecl.cpp
+++ clang/lib/CodeGen/CGDecl.cpp
@@ -100,11 +100,24 @@
   case Decl::ObjCTypeParam:
   case Decl::Binding:
     llvm_unreachable("Declaration should not be in declstmts!");
-  case Decl::Function:  // void X();
+  case Decl::CXXRecord: // struct/union/class X; [C++]
+    if (CGDebugInfo *DI = getDebugInfo())
+      if (CGM.getCodeGenOpts().DebugUnusedTypes)
+        DI->completeUnusedClass(cast<CXXRecordDecl>(D));
+    return;
   case Decl::Record:    // struct/union/class X;
+    if (CGDebugInfo *DI = getDebugInfo())
+      if (CGM.getCodeGenOpts().DebugUnusedTypes)
+        DI->EmitExplicitCastType(
+            getContext().getRecordType(cast<RecordDecl>(&D)));
+    return;
   case Decl::Enum:      // enum X;
+    if (CGDebugInfo *DI = getDebugInfo())
+      if (CGM.getCodeGenOpts().DebugUnusedTypes)
+        DI->EmitExplicitCastType(getContext().getEnumType(cast<EnumDecl>(&D)));
+    return;
+  case Decl::Function:     // void X();
   case Decl::EnumConstant: // enum ? { X = ? }
-  case Decl::CXXRecord: // struct/union/class X; [C++]
   case Decl::StaticAssert: // static_assert(X, ""); [C++0x]
   case Decl::Label:        // __label__ x;
   case Decl::Import:
@@ -157,12 +170,12 @@
 
   case Decl::Typedef:      // typedef int X;
   case Decl::TypeAlias: {  // using X = int; [C++0x]
-    const TypedefNameDecl &TD = cast<TypedefNameDecl>(D);
-    QualType Ty = TD.getUnderlyingType();
-
+    QualType Ty = cast<TypedefNameDecl>(D).getUnderlyingType();
+    if (CGDebugInfo *DI = getDebugInfo())
+      if (CGM.getCodeGenOpts().DebugUnusedTypes)
+        return DI->EmitExplicitCastType(Ty);
     if (Ty->isVariablyModifiedType())
       EmitVariablyModifiedType(Ty);
-
     return;
   }
   }
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -921,6 +921,8 @@
     Flags<[CC1Option]>,
     HelpText<"Do not elide types when printing diagnostics">;
 def feliminate_unused_debug_symbols : Flag<["-"], "feliminate-unused-debug-symbols">, Group<f_Group>;
+def feliminate_unused_debug_types : Flag<["-"],
+  "feliminate-unused-debug-types">, Group<f_Group>, Flags<[CC1Option]>;
 def femit_all_decls : Flag<["-"], "femit-all-decls">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Emit all declarations, even if unused">;
 def femulated_tls : Flag<["-"], "femulated-tls">, Group<f_Group>, Flags<[CC1Option]>,
@@ -1485,6 +1487,9 @@
 def fno_elide_constructors : Flag<["-"], "fno-elide-constructors">, Group<f_Group>,
   HelpText<"Disable C++ copy constructor elision">, Flags<[CC1Option]>;
 def fno_eliminate_unused_debug_symbols : Flag<["-"], "fno-eliminate-unused-debug-symbols">, Group<f_Group>;
+def fno_eliminate_unused_debug_types : Flag<["-"],
+  "fno-eliminate-unused-debug-types">, Group<f_Group> , Flags<[CC1Option]>,
+  HelpText<"Emit debug info for types that may be unused.">;
 def fno_gnu_keywords : Flag<["-"], "fno-gnu-keywords">, Group<f_Group>, Flags<[CC1Option]>;
 def fno_inline_functions : Flag<["-"], "fno-inline-functions">, Group<f_clang_Group>, Flags<[CC1Option]>;
 def fno_inline : Flag<["-"], "fno-inline">, Group<f_clang_Group>, Flags<[CC1Option]>;
@@ -3230,7 +3235,6 @@
 defm fcheck_new : BooleanFFlag<"check-new">, Group<clang_ignored_f_Group>;
 defm caller_saves : BooleanFFlag<"caller-saves">, Group<clang_ignored_gcc_optimization_f_Group>;
 defm reorder_blocks : BooleanFFlag<"reorder-blocks">, Group<clang_ignored_gcc_optimization_f_Group>;
-defm eliminate_unused_debug_types : BooleanFFlag<"eliminate-unused-debug-types">, Group<clang_ignored_f_Group>;
 defm branch_count_reg : BooleanFFlag<"branch-count-reg">, Group<clang_ignored_gcc_optimization_f_Group>;
 defm default_inline : BooleanFFlag<"default-inline">, Group<clang_ignored_gcc_optimization_f_Group>;
 defm fat_lto_objects : BooleanFFlag<"fat-lto-objects">, Group<clang_ignored_gcc_optimization_f_Group>;
Index: clang/include/clang/Basic/CodeGenOptions.def
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.def
+++ clang/include/clang/Basic/CodeGenOptions.def
@@ -284,6 +284,8 @@
                                          ///< template parameter descriptions in
                                          ///< forward declarations (versus just
                                          ///< including them in the name).
+CODEGENOPT(DebugUnusedTypes, 1, 0) /// < Whether to emit debug info for types
+                                   /// < that may be unused.
 
 CODEGENOPT(EmitLLVMUseLists, 1, 0) ///< Control whether to serialize use-lists.
 
Index: clang/docs/UsersManual.rst
===================================================================
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -2352,6 +2352,12 @@
 
   Generate complete debug info.
 
+.. option:: -feliminate-unused-debug-types
+
+  By default, Clang does not emit type information for types that are declared
+  but not used in a program. To retain the debug info for these unused types,
+  the negation **-fno-eliminate-unused-debug-types** can be used.
+
 Controlling Macro Debug Info Generation
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
Index: clang/docs/CommandGuide/clang.rst
===================================================================
--- clang/docs/CommandGuide/clang.rst
+++ clang/docs/CommandGuide/clang.rst
@@ -433,6 +433,12 @@
   never emit type information for types that are not referenced at all by the
   program.
 
+.. option:: -feliminate-unused-debug-types
+
+  By default, Clang does not emit type information for types that are declared
+  but not used in a program. To retain the debug info for these unused types,
+  the negation **-fno-eliminate-unused-debug-types** can be used.
+
 .. option:: -fexceptions
 
   Enable generation of unwind information. This allows exceptions to be thrown
Index: clang/docs/ClangCommandLineReference.rst
===================================================================
--- clang/docs/ClangCommandLineReference.rst
+++ clang/docs/ClangCommandLineReference.rst
@@ -2118,6 +2118,10 @@
 
 Emit full debug info for all types used by the program
 
+.. option:: -feliminate-unused-debug-types, -fno-eliminate-unused-debug-types
+
+Emit debug info for types that are unused but declared by the program.
+
 .. option:: -fstrict-aliasing, -fno-strict-aliasing
 
 .. option:: -fstrict-enums, -fno-strict-enums
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to