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