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 aa66449..492429e 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -764,7 +764,7 @@
// 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 @@
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<FunctionDecl>(D);
+ if (!FD) return llvm::DISubprogram();
+
+ // Setup context.
+ getContextDescriptor(cast<Decl>(D->getDeclContext()));
+
+ for (FunctionDecl::redecl_iterator I = FD->redecls_begin(),
+ E = FD->redecls_end(); I != E; ++I) {
+ const FunctionDecl *NextFD = *I;
+ llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
+ MI = SPCache.find(NextFD);
+ if (MI != SPCache.end()) {
+ llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(&*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 @@
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 f806f63..af00c2f 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -258,6 +258,10 @@
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 0000000..31f6663
--- /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);
+}