summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Blaikie <dblaikie@gmail.com>2015-01-09 23:00:28 +0000
committerDavid Blaikie <dblaikie@gmail.com>2015-01-09 23:00:28 +0000
commita740b903f87b8dd60860caea7973f5f4fdd91638 (patch)
treedd0800033ba1b4da18ba88beb296c606c5636ef7
parentad1cfd9132b6e901894033bca777f456c822af39 (diff)
Revert "DebugInfo: Generalize debug info location handling" and related commits
This reverts commit r225000, r225021, r225083, r225086, r225090. The root change (r225000) still has several issues where it's caused calls to be emitted without debug locations. This causes assertion failures if/when those calls are inlined. I'll work up some test cases and fixes before recommitting this. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@225555 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/CGBlocks.cpp12
-rw-r--r--lib/CodeGen/CGClass.cpp18
-rw-r--r--lib/CodeGen/CGCleanup.cpp5
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp83
-rw-r--r--lib/CodeGen/CGDebugInfo.h39
-rw-r--r--lib/CodeGen/CGDecl.cpp17
-rw-r--r--lib/CodeGen/CGDeclCXX.cpp8
-rw-r--r--lib/CodeGen/CGException.cpp4
-rw-r--r--lib/CodeGen/CGExpr.cpp37
-rw-r--r--lib/CodeGen/CGExprCXX.cpp15
-rw-r--r--lib/CodeGen/CGExprComplex.cpp22
-rw-r--r--lib/CodeGen/CGExprScalar.cpp3
-rw-r--r--lib/CodeGen/CGStmt.cpp4
-rw-r--r--lib/CodeGen/CGStmtOpenMP.cpp4
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp23
-rw-r--r--lib/CodeGen/CodeGenFunction.h32
-rw-r--r--test/CodeGenCXX/PR20038.cpp8
-rw-r--r--test/CodeGenCXX/debug-info-line.cpp30
-rw-r--r--test/CodeGenCXX/debug-info-scope.cpp12
19 files changed, 220 insertions, 156 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index be6d8d849b..bdb3eaf549 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -874,7 +874,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// locations of subexpressions in the initialization.
EmitExprAsInit(&l2r, &blockFieldPseudoVar,
MakeAddrLValue(blockField, type, align),
- /*captured by init*/ false);
+ /*captured by init*/ false, SourceLocation());
}
// Activate the cleanup if layout pushed one.
@@ -1175,7 +1175,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
Alloca->setAlignment(Align);
// Set the DebugLocation to empty, so the store is recognized as a
// frame setup instruction by llvm::DwarfDebug::beginFunction().
- ApplyDebugLocation NL(*this);
+ NoLocation NL(*this, Builder);
Builder.CreateAlignedStore(BlockPointer, Alloca, Align);
BlockPointerDbgLoc = Alloca;
}
@@ -1326,9 +1326,9 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
false,
false);
// Create a scope with an artificial location for the body of this function.
- ApplyDebugLocation NL(*this);
+ ArtificialLocation AL(*this, Builder);
StartFunction(FD, C.VoidTy, Fn, FI, args);
- ArtificialLocation AL(*this);
+ AL.Emit();
llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
@@ -1497,9 +1497,9 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
nullptr, SC_Static,
false, false);
// Create a scope with an artificial location for the body of this function.
- ApplyDebugLocation NL(*this);
+ ArtificialLocation AL(*this, Builder);
StartFunction(FD, C.VoidTy, Fn, FI, args);
- ArtificialLocation AL(*this);
+ AL.Emit();
llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 92c694a76d..5ffab603ac 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -544,7 +544,6 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
CXXCtorInitializer *MemberInit,
const CXXConstructorDecl *Constructor,
FunctionArgList &Args) {
- ApplyDebugLocation Loc(CGF, MemberInit->getMemberLocation());
assert(MemberInit->isAnyMemberInitializer() &&
"Must have member initializer!");
assert(MemberInit->getInit() && "Must have initializer!");
@@ -598,25 +597,26 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
ArrayRef<VarDecl *> ArrayIndexes;
if (MemberInit->getNumArrayIndices())
ArrayIndexes = MemberInit->getArrayIndexes();
- ApplyDebugLocation DL(CGF, MemberInit->getMemberLocation());
- CGF.EmitInitializerForField(Field, LHS, MemberInit->getInit(), ArrayIndexes);
+ CGF.EmitInitializerForField(Field, LHS, MemberInit->getInit(), ArrayIndexes,
+ MemberInit->getMemberLocation());
}
-void CodeGenFunction::EmitInitializerForField(
- FieldDecl *Field, LValue LHS, Expr *Init,
- ArrayRef<VarDecl *> ArrayIndexes) {
+void CodeGenFunction::EmitInitializerForField(FieldDecl *Field, LValue LHS,
+ Expr *Init,
+ ArrayRef<VarDecl *> ArrayIndexes,
+ SourceLocation DbgLoc) {
QualType FieldType = Field->getType();
switch (getEvaluationKind(FieldType)) {
case TEK_Scalar:
if (LHS.isSimple()) {
- EmitExprAsInit(Init, Field, LHS, false);
+ EmitExprAsInit(Init, Field, LHS, false, DbgLoc);
} else {
RValue RHS = RValue::get(EmitScalarExpr(Init));
EmitStoreThroughLValue(RHS, LHS);
}
break;
case TEK_Complex:
- EmitComplexExprIntoLValue(Init, LHS, /*isInit*/ true);
+ EmitComplexExprIntoLValue(Init, LHS, /*isInit*/ true, DbgLoc);
break;
case TEK_Aggregate: {
llvm::Value *ArrayIndexVar = nullptr;
@@ -783,6 +783,8 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {
// delegation optimization.
if (CtorType == Ctor_Complete && IsConstructorDelegationValid(Ctor) &&
CGM.getTarget().getCXXABI().hasConstructorVariants()) {
+ if (CGDebugInfo *DI = getDebugInfo())
+ DI->EmitLocation(Builder, Ctor->getLocEnd());
EmitDelegateCXXConstructorCall(Ctor, Ctor_Base, Args, Ctor->getLocEnd());
return;
}
diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp
index 18ed3e543d..d81e3a597b 100644
--- a/lib/CodeGen/CGCleanup.cpp
+++ b/lib/CodeGen/CGCleanup.cpp
@@ -861,7 +861,10 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
// Emit the EH cleanup if required.
if (RequiresEHCleanup) {
- ApplyDebugLocation AutoRestoreLocation(*this, CurEHLocation);
+ CGDebugInfo *DI = getDebugInfo();
+ SaveAndRestoreLocation AutoRestoreLocation(*this, Builder);
+ if (DI)
+ DI->EmitLocation(Builder, CurEHLocation);
CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 978e1bb5b8..630159c139 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -52,47 +52,54 @@ CGDebugInfo::~CGDebugInfo() {
"Region stack mismatch, stack not empty!");
}
-ArtificialLocation::ArtificialLocation(CodeGenFunction &CGF)
- : ApplyDebugLocation(CGF) {
- if (auto *DI = CGF.getDebugInfo()) {
- // Construct a location that has a valid scope, but no line info.
- assert(!DI->LexicalBlockStack.empty());
- llvm::DIDescriptor Scope(DI->LexicalBlockStack.back());
- CGF.Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(0, 0, Scope));
+SaveAndRestoreLocation::SaveAndRestoreLocation(CodeGenFunction &CGF,
+ CGBuilderTy &B)
+ : DI(CGF.getDebugInfo()), Builder(B) {
+ if (DI) {
+ SavedLoc = DI->getLocation();
+ DI->CurLoc = SourceLocation();
}
}
-ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF,
- SourceLocation TemporaryLocation,
- bool ForceColumnInfo)
- : CGF(CGF) {
- if (auto *DI = CGF.getDebugInfo()) {
- OriginalLocation = CGF.Builder.getCurrentDebugLocation();
- if (TemporaryLocation.isInvalid())
- CGF.Builder.SetCurrentDebugLocation(llvm::DebugLoc());
- else
- DI->EmitLocation(CGF.Builder, TemporaryLocation, ForceColumnInfo);
- }
+SaveAndRestoreLocation::~SaveAndRestoreLocation() {
+ if (DI)
+ DI->EmitLocation(Builder, SavedLoc);
+}
+
+NoLocation::NoLocation(CodeGenFunction &CGF, CGBuilderTy &B)
+ : SaveAndRestoreLocation(CGF, B) {
+ if (DI)
+ Builder.SetCurrentDebugLocation(llvm::DebugLoc());
+}
+
+NoLocation::~NoLocation() {
+ if (DI)
+ assert(Builder.getCurrentDebugLocation().isUnknown());
}
-ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF, llvm::DebugLoc Loc)
- : CGF(CGF) {
- if (CGF.getDebugInfo()) {
- OriginalLocation = CGF.Builder.getCurrentDebugLocation();
- if (!Loc.isUnknown())
- CGF.Builder.SetCurrentDebugLocation(Loc);
+ArtificialLocation::ArtificialLocation(CodeGenFunction &CGF, CGBuilderTy &B)
+ : SaveAndRestoreLocation(CGF, B) {
+ if (DI)
+ Builder.SetCurrentDebugLocation(llvm::DebugLoc());
+}
+
+void ArtificialLocation::Emit() {
+ if (DI) {
+ // Sync the Builder.
+ DI->EmitLocation(Builder, SavedLoc);
+ DI->CurLoc = SourceLocation();
+ // Construct a location that has a valid scope, but no line info.
+ assert(!DI->LexicalBlockStack.empty());
+ llvm::DIDescriptor Scope(DI->LexicalBlockStack.back());
+ Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(0, 0, Scope));
}
}
-ApplyDebugLocation::~ApplyDebugLocation() {
- // Query CGF so the location isn't overwritten when location updates are
- // temporarily disabled (for C++ default function arguments)
- if (CGF.getDebugInfo())
- CGF.Builder.SetCurrentDebugLocation(OriginalLocation);
+ArtificialLocation::~ArtificialLocation() {
+ if (DI)
+ assert(Builder.getCurrentDebugLocation().getLine() == 0);
}
-/// ArtificialLocation - An RAII object that temporarily switches to
-/// an artificial debug location that has a valid scope, but no line
void CGDebugInfo::setLocation(SourceLocation Loc) {
// If the new location isn't valid return.
if (Loc.isInvalid())
@@ -2637,6 +2644,20 @@ void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc,
if (CurLoc.isInvalid() || CurLoc.isMacroID())
return;
+ // Don't bother if things are the same as last time.
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ assert(!LexicalBlockStack.empty());
+ if (CurLoc == PrevLoc ||
+ SM.getExpansionLoc(CurLoc) == SM.getExpansionLoc(PrevLoc))
+ // New Builder may not be in sync with CGDebugInfo.
+ if (!Builder.getCurrentDebugLocation().isUnknown() &&
+ Builder.getCurrentDebugLocation().getScope(CGM.getLLVMContext()) ==
+ LexicalBlockStack.back())
+ return;
+
+ // Update last state.
+ PrevLoc = CurLoc;
+
llvm::MDNode *Scope = LexicalBlockStack.back();
Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(
getLineNumber(CurLoc), getColumnNumber(CurLoc, ForceColumnInfo), Scope));
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index 0be032c1d7..9649e29616 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -53,7 +53,7 @@ class CGDebugInfo {
const CodeGenOptions::DebugInfoKind DebugKind;
llvm::DIBuilder DBuilder;
llvm::DICompileUnit TheCU;
- SourceLocation CurLoc;
+ SourceLocation CurLoc, PrevLoc;
llvm::DIType VTablePtrType;
llvm::DIType ClassTy;
llvm::DICompositeType ObjTy;
@@ -448,17 +448,27 @@ private:
}
};
-class ApplyDebugLocation {
+/// SaveAndRestoreLocation - An RAII object saves the current location
+/// and automatically restores it to the original value.
+class SaveAndRestoreLocation {
protected:
- llvm::DebugLoc OriginalLocation;
- CodeGenFunction &CGF;
+ SourceLocation SavedLoc;
+ CGDebugInfo *DI;
+ CGBuilderTy &Builder;
+public:
+ SaveAndRestoreLocation(CodeGenFunction &CGF, CGBuilderTy &B);
+ /// Autorestore everything back to normal.
+ ~SaveAndRestoreLocation();
+};
+/// NoLocation - An RAII object that temporarily disables debug
+/// locations. This is useful for emitting instructions that should be
+/// counted towards the function prologue.
+class NoLocation : public SaveAndRestoreLocation {
public:
- ApplyDebugLocation(CodeGenFunction &CGF,
- SourceLocation TemporaryLocation = SourceLocation(),
- bool ForceColumnInfo = false);
- ApplyDebugLocation(CodeGenFunction &CGF, llvm::DebugLoc Loc);
- ~ApplyDebugLocation();
+ NoLocation(CodeGenFunction &CGF, CGBuilderTy &B);
+ /// Autorestore everything back to normal.
+ ~NoLocation();
};
/// ArtificialLocation - An RAII object that temporarily switches to
@@ -472,9 +482,16 @@ public:
/// This is necessary because passing an empty SourceLocation to
/// CGDebugInfo::setLocation() will result in the last valid location
/// being reused.
-class ArtificialLocation : public ApplyDebugLocation {
+class ArtificialLocation : public SaveAndRestoreLocation {
public:
- ArtificialLocation(CodeGenFunction &CGF);
+ ArtificialLocation(CodeGenFunction &CGF, CGBuilderTy &B);
+
+ /// Set the current location to line 0, but within the current scope
+ /// (= the top of the LexicalBlockStack).
+ void Emit();
+
+ /// Autorestore everything back to normal.
+ ~ArtificialLocation();
};
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 15a1a7fb5f..4a612c9bed 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -597,13 +597,14 @@ static void drillIntoBlockVariable(CodeGenFunction &CGF,
}
void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D,
- LValue lvalue, bool capturedByInit) {
+ LValue lvalue, bool capturedByInit,
+ SourceLocation DbgLoc) {
Qualifiers::ObjCLifetime lifetime = lvalue.getObjCLifetime();
if (!lifetime) {
llvm::Value *value = EmitScalarExpr(init);
if (capturedByInit)
drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D));
- EmitStoreThroughLValue(RValue::get(value), lvalue, true);
+ EmitStoreThroughLValue(RValue::get(value), lvalue, true, DbgLoc);
return;
}
@@ -1087,7 +1088,6 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
if (emission.wasEmittedAsGlobal()) return;
const VarDecl &D = *emission.Variable;
- ApplyDebugLocation DL(*this, D.getLocation());
QualType type = D.getType();
// If this local has an initializer, emit it now.
@@ -1126,7 +1126,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
if (!constant) {
LValue lv = MakeAddrLValue(Loc, type, alignment);
lv.setNonGC(true);
- return EmitExprAsInit(Init, &D, lv, capturedByInit);
+ return EmitExprAsInit(Init, &D, lv, capturedByInit, D.getLocation());
}
if (!emission.IsConstantAggregate) {
@@ -1192,25 +1192,26 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
/// \param capturedByInit true if the variable is a __block variable
/// whose address is potentially changed by the initializer
void CodeGenFunction::EmitExprAsInit(const Expr *init, const ValueDecl *D,
- LValue lvalue, bool capturedByInit) {
+ LValue lvalue, bool capturedByInit,
+ SourceLocation DbgLoc) {
QualType type = D->getType();
if (type->isReferenceType()) {
RValue rvalue = EmitReferenceBindingToExpr(init);
if (capturedByInit)
drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D));
- EmitStoreThroughLValue(rvalue, lvalue, true);
+ EmitStoreThroughLValue(rvalue, lvalue, true, DbgLoc);
return;
}
switch (getEvaluationKind(type)) {
case TEK_Scalar:
- EmitScalarInit(init, D, lvalue, capturedByInit);
+ EmitScalarInit(init, D, lvalue, capturedByInit, DbgLoc);
return;
case TEK_Complex: {
ComplexPairTy complex = EmitComplexExpr(init);
if (capturedByInit)
drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D));
- EmitStoreOfComplex(complex, lvalue, /*init*/ true);
+ EmitStoreOfComplex(complex, lvalue, /*init*/ true, DbgLoc);
return;
}
case TEK_Aggregate:
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index 3997c8c3d4..e002cdf6d8 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -474,11 +474,11 @@ CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
ArrayRef<llvm::Function *> Decls,
llvm::GlobalVariable *Guard) {
{
- ApplyDebugLocation NL(*this);
+ ArtificialLocation AL(*this, Builder);
StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
getTypes().arrangeNullaryFunction(), FunctionArgList());
// Emit an artificial location for this function.
- ArtificialLocation AL(*this);
+ AL.Emit();
llvm::BasicBlock *ExitBlock = nullptr;
if (Guard) {
@@ -525,11 +525,11 @@ void CodeGenFunction::GenerateCXXGlobalDtorsFunc(llvm::Function *Fn,
const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> >
&DtorsAndObjects) {
{
- ApplyDebugLocation NL(*this);
+ ArtificialLocation AL(*this, Builder);
StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
getTypes().arrangeNullaryFunction(), FunctionArgList());
// Emit an artificial location for this function.
- ArtificialLocation AL(*this);
+ AL.Emit();
// Emit the dtors, in reverse order from construction.
for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index 4b57533c60..fa89033bb0 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -734,7 +734,9 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
// Save the current IR generation state.
CGBuilderTy::InsertPoint savedIP = Builder.saveAndClearIP();
- ApplyDebugLocation AutoRestoreLocation(*this, CurEHLocation);
+ SaveAndRestoreLocation AutoRestoreLocation(*this, Builder);
+ if (CGDebugInfo *DI = getDebugInfo())
+ DI->EmitLocation(Builder, CurEHLocation);
const EHPersonality &personality = EHPersonality::get(CGM);
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 8c04f138b8..d832b1ead2 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -1438,7 +1438,11 @@ RValue CodeGenFunction::EmitLoadOfGlobalRegLValue(LValue LV) {
/// lvalue, where both are guaranteed to the have the same type, and that type
/// is 'Ty'.
void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
- bool isInit) {
+ bool isInit,
+ SourceLocation DbgLoc) {
+ if (auto *DI = getDebugInfo())
+ DI->EmitLocation(Builder, DbgLoc);
+
if (!Dst.isSimple()) {
if (Dst.isVectorElt()) {
// Read/modify/write the vector, inserting the new element.
@@ -2404,6 +2408,9 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
// The element count here is the total number of non-VLA elements.
llvm::Value *numElements = getVLASize(vla).first;
+ if (auto *DI = getDebugInfo())
+ DI->EmitLocation(Builder, E->getLocStart());
+
// Effectively, the multiply by the VLA size is part of the GEP.
// GEP indexes are signed, and scaling an index isn't permitted to
// signed-overflow, so we use the same semantics for our explicit
@@ -2449,6 +2456,9 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
// Propagate the alignment from the array itself to the result.
ArrayAlignment = ArrayLV.getAlignment();
+ if (auto *DI = getDebugInfo())
+ DI->EmitLocation(Builder, E->getLocStart());
+
if (getLangOpts().isSignedOverflowDefined())
Address = Builder.CreateGEP(ArrayPtr, Args, "arrayidx");
else
@@ -2456,6 +2466,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
} else {
// The base must be a pointer, which is not an aggregate. Emit it.
llvm::Value *Base = EmitScalarExpr(E->getBase());
+ if (auto *DI = getDebugInfo())
+ DI->EmitLocation(Builder, E->getLocStart());
if (getLangOpts().isSignedOverflowDefined())
Address = Builder.CreateGEP(Base, Idx, "arrayidx");
else
@@ -3012,15 +3024,18 @@ RValue CodeGenFunction::EmitRValueForField(LValue LV,
RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
ReturnValueSlot ReturnValue) {
- // Force column info to be generated so we can differentiate
- // multiple call sites on the same line in the debug info.
- // FIXME: This is insufficient. Two calls coming from the same macro
- // expansion will still get the same line/column and break debug info. It's
- // possible that LLVM can be fixed to not rely on this uniqueness, at which
- // point this workaround can be removed.
- ApplyDebugLocation DL(*this, E->getLocStart(),
- E->getDirectCallee() &&
- E->getDirectCallee()->isInlineSpecified());
+ if (CGDebugInfo *DI = getDebugInfo()) {
+ SourceLocation Loc = E->getLocStart();
+ // Force column info to be generated so we can differentiate
+ // multiple call sites on the same line in the debug info.
+ // FIXME: This is insufficient. Two calls coming from the same macro
+ // expansion will still get the same line/column and break debug info. It's
+ // possible that LLVM can be fixed to not rely on this uniqueness, at which
+ // point this workaround can be removed.
+ const FunctionDecl* Callee = E->getDirectCallee();
+ bool ForceColumnInfo = Callee && Callee->isInlineSpecified();
+ DI->EmitLocation(Builder, Loc, ForceColumnInfo);
+ }
// Builtins never have block type.
if (E->getCallee()->getType()->isBlockPointerType())
@@ -3136,6 +3151,8 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
RValue RV = EmitAnyExpr(E->getRHS());
LValue LV = EmitCheckedLValue(E->getLHS(), TCK_Store);
+ if (CGDebugInfo *DI = getDebugInfo())
+ DI->EmitLocation(Builder, E->getLocStart());
EmitStoreThroughLValue(RV, LV);
return LV;
}
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index 6d63b3ae9c..31f9141eeb 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -187,6 +187,8 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
unsigned ArgsToSkip = isa<CXXOperatorCallExpr>(CE) ? 1 : 0;
llvm::Value *RHS =
EmitLValue(*(CE->arg_begin() + ArgsToSkip)).getAddress();
+ if (auto *DI = getDebugInfo())
+ DI->EmitLocation(Builder, CE->getLocStart());
EmitAggregateAssign(This, RHS, CE->getType());
return RValue::get(This);
}
@@ -752,13 +754,15 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
}
static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const Expr *Init,
- QualType AllocType, llvm::Value *NewPtr) {
+ QualType AllocType, llvm::Value *NewPtr,
+ SourceLocation DbgLoc = SourceLocation()) {
// FIXME: Refactor with EmitExprAsInit.
CharUnits Alignment = CGF.getContext().getTypeAlignInChars(AllocType);
switch (CGF.getEvaluationKind(AllocType)) {
case TEK_Scalar:
CGF.EmitScalarInit(Init, nullptr,
- CGF.MakeAddrLValue(NewPtr, AllocType, Alignment), false);
+ CGF.MakeAddrLValue(NewPtr, AllocType, Alignment), false,
+ DbgLoc);
return;
case TEK_Complex:
CGF.EmitComplexExprIntoLValue(Init, CGF.MakeAddrLValue(NewPtr, AllocType,
@@ -1016,12 +1020,12 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
llvm::Value *NewPtr,
llvm::Value *NumElements,
llvm::Value *AllocSizeWithoutCookie) {
- ApplyDebugLocation DL(CGF, E->getStartLoc());
if (E->isArray())
CGF.EmitNewArrayInitializer(E, ElementType, NewPtr, NumElements,
AllocSizeWithoutCookie);
else if (const Expr *Init = E->getInitializer())
- StoreAnyExprIntoOneUnit(CGF, Init, E->getAllocatedType(), NewPtr);
+ StoreAnyExprIntoOneUnit(CGF, Init, E->getAllocatedType(), NewPtr,
+ E->getStartLoc());
}
/// Emit a call to an operator new or operator delete function, as implicitly
@@ -1265,6 +1269,9 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
E->placement_arg_end(), /* CalleeDecl */ nullptr,
/*ParamsToSkip*/ 1);
+ if (auto *DI = getDebugInfo())
+ DI->EmitLocation(Builder, E->getLocStart());
+
// Emit the allocation call. If the allocator is a global placement
// operator, just "inline" it directly.
RValue RV;
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index 1580bbe6a2..2732d40093 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -81,7 +81,8 @@ public:
/// EmitStoreOfComplex - Store the specified real/imag parts into the
/// specified value pointer.
- void EmitStoreOfComplex(ComplexPairTy Val, LValue LV, bool isInit);
+ void EmitStoreOfComplex(ComplexPairTy Val, LValue LV, bool isInit,
+ SourceLocation DbgLoc);
/// EmitComplexToComplexCast - Emit a cast from complex value Val to DestType.
ComplexPairTy EmitComplexToComplexCast(ComplexPairTy Val, QualType SrcType,
@@ -334,7 +335,11 @@ ComplexPairTy ComplexExprEmitter::EmitLoadOfLValue(LValue lvalue,
/// EmitStoreOfComplex - Store the specified real/imag parts into the
/// specified value pointer.
void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, LValue lvalue,
- bool isInit) {
+ bool isInit,
+ SourceLocation DbgLoc) {
+ if (auto *DI = CGF.getDebugInfo())
+ DI->EmitLocation(CGF.Builder, DbgLoc);
+
if (lvalue.getType()->isAtomicType())
return CGF.EmitAtomicStore(RValue::getComplex(Val), lvalue, isInit);
@@ -864,7 +869,7 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E,
// Truncate the result and store it into the LHS lvalue.
if (LHSTy->isAnyComplexType()) {
ComplexPairTy ResVal = EmitComplexToComplexCast(Result, OpInfo.Ty, LHSTy);
- EmitStoreOfComplex(ResVal, LHS, /*isInit*/ false);
+ EmitStoreOfComplex(ResVal, LHS, /*isInit*/ false, E->getLocStart());
Val = RValue::getComplex(ResVal);
} else {
llvm::Value *ResVal =
@@ -909,7 +914,7 @@ LValue ComplexExprEmitter::EmitBinAssignLValue(const BinaryOperator *E,
LValue LHS = CGF.EmitLValue(E->getLHS());
// Store the result value into the LHS lvalue.
- EmitStoreOfComplex(Val, LHS, /*isInit*/ false);
+ EmitStoreOfComplex(Val, LHS, /*isInit*/ false, E->getLocStart());
return LHS;
}
@@ -1037,18 +1042,19 @@ ComplexPairTy CodeGenFunction::EmitComplexExpr(const Expr *E, bool IgnoreReal,
}
void CodeGenFunction::EmitComplexExprIntoLValue(const Expr *E, LValue dest,
- bool isInit) {
+ bool isInit,
+ SourceLocation DbgLoc) {
assert(E && getComplexType(E->getType()) &&
"Invalid complex expression to emit");
ComplexExprEmitter Emitter(*this);
ComplexPairTy Val = Emitter.Visit(const_cast<Expr*>(E));
- Emitter.EmitStoreOfComplex(Val, dest, isInit);
+ Emitter.EmitStoreOfComplex(Val, dest, isInit, DbgLoc);
}
/// EmitStoreOfComplex - Store a complex number into the specified l-value.
void CodeGenFunction::EmitStoreOfComplex(ComplexPairTy V, LValue dest,
- bool isInit) {
- ComplexExprEmitter(*this).EmitStoreOfComplex(V, dest, isInit);
+ bool isInit, SourceLocation DbgLoc) {
+ ComplexExprEmitter(*this).EmitStoreOfComplex(V, dest, isInit, DbgLoc);
}
/// EmitLoadOfComplex - Load a complex number from the specified address.
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index f83df75869..0fef4462eb 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -196,7 +196,6 @@ public:
//===--------------------------------------------------------------------===//
Value *Visit(Expr *E) {
- ApplyDebugLocation DL(CGF, E->getLocStart());
return StmtVisitor<ScalarExprEmitter, Value*>::Visit(E);
}
@@ -3043,7 +3042,7 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
// Emit an unconditional branch from this block to ContBlock.
{
// There is no need to emit line number for unconditional branch.
- ApplyDebugLocation DL(CGF);
+ SuppressDebugLocation S(Builder);
CGF.EmitBlock(ContBlock);
}
// Insert an entry into the phi node for the edge with the value of RHSCond.
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 2e43125613..a003e8ab9e 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -565,7 +565,7 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
if (const Stmt *Else = S.getElse()) {
{
// There is no need to emit line number for unconditional branch.
- ApplyDebugLocation DL(*this);
+ SuppressDebugLocation S(Builder);
EmitBlock(ElseBlock);
}
{
@@ -574,7 +574,7 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
}
{
// There is no need to emit line number for unconditional branch.
- ApplyDebugLocation DL(*this);
+ SuppressDebugLocation S(Builder);
EmitBranch(ContBlock);
}
}
diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
index 09352f1216..73bb43654b 100644
--- a/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/lib/CodeGen/CGStmtOpenMP.cpp
@@ -86,13 +86,13 @@ static void EmitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
// Emit the 'else' code if present.
{
// There is no need to emit line number for unconditional branch.
- ApplyDebugLocation DL(CGF);
+ SuppressDebugLocation SDL(CGF.Builder);
CGF.EmitBlock(ElseBlock);
}
CodeGen(/*ThenBlock*/ false);
{
// There is no need to emit line number for unconditional branch.
- ApplyDebugLocation DL(CGF);
+ SuppressDebugLocation SDL(CGF.Builder);
CGF.EmitBranch(ContBlock);
}
// Emit the continuation block for code after the if.
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 826171a46e..4e97f9bfe3 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -158,7 +158,7 @@ TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) {
}
}
-llvm::DebugLoc CodeGenFunction::EmitReturnBlock() {
+void CodeGenFunction::EmitReturnBlock() {
// For cleanliness, we try to avoid emitting the return block for
// simple cases.
llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
@@ -173,7 +173,7 @@ llvm::DebugLoc CodeGenFunction::EmitReturnBlock() {
delete ReturnBlock.getBlock();
} else
EmitBlock(ReturnBlock.getBlock());
- return llvm::DebugLoc();
+ return;
}
// Otherwise, if the return block is the target of a single direct
@@ -184,13 +184,15 @@ llvm::DebugLoc CodeGenFunction::EmitReturnBlock() {
dyn_cast<llvm::BranchInst>(*ReturnBlock.getBlock()->user_begin());
if (BI && BI->isUnconditional() &&
BI->getSuccessor(0) == ReturnBlock.getBlock()) {
- // Record/return the DebugLoc of the simple 'return' expression to be used
- // later by the actual 'ret' instruction.
- llvm::DebugLoc Loc = BI->getDebugLoc();
+ // Reset insertion point, including debug location, and delete the
+ // branch. This is really subtle and only works because the next change
+ // in location will hit the caching in CGDebugInfo::EmitLocation and not
+ // override this.
+ Builder.SetCurrentDebugLocation(BI->getDebugLoc());
Builder.SetInsertPoint(BI->getParent());
BI->eraseFromParent();
delete ReturnBlock.getBlock();
- return Loc;
+ return;
}
}
@@ -199,7 +201,6 @@ llvm::DebugLoc CodeGenFunction::EmitReturnBlock() {
// region.end for now.
EmitBlock(ReturnBlock.getBlock());
- return llvm::DebugLoc();
}
static void EmitIfUsed(CodeGenFunction &CGF, llvm::BasicBlock *BB) {
@@ -253,18 +254,16 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
}
// Emit function epilog (to return).
- llvm::DebugLoc Loc = EmitReturnBlock();
+ EmitReturnBlock();
if (ShouldInstrumentFunction())
EmitFunctionInstrumentation("__cyg_profile_func_exit");
// Emit debug descriptor for function end.
- if (CGDebugInfo *DI = getDebugInfo())
+ if (CGDebugInfo *DI = getDebugInfo()) {
DI->EmitFunctionEnd(Builder);
+ }
- // Reset the debug location to that of the simple 'return' expression, if any
- // rather than that of the end of the function's scope '}'.
- ApplyDebugLocation AL(*this, Loc);
EmitFunctionEpilog(*CurFnInfo, EmitRetDbgLoc, EndLoc);
EmitEndEHSpec(CurCodeDecl);
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 36914691eb..e2fd80e7d3 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -93,6 +93,19 @@ enum TypeEvaluationKind {
TEK_Aggregate
};
+class SuppressDebugLocation {
+ llvm::DebugLoc CurLoc;
+ llvm::IRBuilderBase &Builder;
+public:
+ SuppressDebugLocation(llvm::IRBuilderBase &Builder)
+ : CurLoc(Builder.getCurrentDebugLocation()), Builder(Builder) {
+ Builder.SetCurrentDebugLocation(llvm::DebugLoc());
+ }
+ ~SuppressDebugLocation() {
+ Builder.SetCurrentDebugLocation(CurLoc);
+ }
+};
+
/// CodeGenFunction - This class organizes the per-function state that is used
/// while generating LLVM code.
class CodeGenFunction : public CodeGenTypeCache {
@@ -1262,7 +1275,7 @@ public:
/// EmitReturnBlock - Emit the unified return block, trying to avoid its
/// emission when possible.
- llvm::DebugLoc EmitReturnBlock();
+ void EmitReturnBlock();
/// FinishFunction - Complete IR generation of the current function. It is
/// legal to call this function even if there is no current insertion point.
@@ -1287,7 +1300,8 @@ public:
FunctionArgList &Args);
void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init,
- ArrayRef<VarDecl *> ArrayIndexes);
+ ArrayRef<VarDecl *> ArrayIndexes,
+ SourceLocation DbgLoc = SourceLocation());
/// InitializeVTablePointer - Initialize the vtable pointer of the given
/// subobject.
@@ -1532,7 +1546,7 @@ public:
/// EmitExprAsInit - Emits the code necessary to initialize a
/// location in memory with the given initializer.
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue,
- bool capturedByInit);
+ bool capturedByInit, SourceLocation DbgLoc);
/// hasVolatileMember - returns true if aggregate type has a volatile
/// member.
@@ -1819,7 +1833,8 @@ public:
void EmitVarDecl(const VarDecl &D);
void EmitScalarInit(const Expr *init, const ValueDecl *D, LValue lvalue,
- bool capturedByInit);
+ bool capturedByInit,
+ SourceLocation DbgLoc = SourceLocation());
void EmitScalarInit(llvm::Value *init, LValue lvalue);
typedef void SpecialInitFn(CodeGenFunction &Init, const VarDecl &D,
@@ -2149,7 +2164,8 @@ public:
/// EmitStoreThroughLValue - Store the specified rvalue into the specified
/// lvalue, where both are guaranteed to the have the same type, and that type
/// is 'Ty'.
- void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit = false);
+ void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit = false,
+ SourceLocation DbgLoc = SourceLocation());
void EmitStoreThroughExtVectorComponentLValue(RValue Src, LValue Dst);
void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst);
@@ -2521,10 +2537,12 @@ public:
/// EmitComplexExprIntoLValue - Emit the given expression of complex
/// type and place its result into the specified l-value.
- void EmitComplexExprIntoLValue(const Expr *E, LValue dest, bool isInit);
+ void EmitComplexExprIntoLValue(const Expr *E, LValue dest, bool isInit,
+ SourceLocation DbgLoc = SourceLocation());
/// EmitStoreOfComplex - Store a complex number into the specified l-value.
- void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit);
+ void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit,
+ SourceLocation DbgLoc = SourceLocation());
/// EmitLoadOfComplex - Load a complex number from the specified l-value.
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc);
diff --git a/test/CodeGenCXX/PR20038.cpp b/test/CodeGenCXX/PR20038.cpp
index d838dbc510..5bae285a83 100644
--- a/test/CodeGenCXX/PR20038.cpp
+++ b/test/CodeGenCXX/PR20038.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple %itanium_abi_triple -g -mllvm -no-discriminators -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -g -emit-llvm %s -o - | FileCheck %s
struct C {
~C();
@@ -8,7 +8,9 @@ extern bool b;
// CHECK: call {{.*}}, !dbg [[DTOR_CALL2_LOC:![0-9]*]]
// CHECK: [[FUN1:.*]] = {{.*}}; [ DW_TAG_subprogram ] {{.*}} [def] [fun1]
// CHECK: [[FUN2:.*]] = {{.*}}; [ DW_TAG_subprogram ] {{.*}} [def] [fun2]
-// CHECK: [[DTOR_CALL1_LOC]] = !{i32 [[@LINE+1]], i32 0, [[FUN1]], null}
+// CHECK: [[DTOR_CALL1_LOC]] = !{i32 [[@LINE+2]], i32 0, [[FUN1_BLOCK:.*]], null}
+// CHECK: [[FUN1_BLOCK]] = !{!"0xb{{[^,]*}}", {{[^,]*}}, [[FUN1]]}
void fun1() { b && (C(), 1); }
-// CHECK: [[DTOR_CALL2_LOC]] = !{i32 [[@LINE+1]], i32 0, [[FUN2]], null}
+// CHECK: [[DTOR_CALL2_LOC]] = !{i32 [[@LINE+2]], i32 0, [[FUN2_BLOCK1:.*]], null}
+// CHECK: [[FUN2_BLOCK1]] = !{!"0xb{{[^,]*}}", {{[^,]*}}, [[FUN2]]}
bool fun2() { return (C(), b) && 0; }
diff --git a/test/CodeGenCXX/debug-info-line.cpp b/test/CodeGenCXX/debug-info-line.cpp
index a4dff576ef..25231720f8 100644
--- a/test/CodeGenCXX/debug-info-line.cpp
+++ b/test/CodeGenCXX/debug-info-line.cpp
@@ -1,5 +1,4 @@
// RUN: %clang_cc1 -g -std=c++11 -S -emit-llvm %s -o - | FileCheck %s
-// RUN: %clang_cc1 -triple i686-linux-gnu -g -std=c++11 -S -emit-llvm %s -o - | FileCheck %s
// XFAIL: win32
@@ -113,32 +112,6 @@ void f10() {
new (void_src()) int(src()));
}
-// CHECK-LABEL: define
-__complex double f11() {
- __complex double f;
-// CHECK: store {{.*}} !dbg [[DBG_F11:!.*]]
-#line 1200
- return f;
-}
-
-// CHECK-LABEL: define
-void f12() {
- int f12_1();
- void f12_2(int = f12_1());
-// CHECK: call {{(signext )?}}i32 {{.*}} !dbg [[DBG_F12:!.*]]
-#line 1300
- f12_2();
-}
-
-// CHECK-LABEL: define
-void f13() {
-// CHECK: call {{.*}} !dbg [[DBG_F13:!.*]]
-#define F13_IMPL 1, src()
- 1,
-#line 1400
- F13_IMPL;
-}
-
// CHECK: [[DBG_F1]] = !{i32 100,
// CHECK: [[DBG_FOO_VALUE]] = !{i32 200,
// CHECK: [[DBG_FOO_REF]] = !{i32 202,
@@ -153,6 +126,3 @@ void f13() {
// CHECK: [[DBG_F9]] = !{i32 1000,
// CHECK: [[DBG_F10_ICMP]] = !{i32 1100,
// CHECK: [[DBG_F10_STORE]] = !{i32 1100,
-// CHECK: [[DBG_F11]] = !{i32 1200,
-// CHECK: [[DBG_F12]] = !{i32 1300,
-// CHECK: [[DBG_F13]] = !{i32 1400,
diff --git a/test/CodeGenCXX/debug-info-scope.cpp b/test/CodeGenCXX/debug-info-scope.cpp
index e66588d699..f72c4aa7cc 100644
--- a/test/CodeGenCXX/debug-info-scope.cpp
+++ b/test/CodeGenCXX/debug-info-scope.cpp
@@ -36,12 +36,12 @@ void func() {
// CHECK: = !{!"0x100\00{{.*}}", [[FOR:![0-9]*]], {{.*}} ; [ DW_TAG_auto_variable ] [i] [line [[@LINE+2]]]
// CHECK: [[FOR]] = !{!"0xb\00[[@LINE+1]]\00{{.*}}", !{{.*}}} ; [ DW_TAG_lexical_block ]
for (int i = 0; i != 10; ++i) {
- // FIXME: Do not include scopes that have only other scopes (and no variables
- // or using declarations) as direct children, they just waste
- // space/relocations/etc.
- // CHECK: [[FOR_LOOP_INCLUDING_COND:!.*]] = !{!"0xb\00[[@LINE-4]]\00{{.*}}", !{{[0-9]+}}, [[FOR]]} ; [ DW_TAG_lexical_block ]
- // CHECK: = !{!"0x100\00{{.*}}", [[FOR_COMPOUND:![0-9]*]], {{.*}} ; [ DW_TAG_auto_variable ] [b] [line [[@LINE+2]]]
- // CHECK: [[FOR_COMPOUND]] = !{!"0xb\00[[@LINE-6]]\00{{.*}}", !{{[0-9]+}}, [[FOR_LOOP_INCLUDING_COND]]} ; [ DW_TAG_lexical_block ]
+ // FIXME: Do not include scopes that have only other scopes (and no variables
+ // or using declarations) as direct children, they just waste
+ // space/relocations/etc.
+ // CHECK: = !{!"0x100\00{{.*}}", [[FOR_COMPOUND:![0-9]*]], {{.*}} ; [ DW_TAG_auto_variable ] [b] [line [[@LINE+3]]]
+ // CHECK: [[FOR_COMPOUND]] = !{!"0xb\00[[@LINE-5]]\00{{.*}}", !{{[0-9]+}}, [[FOR_BODY:![0-9]+]]} ; [ DW_TAG_lexical_block ]
+ // CHECK: [[FOR_BODY]] = !{!"0xb\00[[@LINE-6]]\00{{.*}}", !{{[0-9]+}}, [[FOR]]} ; [ DW_TAG_lexical_block ]
bool b = i % 2;
}