Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -805,6 +805,10 @@ llvm::DICompositeType *RetTy = DBuilder.createReplaceableCompositeType( getTagForRecord(RD), RDName, Ctx, DefUnit, Line, 0, Size, Align, llvm::DINode::FlagFwdDecl, FullName); + if (const ClassTemplateSpecializationDecl *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: test/CodeGenCXX/debug-info-template-fwd-param.cpp =================================================================== --- test/CodeGenCXX/debug-info-template-fwd-param.cpp +++ test/CodeGenCXX/debug-info-template-fwd-param.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -debug-info-kind=limited -emit-llvm -o - | FileCheck %s +// A forward declaration of a template should still have template parameters. + +template class A { +public: + A(T val); +private: + T x; +}; + +struct B { + A *p; +}; + +B b; + +// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "A" +// CHECK-SAME: flags: DIFlagFwdDecl +// CHECK-SAME: templateParams: [[PARAM_LIST:![0-9]*]] +// CHECK: [[PARAM_LIST]] = !{[[PARAM:![0-9]*]]} +// CHECK: [[PARAM]] = !DITemplateTypeParameter(name: "T", +// CHECK-SAME: type: [[CTYPE:![0-9]*]] +// CHECK: [[CTYPE]] = !DIDerivedType(tag: DW_TAG_const_type +// CHECK-SAME: baseType: [[BTYPE:![0-9]*]] +// CHECK: [[BTYPE]] = !DIBasicType(name: "int" Index: test/Modules/ExtDebugInfo.cpp =================================================================== --- test/Modules/ExtDebugInfo.cpp +++ test/Modules/ExtDebugInfo.cpp @@ -93,9 +93,13 @@ // CHECK-SAME: flags: DIFlagFwdDecl, // CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIiNS_6traitsIiEEEE") -// This type isn't, however, even with standalone non-module debug info this -// type is a forward declaration. -// CHECK-NOT: !DICompositeType(tag: DW_TAG_structure_type, name: "traits", +// This type isn't, however, it is a template parameter type and so gets a +// forward declaration. +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, +// CHECK-SAME: name: "traits", +// CHECK-SAME: scope: ![[NS]], +// CHECK-SAME: flags: DIFlagFwdDecl, +// CHECK-SAME: identifier: "_ZTSN8DebugCXX6traitsIiEE") // This one isn't. // CHECK: !DICompositeType(tag: DW_TAG_class_type,