diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/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. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3343,7 +3343,10 @@ defm fcheck_new : BooleanFFlag<"check-new">, Group; defm caller_saves : BooleanFFlag<"caller-saves">, Group; defm reorder_blocks : BooleanFFlag<"reorder-blocks">, Group; -defm eliminate_unused_debug_types : BooleanFFlag<"eliminate-unused-debug-types">, Group; +defm eliminate_unused_debug_types : + BooleanFFlag<"eliminate-unused-debug-types">, Group, + Flags<[CC1Option]>, + HelpText<"Emit debug info for types, even if they may be unreferenced">; defm branch_count_reg : BooleanFFlag<"branch-count-reg">, Group; defm default_inline : BooleanFFlag<"default-inline">, Group; defm fat_lto_objects : BooleanFFlag<"fat-lto-objects">, Group; diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -496,6 +496,9 @@ /// Emit an @import declaration. void EmitImportDecl(const ImportDecl &ID); + /// Eagerly emit Typedef. + void EmitTypedef(const TypedefDecl &TD); + /// Emit C++ namespace alias. llvm::DIImportedEntity *EmitNamespaceAlias(const NamespaceAliasDecl &NA); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -4956,3 +4956,10 @@ return llvm::DINode::FlagAllCallsDescribed; } + +void CGDebugInfo::EmitTypedef(const TypedefDecl &TD) { + QualType QT = CGM.getContext().getTypedefType(&TD); + llvm::DIFile *Unit = getOrCreateFile(TD.getLocation()); + llvm::DIType *Ty = getOrCreateType(QT, Unit); + DBuilder.retainType(Ty); +} diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -5555,6 +5555,12 @@ EmitOMPRequiresDecl(cast(D)); break; + case Decl::Typedef: + if (getCodeGenOpts().DebugUnusedTypes) + if (CGDebugInfo *DI = getModuleDebugInfo()) + DI->EmitTypedef(*cast(D)); + 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 diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5190,6 +5190,8 @@ // Forward -f (flag) options which we can pass directly. Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls); + Args.AddLastArg(CmdArgs, options::OPT_eliminate_unused_debug_types_f); + Args.AddLastArg(CmdArgs, options::OPT_eliminate_unused_debug_types_fno); 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); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/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_eliminate_unused_debug_types_fno); Opts.EmbedSource = Args.hasArg(OPT_gembed_source); Opts.ForceDwarfFrameSection = Args.hasArg(OPT_fforce_dwarf_frame); diff --git a/clang/test/CodeGen/debug-info-unused-types.c b/clang/test/CodeGen/debug-info-unused-types.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/debug-info-unused-types.c @@ -0,0 +1,11 @@ +// 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; +// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "my_int", file: !5, line: 5, baseType: !6) +// CHECK-NEXT: !5 = !DIFile(filename: "clang/test/CodeGen/debug-info-unused-types.c", directory: "/android0/llvm-project") +// CHECK-NEXT: !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +// NODBG-NOT: !DIDerivedType(tag: DW_TAG_typedef, name: "my_int", file: !5, line: 5, baseType: !6) +// NODBG-NOT: !5 = !DIFile(filename: "clang/test/CodeGen/debug-info-unused-types.c", directory: "/android0/llvm-project") +// NODBG-NOT: !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)