From 35178dc09d97bb2e0612813def09833866e3ad82 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Sat, 22 Jun 2013 18:59:18 +0000 Subject: [PATCH] DebugInfo: Support (using GNU extensions) for template template parameters and parameter packs git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184644 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/TypePrinter.cpp | 7 ++-- lib/CodeGen/CGDebugInfo.cpp | 42 ++++++++++++------- lib/CodeGen/CGDebugInfo.h | 2 +- test/CXX/temp/temp.decls/temp.variadic/p2.cpp | 2 +- test/CodeGenCXX/debug-info-template.cpp | 37 ++++++++-------- 5 files changed, 52 insertions(+), 38 deletions(-) diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 56a66f1efc..2c439128f2 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -1281,18 +1281,19 @@ TemplateSpecializationType::PrintTemplateArgumentList( bool needSpace = false; for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { - if (Arg > 0) - OS << ", "; - // Print the argument into a string. SmallString<128> Buf; llvm::raw_svector_ostream ArgOS(Buf); if (Args[Arg].getKind() == TemplateArgument::Pack) { + if (Args[Arg].pack_size() && Arg > 0) + OS << ", "; PrintTemplateArgumentList(ArgOS, Args[Arg].pack_begin(), Args[Arg].pack_size(), Policy, true); } else { + if (Arg > 0) + OS << ", "; Args[Arg].print(Policy, ArgOS); } StringRef ArgString = ArgOS.str(); diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index da40fbc2b5..fd75a9a3a3 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -1176,24 +1176,26 @@ CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit, /// CollectTemplateParams - A helper function to collect template parameters. llvm::DIArray CGDebugInfo:: CollectTemplateParams(const TemplateParameterList *TPList, - const TemplateArgumentList &TAList, + ArrayRef TAList, llvm::DIFile Unit) { SmallVector TemplateParams; for (unsigned i = 0, e = TAList.size(); i != e; ++i) { const TemplateArgument &TA = TAList[i]; - const NamedDecl *ND = TPList->getParam(i); + StringRef Name; + if (TPList) + Name = TPList->getParam(i)->getName(); switch (TA.getKind()) { case TemplateArgument::Type: { llvm::DIType TTy = getOrCreateType(TA.getAsType(), Unit); llvm::DITemplateTypeParameter TTP = - DBuilder.createTemplateTypeParameter(TheCU, ND->getName(), TTy); + DBuilder.createTemplateTypeParameter(TheCU, Name, TTy); TemplateParams.push_back(TTP); } break; case TemplateArgument::Integral: { llvm::DIType TTy = getOrCreateType(TA.getIntegralType(), Unit); llvm::DITemplateValueParameter TVP = DBuilder.createTemplateValueParameter( - TheCU, ND->getName(), TTy, + TheCU, Name, TTy, llvm::ConstantInt::get(CGM.getLLVMContext(), TA.getAsIntegral())); TemplateParams.push_back(TVP); } break; @@ -1231,7 +1233,7 @@ CollectTemplateParams(const TemplateParameterList *TPList, cast(T.getTypePtr()), chars); } llvm::DITemplateValueParameter TVP = - DBuilder.createTemplateValueParameter(TheCU, ND->getName(), TTy, V); + DBuilder.createTemplateValueParameter(TheCU, Name, TTy, V); TemplateParams.push_back(TVP); } break; case TemplateArgument::NullPtr: { @@ -1252,16 +1254,24 @@ CollectTemplateParams(const TemplateParameterList *TPList, if (!V) V = llvm::ConstantInt::get(CGM.Int8Ty, 0); llvm::DITemplateValueParameter TVP = - DBuilder.createTemplateValueParameter(TheCU, ND->getName(), TTy, V); + DBuilder.createTemplateValueParameter(TheCU, Name, TTy, V); + TemplateParams.push_back(TVP); + } break; + case TemplateArgument::Template: { + llvm::DITemplateValueParameter TVP = + DBuilder.createTemplateTemplateParameter( + TheCU, Name, llvm::DIType(), + TA.getAsTemplate().getAsTemplateDecl() + ->getQualifiedNameAsString()); + TemplateParams.push_back(TVP); + } break; + case TemplateArgument::Pack: { + llvm::DITemplateValueParameter TVP = + DBuilder.createTemplateParameterPack( + TheCU, Name, llvm::DIType(), + CollectTemplateParams(NULL, TA.getPackAsArray(), Unit)); TemplateParams.push_back(TVP); } break; - case TemplateArgument::Template: - // We could support this with the GCC extension - // DW_TAG_GNU_template_template_param - break; - case TemplateArgument::Pack: - // And this with DW_TAG_GNU_template_parameter_pack - break; // And the following should never occur: case TemplateArgument::Expression: case TemplateArgument::TemplateExpansion: @@ -1282,8 +1292,8 @@ CollectFunctionTemplateParams(const FunctionDecl *FD, llvm::DIFile Unit) { const TemplateParameterList *TList = FD->getTemplateSpecializationInfo()->getTemplate() ->getTemplateParameters(); - return - CollectTemplateParams(TList, *FD->getTemplateSpecializationArgs(), Unit); + return CollectTemplateParams( + TList, FD->getTemplateSpecializationArgs()->asArray(), Unit); } return llvm::DIArray(); } @@ -1301,7 +1311,7 @@ CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TSpecial, PU.get()->getTemplateParameters() : PU.get()->getTemplateParameters(); const TemplateArgumentList &TAList = TSpecial->getTemplateInstantiationArgs(); - return CollectTemplateParams(TPList, TAList, Unit); + return CollectTemplateParams(TPList, TAList.asArray(), Unit); } /// getOrCreateVTablePtrType - Return debug info descriptor for vtable. diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 4603b9c606..ddd4f0b1df 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -166,7 +166,7 @@ class CGDebugInfo { llvm::DIArray CollectTemplateParams(const TemplateParameterList *TPList, - const TemplateArgumentList &TAList, + ArrayRef TAList, llvm::DIFile Unit); llvm::DIArray CollectFunctionTemplateParams(const FunctionDecl *FD, llvm::DIFile Unit); diff --git a/test/CXX/temp/temp.decls/temp.variadic/p2.cpp b/test/CXX/temp/temp.decls/temp.variadic/p2.cpp index ce19582c22..e7a62366a9 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/p2.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/p2.cpp @@ -12,7 +12,7 @@ void test() { template void recurse_until_fail(const Head &, const Tail &...tail) { // expected-note{{candidate function template not viable: requires at least 1 argument, but 0 were provided}} recurse_until_fail(tail...); // expected-error{{no matching function for call to 'recurse_until_fail'}} \ - // expected-note{{in instantiation of function template specialization 'recurse_until_fail' requested here}} \ + // expected-note{{in instantiation of function template specialization 'recurse_until_fail' requested here}} \ // expected-note{{in instantiation of function template specialization 'recurse_until_fail' requested here}} } diff --git a/test/CodeGenCXX/debug-info-template.cpp b/test/CodeGenCXX/debug-info-template.cpp index a97c991f38..da58f9e6c8 100644 --- a/test/CodeGenCXX/debug-info-template.cpp +++ b/test/CodeGenCXX/debug-info-template.cpp @@ -2,18 +2,11 @@ // CHECK: [[EMPTY:![0-9]*]] = metadata !{i32 0} -// CHECK: [[FUNTYPE:![0-9]*]] = {{.*}}, metadata [[FUNARGS:![0-9]*]], i32 0, i32 0} ; [ DW_TAG_subroutine_type ] -// CHECK: [[FUNARGS]] = metadata !{null} - -// func<...> doesn't have any template arguments listed since we don't support -// packs yet. This could be encoded with GNU's -// DW_TAG_GNU_template_parameter_pack extension. -// CHECK: {{.*}}, metadata [[EMPTY]], i32 {{[0-9]*}}} ; [ DW_TAG_subprogram ] {{.*}} [func] // CHECK: [[INT:![0-9]*]] = {{.*}} ; [ DW_TAG_base_type ] [int] // CHECK: metadata [[TCI:![0-9]*]], i32 0, i32 1, %class.TC* @tci, null} ; [ DW_TAG_variable ] [tci] -// CHECK: [[TC:![0-9]*]] = {{.*}}, metadata [[TCARGS:![0-9]*]]} ; [ DW_TAG_class_type ] [TC] -// CHECK: [[TCARGS]] = metadata !{metadata [[TCARG1:![0-9]*]], metadata [[TCARG2:![0-9]*]], metadata [[TCARG3:![0-9]*]], metadata [[TCARG4:![0-9]*]], metadata [[TCARG5:![0-9]*]], metadata [[TCARG6:![0-9]*]]} +// CHECK: [[TC:![0-9]*]] = {{.*}}, metadata [[TCARGS:![0-9]*]]} ; [ DW_TAG_class_type ] [TC] +// CHECK: [[TCARGS]] = metadata !{metadata [[TCARG1:![0-9]*]], metadata [[TCARG2:![0-9]*]], metadata [[TCARG3:![0-9]*]], metadata [[TCARG4:![0-9]*]], metadata [[TCARG5:![0-9]*]], metadata [[TCARG6:![0-9]*]], metadata [[TCARG7:![0-9]*]], metadata [[TCARG8:![0-9]*]]} // // We seem to be missing file/line/col info on template value parameters - // metadata supports it but it's not populated. GCC doesn't emit it either, @@ -43,12 +36,20 @@ // CHECK: [[TCARG5]] = {{.*}}metadata !"b", metadata [[MEMFUNPTR:![0-9]*]], { i64, i64 } { i64 ptrtoint (void (%struct.foo*)* @_ZN3foo1fEv to i64), i64 0 }, {{.*}} ; [ DW_TAG_template_value_parameter ] // CHECK: [[MEMFUNPTR]] = {{.*}}, metadata [[FTYPE]], metadata [[FOO]]} ; [ DW_TAG_ptr_to_member_type ] // CHECK: [[TCARG6]] = {{.*}}metadata !"f", metadata [[FUNPTR:![0-9]*]], void ()* @_Z4funcv, {{.*}} ; [ DW_TAG_template_value_parameter ] -// CHECK: [[FUNPTR]] = {{.*}}, metadata [[FUNTYPE]]} ; [ DW_TAG_pointer_type ] +// CHECK: [[FUNPTR]] = {{.*}}, metadata [[FUNTYPE:![0-9]*]]} ; [ DW_TAG_pointer_type ] +// CHECK: [[FUNTYPE]] = {{.*}}, metadata [[FUNARGS:![0-9]*]], i32 0, i32 0} ; [ DW_TAG_subroutine_type ] +// CHECK: [[FUNARGS]] = metadata !{null} +// CHECK: [[TCARG7]] = {{.*}}metadata !"tmpl", null, metadata !"tmpl_impl", {{.*}} ; [ DW_TAG_GNU_template_template_param ] +// CHECK: [[TCARG8]] = {{.*}}metadata !"Is", null, metadata [[TCARG8_VALS:![0-9]*]], {{.*}} ; [ DW_TAG_GNU_template_parameter_pack ] +// CHECK: [[TCARG8_VALS]] = metadata !{metadata [[TCARG8_1:![0-9]*]], metadata [[TCARG8_2:![0-9]*]], metadata [[TCARG8_3:![0-9]*]]} +// CHECK: [[TCARG8_1]] = {{.*}}metadata !"", metadata [[INT]], i32 1, {{.*}} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[TCARG8_2]] = {{.*}}metadata !"", metadata [[INT]], i32 2, {{.*}} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[TCARG8_3]] = {{.*}}metadata !"", metadata [[INT]], i32 3, {{.*}} ; [ DW_TAG_template_value_parameter ] // CHECK: metadata [[TCNT:![0-9]*]], i32 0, i32 1, %class.TC.0* @tcn, null} ; [ DW_TAG_variable ] [tcn] -// CHECK: [[TCNT:![0-9]*]] = {{.*}}, metadata [[TCNARGS:![0-9]*]]} ; [ DW_TAG_class_type ] [TC] -// CHECK: [[TCNARGS]] = metadata !{metadata [[TCNARG1:![0-9]*]], metadata [[TCNARG2:![0-9]*]], metadata [[TCNARG3:![0-9]*]], metadata [[TCNARG4:![0-9]*]], metadata [[TCNARG5:![0-9]*]], metadata [[TCNARG6:![0-9]*]]} +// CHECK: [[TCNT:![0-9]*]] = {{.*}}, metadata [[TCNARGS:![0-9]*]]} ; [ DW_TAG_class_type ] [TC] +// CHECK: [[TCNARGS]] = metadata !{metadata [[TCNARG1:![0-9]*]], metadata [[TCNARG2:![0-9]*]], metadata [[TCNARG3:![0-9]*]], metadata [[TCNARG4:![0-9]*]], metadata [[TCNARG5:![0-9]*]], metadata [[TCNARG6:![0-9]*]], metadata [[TCARG7:![0-9]*]], metadata [[TCNARG8:![0-9]*]]} // CHECK: [[TCNARG1]] = {{.*}}metadata !"T", metadata [[INT]], {{.*}} ; [ DW_TAG_template_type_parameter ] // CHECK: [[TCNARG2]] = {{.*}}metadata !"", metadata [[INT]], i32 -3, {{.*}} ; [ DW_TAG_template_value_parameter ] // CHECK: [[TCNARG3]] = {{.*}}metadata !"x", metadata [[INTPTR]], i8 0, {{.*}} ; [ DW_TAG_template_value_parameter ] @@ -66,21 +67,23 @@ // // CHECK: [[TCNARG5]] = {{.*}}metadata !"b", metadata [[MEMFUNPTR]], i8 0, {{.*}} ; [ DW_TAG_template_value_parameter ] // CHECK: [[TCNARG6]] = {{.*}}metadata !"f", metadata [[FUNPTR]], i8 0, {{.*}} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[TCNARG8]] = {{.*}}metadata !"Is", null, metadata [[EMPTY]], {{.*}} ; [ DW_TAG_GNU_template_parameter_pack ] struct foo { char pad[8]; // make the member pointer to 'e' a bit more interesting (nonzero) int e; void f(); }; -template +template class tmpl, int ...Is> class TC { }; int glb; void func(); -TC tci; -TC tcn; +template +struct tmpl_impl { +}; -template int func() { return 0; } -int anchor = func(); +TC tci; +TC tcn; -- 2.40.0