nickdesaulniers updated this revision to Diff 267970.
nickdesaulniers added a comment.
- add documentation
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/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
Index: clang/test/CodeGen/debug-info-unused-types.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/debug-info-unused-types.cpp
@@ -0,0 +1,19 @@
+// 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 };
+
+// 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: !5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+// CHECK: !7 = !DIEnumerator(name: "BAZ", value: 0)
+// CHECK: !9 = !DIDerivedType(tag: DW_TAG_typedef, name: "foo", file: !4, line: 5, baseType: !5)
+// CHECK: !10 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "bar", file: !4, line: 6, size: 8, flags: DIFlagTypePassByValue, elements: !11, identifier: "_ZTS3bar")
+
+// 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: !5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+// NODBG-NOT: !7 = !DIEnumerator(name: "BAZ", value: 0)
+// NODBG-NOT: !9 = !DIDerivedType(tag: DW_TAG_typedef, name: "foo", file: !4, line: 5, baseType: !5)
+// NODBG-NOT: !10 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "bar", file: !4, line: 6, size: 8, flags: DIFlagTypePassByValue, elements: !11, identifier: "_ZTS3bar")
Index: clang/test/CodeGen/debug-info-unused-types.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/debug-info-unused-types.c
@@ -0,0 +1,30 @@
+// 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 {};
+
+// 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: !5 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+// CHECK: !7 = !DIEnumerator(name: "BAR", value: 0, isUnsigned: true)
+// CHECK: !9 = !DIDerivedType(tag: DW_TAG_typedef, name: "my_int", file: !4, line: 5, baseType: !10)
+// CHECK: !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+// CHECK: !11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo", file: !4, line: 6, elements: !12)
+// CHECK: !13 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "baz", file: !4, line: 8, 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.
+
+// NODBG-NOT: !3 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "bar", file: !4, line: 7, baseType: !5, size: 32, elements: !6)
+// NODBG-NOT: !5 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+// NODBG-NOT: !7 = !DIEnumerator(name: "BAR", value: 0, isUnsigned: true)
+// NODBG-NOT: !9 = !DIDerivedType(tag: DW_TAG_typedef, name: "my_int", file: !4, line: 5, baseType: !10)
+// NODBG-NOT: !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+// NODBG-NOT: !11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo", file: !4, line: 6, elements: !12)
+// NODBG-NOT: !13 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "baz", file: !4, line: 8, 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
@@ -5145,6 +5145,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);
+ Args.AddLastArg(CmdArgs, 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
@@ -5370,16 +5370,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:
@@ -5565,6 +5570,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/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -3343,7 +3343,10 @@
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 eliminate_unused_debug_types :
+ BooleanFFlag<"eliminate-unused-debug-types">, Group<f_Group>,
+ Flags<[CC1Option]>,
+ HelpText<"Emit debug info for types, even if they may be unreferenced">;
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
@@ -288,6 +288,8 @@
///< template parameter descriptions in
///< forward declarations (versus just
///< including them in the name).
+CODEGENOPT(DebugUnusedTypes, 1, 0) /// < Whether to emit typedefs 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
@@ -2314,6 +2314,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
@@ -2114,6 +2114,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 defined by the program.
+
.. option:: -fstrict-aliasing, -fno-strict-aliasing
.. option:: -fstrict-enums, -fno-strict-enums
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits