Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -702,6 +702,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/CodeGenCXX/debug-info-template-member.cpp =================================================================== --- test/CodeGenCXX/debug-info-template-member.cpp +++ test/CodeGenCXX/debug-info-template-member.cpp @@ -34,6 +34,13 @@ // CHECK: [[VIRT_TEMP_PARAM]] = !{[[VIRT_T:![0-9]*]]} // CHECK: [[VIRT_T]] = !DITemplateTypeParameter(name: "T", type: !"_ZTS4elem") +// CHECK: [[ELEM:![0-9]*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "elem" +// CHECK-SAME: elements: [[ELEM_MEM:![0-9]*]] +// CHECK-SAME: identifier: "_ZTS4elem" +// CHECK: [[ELEM_MEM]] = !{[[ELEM_X:![0-9]*]]} +// CHECK: [[ELEM_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !"_ZTS4elem" +// CHECK-SAME: baseType: !"_ZTS4virtI4elemE" + // CHECK: [[C:![0-9]*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "MyClass" // CHECK-SAME: elements: [[C_MEM:![0-9]*]] // CHECK-SAME: vtableHolder: !"_ZTS7MyClass" @@ -43,13 +50,6 @@ // CHECK: [[C_FUNC]] = !DISubprogram(name: "func",{{.*}} line: 7, -// CHECK: [[ELEM:![0-9]*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "elem" -// CHECK-SAME: elements: [[ELEM_MEM:![0-9]*]] -// CHECK-SAME: identifier: "_ZTS4elem" -// CHECK: [[ELEM_MEM]] = !{[[ELEM_X:![0-9]*]]} -// CHECK: [[ELEM_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !"_ZTS4elem" -// CHECK-SAME: baseType: !"_ZTS4virtI4elemE" - // Check that the member function template specialization and implicit special // members (the default ctor) refer to their class by scope, even though they // didn't appear in the class's member list (C_MEM). This prevents the functions