From: Devang Patel Date: Sat, 23 Apr 2011 00:08:01 +0000 (+0000) Subject: Tie debug information for method declaration with debug information for method defini... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=120bf32525829be4622fc85b67e38b2ff0276744;p=clang Tie debug information for method declaration with debug information for method definition. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130037 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index aa664491fc..492429ed9a 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -764,7 +764,7 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method, // Don't cache ctors or dtors since we have to emit multiple functions for // a single ctor or dtor. - if (!IsCtorOrDtor && Method->isThisDeclarationADefinition()) + if (!IsCtorOrDtor) SPCache[Method] = llvm::WeakVH(SP); return SP; @@ -1579,6 +1579,29 @@ llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType, return Ty; } +/// getFunctionDeclaration - Return debug info descriptor to describe method +/// declaration for the given method definition. +llvm::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) { + const FunctionDecl *FD = dyn_cast(D); + if (!FD) return llvm::DISubprogram(); + + // Setup context. + getContextDescriptor(cast(D->getDeclContext())); + + for (FunctionDecl::redecl_iterator I = FD->redecls_begin(), + E = FD->redecls_end(); I != E; ++I) { + const FunctionDecl *NextFD = *I; + llvm::DenseMap::iterator + MI = SPCache.find(NextFD); + if (MI != SPCache.end()) { + llvm::DISubprogram SP(dyn_cast_or_null(&*MI->second)); + if (SP.isSubprogram() && !llvm::DISubprogram(SP).isDefinition()) + return SP; + } + } + return llvm::DISubprogram(); +} + /// EmitFunctionStart - Constructs the debug code for entering a function - /// "llvm.dbg.func.start.". void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, @@ -1639,12 +1662,14 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, unsigned LineNo = getLineNumber(CurLoc); if (D->isImplicit()) Flags |= llvm::DIDescriptor::FlagArtificial; + llvm::DIType SPTy = getOrCreateType(FnType, Unit); + llvm::DISubprogram SPDecl = getFunctionDeclaration(D); llvm::DISubprogram SP = DBuilder.createFunction(FDContext, Name, LinkageName, Unit, - LineNo, getOrCreateType(FnType, Unit), + LineNo, SPTy, Fn->hasInternalLinkage(), true/*definition*/, Flags, CGM.getLangOptions().Optimize, Fn, - TParamsArray); + TParamsArray, SPDecl); // Push function on region stack. llvm::MDNode *SPN = SP; diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index f806f630b9..af00c2f84f 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -258,6 +258,10 @@ private: llvm::DIType CreateMemberType(llvm::DIFile Unit, QualType FType, llvm::StringRef Name, uint64_t *Offset); + /// getFunctionDeclaration - Return debug info descriptor to describe method + /// declaration for the given method definition. + llvm::DISubprogram getFunctionDeclaration(const Decl *D); + /// getFunctionName - Get function name for the given FunctionDecl. If the /// name is constructred on demand (e.g. C++ destructor) then the name /// is stored on the side. diff --git a/test/CodeGenCXX/debug-info-method-spec.cpp b/test/CodeGenCXX/debug-info-method-spec.cpp new file mode 100644 index 0000000000..31f66633dc --- /dev/null +++ b/test/CodeGenCXX/debug-info-method-spec.cpp @@ -0,0 +1,10 @@ +// RUN: %clang -fverbose-asm -cc1 -g -S %s -o - | grep DW_AT_specification +// Radar 9254491 +class A { +public: + void doSomething(int i) { ++i; } +}; + +void foo(A *a) { + a->doSomething(2); +}