From: Eric Christopher Date: Tue, 13 Mar 2012 23:40:48 +0000 (+0000) Subject: When adding member functions to a class add any specializations of X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3b10cfe6b804cef041ddf85854d2d536f7a82cb6;p=clang When adding member functions to a class add any specializations of function templates as well. A future commit will mangle the added name with the template args like classes are mangled. Fixes rdar://10986010 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152683 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index bd37197ae3..d88f24339a 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -831,7 +831,7 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, = getOrCreateType(QualType(Method->getType()->getAs(), 0), Unit); - + // Add "this" pointer. llvm::DIArray Args = llvm::DICompositeType(FnTy).getTypeArray(); assert (Args.getNumElements() && "Invalid number of arguments!"); @@ -946,14 +946,16 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method, } if (Method->hasPrototype()) Flags |= llvm::DIDescriptor::FlagPrototyped; - + + llvm::DIArray TParamsArray = CollectFunctionTemplateParams(Method, Unit); llvm::DISubprogram SP = DBuilder.createMethod(RecordTy, MethodName, MethodLinkageName, MethodDefUnit, MethodLine, MethodTy, /*isLocalToUnit=*/false, /* isDefinition=*/ false, Virtuality, VIndex, ContainingType, - Flags, CGM.getLangOpts().Optimize); + Flags, CGM.getLangOpts().Optimize, NULL, + TParamsArray); SPCache[Method->getCanonicalDecl()] = llvm::WeakVH(SP); @@ -967,14 +969,25 @@ void CGDebugInfo:: CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit, SmallVectorImpl &EltTys, llvm::DIType RecordTy) { - for(CXXRecordDecl::method_iterator I = RD->method_begin(), - E = RD->method_end(); I != E; ++I) { - const CXXMethodDecl *Method = *I; - - if (Method->isImplicit() && !Method->isUsed()) + + // Since we want more than just the individual member decls if we + // have templated functions iterate over every declaration to gather + // the functions. + for(DeclContext::decl_iterator I = RD->decls_begin(), + E = RD->decls_end(); I != E; ++I) { + Decl *D = *I; + if (D->isImplicit() && !D->isUsed()) continue; - EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy)); + if (const CXXMethodDecl *Method = dyn_cast(D)) + EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy)); + else if (FunctionTemplateDecl *FTD = dyn_cast(D)) + for (FunctionTemplateDecl::spec_iterator SI = FTD->spec_begin(), + SE = FTD->spec_end(); SI != SE; ++SI) { + FunctionDecl *FD = *SI; + if (CXXMethodDecl *M = dyn_cast(FD)) + EltTys.push_back(CreateCXXMemberFunction(M, Unit, RecordTy)); + } } } diff --git a/test/CodeGenCXX/debug-info-template-member.cpp b/test/CodeGenCXX/debug-info-template-member.cpp new file mode 100644 index 0000000000..c272dd4dd2 --- /dev/null +++ b/test/CodeGenCXX/debug-info-template-member.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s + +class MyClass +{ +public: + int add2(int j) + { + return add<2>(j); + } +private: + template int add(int j) + { + return i + j; + } +}; + +MyClass m; + +// CHECK: metadata !{i32 {{.*}}, null, metadata !"MyClass", metadata {{.*}}, i32 {{.*}}, i64 8, i64 8, i32 0, i32 0, null, metadata [[C_MEM:.*]], i32 0, null, null} ; [ DW_TAG_class_type ] +// CHECK: [[C_MEM]] = metadata !{metadata {{.*}}, metadata [[C_TEMP:.*]], metadata {{.*}}} +// CHECK: [[C_TEMP]] = metadata !{i32 {{.*}}, i32 0, metadata {{.*}}, metadata !"add", metadata !"add", metadata !"_ZN7MyClass3addILi2EEEii", metadata {{.*}}