Force column info to be generated for call expressions so we can

differentiate multiple inlined call sites on the same line
in the debug info.

Fixes rdar://problem/13036237

llvm-svn: 176895
This commit is contained in:
Adrian Prantl 2013-03-12 20:43:25 +00:00
parent 061dabf7df
commit c782242a12
4 changed files with 90 additions and 15 deletions

View File

@ -262,9 +262,9 @@ unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) {
}
/// getColumnNumber - Get column number for the location.
unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc) {
unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc, bool Force) {
// We may not want column information at all.
if (!CGM.getCodeGenOpts().DebugColumnInfo)
if (!Force && !CGM.getCodeGenOpts().DebugColumnInfo)
return 0;
// If the location is invalid then use the current column.
@ -2291,7 +2291,8 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
/// EmitLocation - Emit metadata to indicate a change in line/column
/// information in the source file.
void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) {
void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc,
bool ForceColumnInfo) {
// Update our current location
setLocation(Loc);
@ -2312,8 +2313,9 @@ void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) {
PrevLoc = CurLoc;
llvm::MDNode *Scope = LexicalBlockStack.back();
Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(getLineNumber(CurLoc),
getColumnNumber(CurLoc),
Builder.SetCurrentDebugLocation(llvm::DebugLoc::get
(getLineNumber(CurLoc),
getColumnNumber(CurLoc, ForceColumnInfo),
Scope));
}

View File

@ -207,7 +207,9 @@ public:
/// EmitLocation - Emit metadata to indicate a change in line/column
/// information in the source file.
void EmitLocation(CGBuilderTy &Builder, SourceLocation Loc);
/// \param ForceColumnInfo Assume DebugColumnInfo option is true.
void EmitLocation(CGBuilderTy &Builder, SourceLocation Loc,
bool ForceColumnInfo = false);
/// EmitFunctionStart - Emit a call to llvm.dbg.function.start to indicate
/// start of a new function.
@ -356,7 +358,8 @@ private:
/// getColumnNumber - Get column number for the location. If location is
/// invalid then use current location.
unsigned getColumnNumber(SourceLocation Loc);
/// \param Force Assume DebugColumnInfo option is true.
unsigned getColumnNumber(SourceLocation Loc, bool Force=false);
};
} // namespace CodeGen
} // namespace clang

View File

@ -2849,8 +2849,12 @@ RValue CodeGenFunction::EmitRValueForField(LValue LV,
RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
ReturnValueSlot ReturnValue) {
if (CGDebugInfo *DI = getDebugInfo())
DI->EmitLocation(Builder, E->getLocStart());
if (CGDebugInfo *DI = getDebugInfo()) {
SourceLocation Loc = E->getLocStart();
DI->EmitLocation(Builder, Loc,
/* Force column info to be generated so we can differentiate
multiple call sites on the same line in the debug info. */ true);
}
// Builtins never have block type.
if (E->getCallee()->getType()->isBlockPointerType())

View File

@ -0,0 +1,66 @@
// RUN: %clang_cc1 -g -emit-obj -o %t %s
// RUN: llvm-dwarfdump %t | FileCheck %s
// In the attached test case a post-r166236 clang coalesces two
// instances of an inlined function in a way that makes it appear as
// if the function was only inlined once.
#define INLINE inline __attribute__((always_inline))
INLINE int
product (int x, int y)
{
int result = x * y;
return result;
}
INLINE int
sum (int a, int b)
{
int result = a + b;
return result;
}
int
strange_max (int m, int n)
{
if (m > n)
return m;
else if (n > m)
return n;
else
return 0;
}
int
foo (int i, int j)
{
if (strange_max (i, j) == i)
return product (i, j);
else if (strange_max (i, j) == j)
return sum (i, j);
else
return product (sum (i, i), sum (j, j));
}
int
main(int argc, char const *argv[])
{
int array[3];
array[0] = foo (1238, 78392);
array[1] = foo (379265, 23674);
array[2] = foo (872934, 234);
return 0;
}
// CHECK: DW_TAG_inlined_subroutine
// CHECK: DW_TAG_inlined_subroutine
// CHECK: DW_TAG_inlined_subroutine
// CHECK: DW_TAG_inlined_subroutine
// CHECK-NOT: DW_TAG_inlined_subroutine
// CHECK: DW_AT_call_line {{.*}} (0x2a)
// CHECK: DW_TAG_inlined_subroutine
// CHECK-NOT: DW_TAG_inlined_subroutine
// CHECK: DW_AT_call_line {{.*}} (0x2a)