Index: include/clang/Basic/LangOptions.def =================================================================== --- include/clang/Basic/LangOptions.def +++ include/clang/Basic/LangOptions.def @@ -141,6 +141,7 @@ LANGOPT(POSIXThreads , 1, 0, "POSIX thread support") LANGOPT(Blocks , 1, 0, "blocks extension to C") BENIGN_LANGOPT(EmitAllDecls , 1, 0, "emitting all declarations") +BENIGN_LANGOPT(EmitFwdTemplateChildren, 1, 0, "emit template parameter children in forward declarations") LANGOPT(MathErrno , 1, 1, "errno in math functions") BENIGN_LANGOPT(HeinousExtensions , 1, 0, "extensions that we really don't like and may be ripped out at any time") LANGOPT(Modules , 1, 0, "modules extension to C") Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1412,6 +1412,14 @@ HelpText<"Emit macro debug information">; def fno_debug_macro : Flag<["-"], "fno-debug-macro">, Group, Flags<[CoreOption]>, HelpText<"Do not emit macro debug information">; +def fdebug_forward_template_params : Flag<["-"], + "fdebug-forward-template-params">, Group, + Flags<[DriverOption, CC1Option]>, + HelpText<"Debug info describes template parameters in forward declarations">; +def fno_debug_forward_template_params : Flag<["-"], + "fno-debug-forward-template-params">, Group, + Flags<[DriverOption, CC1Option]>, + HelpText<"Debug info omits template parameters in forward declarations">; def fstrict_aliasing : Flag<["-"], "fstrict-aliasing">, Group, Flags<[DriverOption, CoreOption]>; def fstrict_enums : Flag<["-"], "fstrict-enums">, Group, Flags<[CC1Option]>, Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -833,6 +833,10 @@ llvm::DICompositeType *RetTy = DBuilder.createReplaceableCompositeType( getTagForRecord(RD), RDName, Ctx, DefUnit, Line, 0, Size, Align, llvm::DINode::FlagFwdDecl, FullName); + if (CGM.getLangOpts().EmitFwdTemplateChildren) + if (auto *TSpecial = dyn_cast(RD)) + DBuilder.replaceArrays(RetTy, llvm::DINodeArray(), + CollectCXXTemplateParams(TSpecial, DefUnit)); ReplaceMap.emplace_back( std::piecewise_construct, std::make_tuple(Ty), std::make_tuple(static_cast(RetTy))); Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -2969,6 +2969,13 @@ CmdArgs.push_back("-generate-type-units"); } + // Decide how to render forward declarations of template instantiations. + // SCE defaults to on, others default to off. + if (Args.hasFlag(options::OPT_fdebug_forward_template_params, + options::OPT_fno_debug_forward_template_params, + DebuggerTuning == llvm::DebuggerKind::SCE)) + CmdArgs.push_back("-fdebug-forward-template-params"); + RenderDebugInfoCompressionArgs(Args, CmdArgs, D); } Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -2201,6 +2201,7 @@ Opts.EncodeExtendedBlockSig = Args.hasArg(OPT_fencode_extended_block_signature); Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls); + Opts.EmitFwdTemplateChildren = Args.hasArg(OPT_fdebug_forward_template_params); Opts.PackStruct = getLastArgIntValue(Args, OPT_fpack_struct_EQ, 0, Diags); Opts.MaxTypeAlign = getLastArgIntValue(Args, OPT_fmax_type_align_EQ, 0, Diags); Opts.AlignDouble = Args.hasArg(OPT_malign_double); Index: test/CodeGenCXX/debug-info-fwd-template-param.cpp =================================================================== --- test/CodeGenCXX/debug-info-fwd-template-param.cpp +++ test/CodeGenCXX/debug-info-fwd-template-param.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 %s -triple=%itanium_abi_triple -debug-info-kind=limited -fdebug-forward-template-params -emit-llvm -o - | FileCheck --check-prefix=CHILD %s +// RUN: %clang_cc1 %s -triple=%itanium_abi_triple -debug-info-kind=limited -fno-debug-forward-template-params -emit-llvm -o - | FileCheck --check-prefix=NONE %s +// A forward declaration of a template instantiation should have template +// parameter children (if we ask for them). + +template class A { +public: + A(T val); +private: + T x; +}; + +struct B { + A *p; +}; + +B b; + +// CHILD: !DICompositeType(tag: DW_TAG_class_type, name: "A" +// CHILD-SAME: flags: DIFlagFwdDecl +// CHILD-SAME: templateParams: [[PARAM_LIST:![0-9]*]] +// CHILD: [[PARAM_LIST]] = !{[[PARAM:![0-9]*]]} +// CHILD: [[PARAM]] = !DITemplateTypeParameter(name: "T", +// CHILD-SAME: type: [[CTYPE:![0-9]*]] +// CHILD: [[CTYPE]] = !DIDerivedType(tag: DW_TAG_const_type +// CHILD-SAME: baseType: [[BTYPE:![0-9]*]] +// CHILD: [[BTYPE]] = !DIBasicType(name: "int" + +// NONE: !DICompositeType(tag: DW_TAG_class_type, name: "A" +// NONE-SAME: flags: DIFlagFwdDecl +// NONE-NOT: templateParams: +// NONE-SAME: ) Index: test/Driver/clang_f_opts.c =================================================================== --- test/Driver/clang_f_opts.c +++ test/Driver/clang_f_opts.c @@ -495,6 +495,11 @@ // CHECK-PROFILE-DEBUG: -fdebug-info-for-profiling // CHECK-NO-PROFILE-DEBUG-NOT: -fdebug-info-for-profiling +// RUN: %clang -### -S -fdebug-forward-template-params %s 2>&1 | FileCheck -check-prefix=CHECK-FWD-TMPL %s +// RUN: %clang -### -S -fno-debug-forward-template-params %s 2>&1 | FileCheck -check-prefix=CHECK-NO-FWD-TMPL %s +// CHECK-FWD-TMPL: -fdebug-forward-template-params +// CHECK-NO-FWD-TMPL-NOT: -fdebug-forward-template-params + // RUN: %clang -### -S -fallow-editor-placeholders %s 2>&1 | FileCheck -check-prefix=CHECK-ALLOW-PLACEHOLDERS %s // RUN: %clang -### -S -fno-allow-editor-placeholders %s 2>&1 | FileCheck -check-prefix=CHECK-NO-ALLOW-PLACEHOLDERS %s // CHECK-ALLOW-PLACEHOLDERS: -fallow-editor-placeholders