From 66e4197f07f6a3fe178f2b220fce62a1889b5fe6 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Wed, 14 Jan 2015 07:38:27 +0000 Subject: [PATCH] Reapply r225000 (reverted in r225555): DebugInfo: Generalize debug info location handling (and follow-up commits). Several pieces of code were relying on implicit debug location setting which usually lead to incorrect line information anyway. So I've fixed those (in r225955 and r225845) separately which should pave the way for this commit to be cleanly reapplied. The reason these implicit dependencies resulted in crashes with this patch is that the debug location would no longer implicitly leak from one place to another, but be set back to invalid. Once a call with no/invalid location was emitted, if that call was ever inlined it could produce invalid debugloc chains and assert during LLVM's codegen. There may be further cases of such bugs in this patch - they're hard to flush out with regression testing, so I'll keep an eye out for reports and investigate/fix them ASAP if they come up. Original commit message: Reapply "DebugInfo: Generalize debug info location handling" Originally committed in r224385 and reverted in r224441 due to concerns this change might've introduced a crash. Turns out this change fixes the crash introduced by one of my earlier more specific location handling changes (those specific fixes are reverted by this patch, in favor of the more general solution). Recommitted in r224941 and reverted in r224970 after it caused a crash when building compiler-rt. Looks to be due to this change zeroing out the debug location when emitting default arguments (which were meant to inherit their outer expression's location) thus creating call instructions without locations - these create problems for inlining and must not be created. That is fixed and tested in this version of the change. Original commit message: This is a more scalable (fixed in mostly one place, rather than many places that will need constant improvement/maintenance) solution to several commits I've made recently to increase source fidelity for subexpressions. This resetting had to be done at the DebugLoc level (not the SourceLocation level) to preserve scoping information (if the resetting was done with CGDebugInfo::EmitLocation, it would've caused the tail end of an expression's codegen to end up in a potentially different scope than the start, even though it was at the same source location). The drawback to this is that it might leave CGDebugInfo out of sync. Ideally CGDebugInfo shouldn't have a duplicate sense of the current SourceLocation, but for now it seems it does... - I don't think I'm going to tackle removing that just now. I expect this'll probably cause some more buildbot fallout & I'll investigate that as it comes up. Also these sort of improvements might be starting to show a weakness/bug in LLVM's line table handling: we don't correctly emit is_stmt for statements, we just put it on every line table entry. This means one statement split over multiple lines appears as multiple 'statements' and two statements on one line (without column info) are treated as one statement. I don't think we have any IR representation of statements that would help us distinguish these cases and identify the beginning of each statement - so that might be something we need to add (possibly to the lexical scope chain - a scope for each statement). This does cause some problems for GDB and possibly other DWARF consumers. llvm-svn: 225956 --- clang/lib/CodeGen/CGBlocks.cpp | 12 ++--- clang/lib/CodeGen/CGClass.cpp | 18 +++---- clang/lib/CodeGen/CGCleanup.cpp | 5 +- clang/lib/CodeGen/CGDebugInfo.cpp | 83 +++++++++++------------------- clang/lib/CodeGen/CGDebugInfo.h | 39 ++++---------- clang/lib/CodeGen/CGDecl.cpp | 17 +++--- clang/lib/CodeGen/CGDeclCXX.cpp | 8 +-- clang/lib/CodeGen/CGException.cpp | 4 +- clang/lib/CodeGen/CGExpr.cpp | 37 ++++--------- clang/lib/CodeGen/CGExprCXX.cpp | 15 ++---- clang/lib/CodeGen/CGExprComplex.cpp | 22 +++----- clang/lib/CodeGen/CGExprScalar.cpp | 3 +- clang/lib/CodeGen/CGStmt.cpp | 4 +- clang/lib/CodeGen/CGStmtOpenMP.cpp | 4 +- clang/lib/CodeGen/CodeGenFunction.cpp | 23 +++++---- clang/lib/CodeGen/CodeGenFunction.h | 32 +++--------- clang/test/CodeGenCXX/PR20038.cpp | 8 ++- clang/test/CodeGenCXX/debug-info-line.cpp | 38 +++++++++++++- clang/test/CodeGenCXX/debug-info-scope.cpp | 12 ++--- 19 files changed, 163 insertions(+), 221 deletions(-) diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 9db1b7a..b98460a 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -875,7 +875,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, SourceLocation()); + /*captured by init*/ false); } // Activate the cleanup if layout pushed one. @@ -1178,7 +1178,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(). - NoLocation NL(*this, Builder); + ApplyDebugLocation NL(*this); Builder.CreateAlignedStore(BlockPointer, Alloca, Align); BlockPointerDbgLoc = Alloca; } @@ -1329,9 +1329,9 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { false, false); // Create a scope with an artificial location for the body of this function. - ArtificialLocation AL(*this, Builder); + ApplyDebugLocation NL(*this); StartFunction(FD, C.VoidTy, Fn, FI, args); - AL.Emit(); + ArtificialLocation AL(*this); llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); @@ -1500,9 +1500,9 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { nullptr, SC_Static, false, false); // Create a scope with an artificial location for the body of this function. - ArtificialLocation AL(*this, Builder); + ApplyDebugLocation NL(*this); StartFunction(FD, C.VoidTy, Fn, FI, args); - AL.Emit(); + ArtificialLocation AL(*this); llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 5ffab60..92c694a 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -544,6 +544,7 @@ 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!"); @@ -597,26 +598,25 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, ArrayRef ArrayIndexes; if (MemberInit->getNumArrayIndices()) ArrayIndexes = MemberInit->getArrayIndexes(); - CGF.EmitInitializerForField(Field, LHS, MemberInit->getInit(), ArrayIndexes, - MemberInit->getMemberLocation()); + ApplyDebugLocation DL(CGF, MemberInit->getMemberLocation()); + CGF.EmitInitializerForField(Field, LHS, MemberInit->getInit(), ArrayIndexes); } -void CodeGenFunction::EmitInitializerForField(FieldDecl *Field, LValue LHS, - Expr *Init, - ArrayRef ArrayIndexes, - SourceLocation DbgLoc) { +void CodeGenFunction::EmitInitializerForField( + FieldDecl *Field, LValue LHS, Expr *Init, + ArrayRef ArrayIndexes) { QualType FieldType = Field->getType(); switch (getEvaluationKind(FieldType)) { case TEK_Scalar: if (LHS.isSimple()) { - EmitExprAsInit(Init, Field, LHS, false, DbgLoc); + EmitExprAsInit(Init, Field, LHS, false); } else { RValue RHS = RValue::get(EmitScalarExpr(Init)); EmitStoreThroughLValue(RHS, LHS); } break; case TEK_Complex: - EmitComplexExprIntoLValue(Init, LHS, /*isInit*/ true, DbgLoc); + EmitComplexExprIntoLValue(Init, LHS, /*isInit*/ true); break; case TEK_Aggregate: { llvm::Value *ArrayIndexVar = nullptr; @@ -783,8 +783,6 @@ 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/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp index d81e3a5..18ed3e5 100644 --- a/clang/lib/CodeGen/CGCleanup.cpp +++ b/clang/lib/CodeGen/CGCleanup.cpp @@ -861,10 +861,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { // Emit the EH cleanup if required. if (RequiresEHCleanup) { - CGDebugInfo *DI = getDebugInfo(); - SaveAndRestoreLocation AutoRestoreLocation(*this, Builder); - if (DI) - DI->EmitLocation(Builder, CurEHLocation); + ApplyDebugLocation AutoRestoreLocation(*this, CurEHLocation); CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 630159c..978e1bb 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -52,54 +52,47 @@ CGDebugInfo::~CGDebugInfo() { "Region stack mismatch, stack not empty!"); } -SaveAndRestoreLocation::SaveAndRestoreLocation(CodeGenFunction &CGF, - CGBuilderTy &B) - : DI(CGF.getDebugInfo()), Builder(B) { - if (DI) { - SavedLoc = DI->getLocation(); - DI->CurLoc = SourceLocation(); +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() { - 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()); -} - -ArtificialLocation::ArtificialLocation(CodeGenFunction &CGF, CGBuilderTy &B) - : SaveAndRestoreLocation(CGF, B) { - if (DI) - Builder.SetCurrentDebugLocation(llvm::DebugLoc()); +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); + } } -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(CodeGenFunction &CGF, llvm::DebugLoc Loc) + : CGF(CGF) { + if (CGF.getDebugInfo()) { + OriginalLocation = CGF.Builder.getCurrentDebugLocation(); + if (!Loc.isUnknown()) + CGF.Builder.SetCurrentDebugLocation(Loc); } } -ArtificialLocation::~ArtificialLocation() { - if (DI) - assert(Builder.getCurrentDebugLocation().getLine() == 0); +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 - 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()) @@ -2644,20 +2637,6 @@ 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/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 9649e29..0be032c 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -53,7 +53,7 @@ class CGDebugInfo { const CodeGenOptions::DebugInfoKind DebugKind; llvm::DIBuilder DBuilder; llvm::DICompileUnit TheCU; - SourceLocation CurLoc, PrevLoc; + SourceLocation CurLoc; llvm::DIType VTablePtrType; llvm::DIType ClassTy; llvm::DICompositeType ObjTy; @@ -448,27 +448,17 @@ private: } }; -/// SaveAndRestoreLocation - An RAII object saves the current location -/// and automatically restores it to the original value. -class SaveAndRestoreLocation { +class ApplyDebugLocation { protected: - SourceLocation SavedLoc; - CGDebugInfo *DI; - CGBuilderTy &Builder; -public: - SaveAndRestoreLocation(CodeGenFunction &CGF, CGBuilderTy &B); - /// Autorestore everything back to normal. - ~SaveAndRestoreLocation(); -}; + llvm::DebugLoc OriginalLocation; + CodeGenFunction &CGF; -/// 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: - NoLocation(CodeGenFunction &CGF, CGBuilderTy &B); - /// Autorestore everything back to normal. - ~NoLocation(); + ApplyDebugLocation(CodeGenFunction &CGF, + SourceLocation TemporaryLocation = SourceLocation(), + bool ForceColumnInfo = false); + ApplyDebugLocation(CodeGenFunction &CGF, llvm::DebugLoc Loc); + ~ApplyDebugLocation(); }; /// ArtificialLocation - An RAII object that temporarily switches to @@ -482,16 +472,9 @@ public: /// This is necessary because passing an empty SourceLocation to /// CGDebugInfo::setLocation() will result in the last valid location /// being reused. -class ArtificialLocation : public SaveAndRestoreLocation { +class ArtificialLocation : public ApplyDebugLocation { public: - 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(); + ArtificialLocation(CodeGenFunction &CGF); }; diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 39052e5..766d2aa 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -600,14 +600,13 @@ static void drillIntoBlockVariable(CodeGenFunction &CGF, } void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D, - LValue lvalue, bool capturedByInit, - SourceLocation DbgLoc) { + LValue lvalue, bool capturedByInit) { Qualifiers::ObjCLifetime lifetime = lvalue.getObjCLifetime(); if (!lifetime) { llvm::Value *value = EmitScalarExpr(init); if (capturedByInit) drillIntoBlockVariable(*this, lvalue, cast(D)); - EmitStoreThroughLValue(RValue::get(value), lvalue, true, DbgLoc); + EmitStoreThroughLValue(RValue::get(value), lvalue, true); return; } @@ -1091,6 +1090,7 @@ 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. @@ -1129,7 +1129,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { if (!constant) { LValue lv = MakeAddrLValue(Loc, type, alignment); lv.setNonGC(true); - return EmitExprAsInit(Init, &D, lv, capturedByInit, D.getLocation()); + return EmitExprAsInit(Init, &D, lv, capturedByInit); } if (!emission.IsConstantAggregate) { @@ -1195,26 +1195,25 @@ 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, - SourceLocation DbgLoc) { + LValue lvalue, bool capturedByInit) { QualType type = D->getType(); if (type->isReferenceType()) { RValue rvalue = EmitReferenceBindingToExpr(init); if (capturedByInit) drillIntoBlockVariable(*this, lvalue, cast(D)); - EmitStoreThroughLValue(rvalue, lvalue, true, DbgLoc); + EmitStoreThroughLValue(rvalue, lvalue, true); return; } switch (getEvaluationKind(type)) { case TEK_Scalar: - EmitScalarInit(init, D, lvalue, capturedByInit, DbgLoc); + EmitScalarInit(init, D, lvalue, capturedByInit); return; case TEK_Complex: { ComplexPairTy complex = EmitComplexExpr(init); if (capturedByInit) drillIntoBlockVariable(*this, lvalue, cast(D)); - EmitStoreOfComplex(complex, lvalue, /*init*/ true, DbgLoc); + EmitStoreOfComplex(complex, lvalue, /*init*/ true); return; } case TEK_Aggregate: diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 9bfad21..3b379b7 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -469,11 +469,11 @@ CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, ArrayRef Decls, llvm::GlobalVariable *Guard) { { - ArtificialLocation AL(*this, Builder); + ApplyDebugLocation NL(*this); StartFunction(GlobalDecl(), getContext().VoidTy, Fn, getTypes().arrangeNullaryFunction(), FunctionArgList()); // Emit an artificial location for this function. - AL.Emit(); + ArtificialLocation AL(*this); llvm::BasicBlock *ExitBlock = nullptr; if (Guard) { @@ -520,11 +520,11 @@ void CodeGenFunction::GenerateCXXGlobalDtorsFunc(llvm::Function *Fn, const std::vector > &DtorsAndObjects) { { - ArtificialLocation AL(*this, Builder); + ApplyDebugLocation NL(*this); StartFunction(GlobalDecl(), getContext().VoidTy, Fn, getTypes().arrangeNullaryFunction(), FunctionArgList()); // Emit an artificial location for this function. - AL.Emit(); + ArtificialLocation AL(*this); // Emit the dtors, in reverse order from construction. for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) { diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index fa89033..4b57533 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -734,9 +734,7 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { // Save the current IR generation state. CGBuilderTy::InsertPoint savedIP = Builder.saveAndClearIP(); - SaveAndRestoreLocation AutoRestoreLocation(*this, Builder); - if (CGDebugInfo *DI = getDebugInfo()) - DI->EmitLocation(Builder, CurEHLocation); + ApplyDebugLocation AutoRestoreLocation(*this, CurEHLocation); const EHPersonality &personality = EHPersonality::get(CGM); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index ebcbcdd..fcae979 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1438,11 +1438,7 @@ 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, - SourceLocation DbgLoc) { - if (auto *DI = getDebugInfo()) - DI->EmitLocation(Builder, DbgLoc); - + bool isInit) { if (!Dst.isSimple()) { if (Dst.isVectorElt()) { // Read/modify/write the vector, inserting the new element. @@ -2455,9 +2451,6 @@ 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 @@ -2503,9 +2496,6 @@ 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 @@ -2513,8 +2503,6 @@ 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 @@ -3071,18 +3059,15 @@ RValue CodeGenFunction::EmitRValueForField(LValue LV, RValue CodeGenFunction::EmitCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue) { - 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); - } + // 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()); // Builtins never have block type. if (E->getCallee()->getType()->isBlockPointerType()) @@ -3198,8 +3183,6 @@ 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/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 31f9141..6d63b3a 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -187,8 +187,6 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( unsigned ArgsToSkip = isa(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); } @@ -754,15 +752,13 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF, } static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const Expr *Init, - QualType AllocType, llvm::Value *NewPtr, - SourceLocation DbgLoc = SourceLocation()) { + QualType AllocType, llvm::Value *NewPtr) { // 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, - DbgLoc); + CGF.MakeAddrLValue(NewPtr, AllocType, Alignment), false); return; case TEK_Complex: CGF.EmitComplexExprIntoLValue(Init, CGF.MakeAddrLValue(NewPtr, AllocType, @@ -1020,12 +1016,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, - E->getStartLoc()); + StoreAnyExprIntoOneUnit(CGF, Init, E->getAllocatedType(), NewPtr); } /// Emit a call to an operator new or operator delete function, as implicitly @@ -1269,9 +1265,6 @@ 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/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index 2732d40..1580bbe 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -81,8 +81,7 @@ public: /// EmitStoreOfComplex - Store the specified real/imag parts into the /// specified value pointer. - void EmitStoreOfComplex(ComplexPairTy Val, LValue LV, bool isInit, - SourceLocation DbgLoc); + void EmitStoreOfComplex(ComplexPairTy Val, LValue LV, bool isInit); /// EmitComplexToComplexCast - Emit a cast from complex value Val to DestType. ComplexPairTy EmitComplexToComplexCast(ComplexPairTy Val, QualType SrcType, @@ -335,11 +334,7 @@ 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, - SourceLocation DbgLoc) { - if (auto *DI = CGF.getDebugInfo()) - DI->EmitLocation(CGF.Builder, DbgLoc); - + bool isInit) { if (lvalue.getType()->isAtomicType()) return CGF.EmitAtomicStore(RValue::getComplex(Val), lvalue, isInit); @@ -869,7 +864,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, E->getLocStart()); + EmitStoreOfComplex(ResVal, LHS, /*isInit*/ false); Val = RValue::getComplex(ResVal); } else { llvm::Value *ResVal = @@ -914,7 +909,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, E->getLocStart()); + EmitStoreOfComplex(Val, LHS, /*isInit*/ false); return LHS; } @@ -1042,19 +1037,18 @@ ComplexPairTy CodeGenFunction::EmitComplexExpr(const Expr *E, bool IgnoreReal, } void CodeGenFunction::EmitComplexExprIntoLValue(const Expr *E, LValue dest, - bool isInit, - SourceLocation DbgLoc) { + bool isInit) { assert(E && getComplexType(E->getType()) && "Invalid complex expression to emit"); ComplexExprEmitter Emitter(*this); ComplexPairTy Val = Emitter.Visit(const_cast(E)); - Emitter.EmitStoreOfComplex(Val, dest, isInit, DbgLoc); + Emitter.EmitStoreOfComplex(Val, dest, isInit); } /// EmitStoreOfComplex - Store a complex number into the specified l-value. void CodeGenFunction::EmitStoreOfComplex(ComplexPairTy V, LValue dest, - bool isInit, SourceLocation DbgLoc) { - ComplexExprEmitter(*this).EmitStoreOfComplex(V, dest, isInit, DbgLoc); + bool isInit) { + ComplexExprEmitter(*this).EmitStoreOfComplex(V, dest, isInit); } /// EmitLoadOfComplex - Load a complex number from the specified address. diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 7c0ce7a..a9cbf05 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -196,6 +196,7 @@ public: //===--------------------------------------------------------------------===// Value *Visit(Expr *E) { + ApplyDebugLocation DL(CGF, E->getLocStart()); return StmtVisitor::Visit(E); } @@ -3042,7 +3043,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. - SuppressDebugLocation S(Builder); + ApplyDebugLocation DL(CGF); CGF.EmitBlock(ContBlock); } // Insert an entry into the phi node for the edge with the value of RHSCond. diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index bd48227..e3bdf86 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/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. - SuppressDebugLocation S(Builder); + ApplyDebugLocation DL(*this); EmitBlock(ElseBlock); } { @@ -574,7 +574,7 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) { } { // There is no need to emit line number for unconditional branch. - SuppressDebugLocation S(Builder); + ApplyDebugLocation DL(*this); EmitBranch(ContBlock); } } diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 73bb436..09352f1 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/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. - SuppressDebugLocation SDL(CGF.Builder); + ApplyDebugLocation DL(CGF); CGF.EmitBlock(ElseBlock); } CodeGen(/*ThenBlock*/ false); { // There is no need to emit line number for unconditional branch. - SuppressDebugLocation SDL(CGF.Builder); + ApplyDebugLocation DL(CGF); CGF.EmitBranch(ContBlock); } // Emit the continuation block for code after the if. diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 4e97f9b..826171a 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -158,7 +158,7 @@ TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) { } } -void CodeGenFunction::EmitReturnBlock() { +llvm::DebugLoc CodeGenFunction::EmitReturnBlock() { // For cleanliness, we try to avoid emitting the return block for // simple cases. llvm::BasicBlock *CurBB = Builder.GetInsertBlock(); @@ -173,7 +173,7 @@ void CodeGenFunction::EmitReturnBlock() { delete ReturnBlock.getBlock(); } else EmitBlock(ReturnBlock.getBlock()); - return; + return llvm::DebugLoc(); } // Otherwise, if the return block is the target of a single direct @@ -184,15 +184,13 @@ void CodeGenFunction::EmitReturnBlock() { dyn_cast(*ReturnBlock.getBlock()->user_begin()); if (BI && BI->isUnconditional() && BI->getSuccessor(0) == ReturnBlock.getBlock()) { - // 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()); + // Record/return the DebugLoc of the simple 'return' expression to be used + // later by the actual 'ret' instruction. + llvm::DebugLoc Loc = BI->getDebugLoc(); Builder.SetInsertPoint(BI->getParent()); BI->eraseFromParent(); delete ReturnBlock.getBlock(); - return; + return Loc; } } @@ -201,6 +199,7 @@ void CodeGenFunction::EmitReturnBlock() { // region.end for now. EmitBlock(ReturnBlock.getBlock()); + return llvm::DebugLoc(); } static void EmitIfUsed(CodeGenFunction &CGF, llvm::BasicBlock *BB) { @@ -254,16 +253,18 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { } // Emit function epilog (to return). - EmitReturnBlock(); + llvm::DebugLoc Loc = 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/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index bd9cd9e..3a990d2 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -93,19 +93,6 @@ 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 { @@ -1273,7 +1260,7 @@ public: /// EmitReturnBlock - Emit the unified return block, trying to avoid its /// emission when possible. - void EmitReturnBlock(); + llvm::DebugLoc EmitReturnBlock(); /// FinishFunction - Complete IR generation of the current function. It is /// legal to call this function even if there is no current insertion point. @@ -1298,8 +1285,7 @@ public: FunctionArgList &Args); void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init, - ArrayRef ArrayIndexes, - SourceLocation DbgLoc = SourceLocation()); + ArrayRef ArrayIndexes); /// InitializeVTablePointer - Initialize the vtable pointer of the given /// subobject. @@ -1544,7 +1530,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, SourceLocation DbgLoc); + bool capturedByInit); /// hasVolatileMember - returns true if aggregate type has a volatile /// member. @@ -1831,8 +1817,7 @@ public: void EmitVarDecl(const VarDecl &D); void EmitScalarInit(const Expr *init, const ValueDecl *D, LValue lvalue, - bool capturedByInit, - SourceLocation DbgLoc = SourceLocation()); + bool capturedByInit); void EmitScalarInit(llvm::Value *init, LValue lvalue); typedef void SpecialInitFn(CodeGenFunction &Init, const VarDecl &D, @@ -2162,8 +2147,7 @@ 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, - SourceLocation DbgLoc = SourceLocation()); + void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit = false); void EmitStoreThroughExtVectorComponentLValue(RValue Src, LValue Dst); void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst); @@ -2535,12 +2519,10 @@ 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, - SourceLocation DbgLoc = SourceLocation()); + void EmitComplexExprIntoLValue(const Expr *E, LValue dest, bool isInit); /// EmitStoreOfComplex - Store a complex number into the specified l-value. - void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit, - SourceLocation DbgLoc = SourceLocation()); + void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit); /// EmitLoadOfComplex - Load a complex number from the specified l-value. ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc); diff --git a/clang/test/CodeGenCXX/PR20038.cpp b/clang/test/CodeGenCXX/PR20038.cpp index 5bae285..d838dbc 100644 --- a/clang/test/CodeGenCXX/PR20038.cpp +++ b/clang/test/CodeGenCXX/PR20038.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -g -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -g -mllvm -no-discriminators -emit-llvm %s -o - | FileCheck %s struct C { ~C(); @@ -8,9 +8,7 @@ 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+2]], i32 0, [[FUN1_BLOCK:.*]], null} -// CHECK: [[FUN1_BLOCK]] = !{!"0xb{{[^,]*}}", {{[^,]*}}, [[FUN1]]} +// CHECK: [[DTOR_CALL1_LOC]] = !{i32 [[@LINE+1]], i32 0, [[FUN1]], null} void fun1() { b && (C(), 1); } -// CHECK: [[DTOR_CALL2_LOC]] = !{i32 [[@LINE+2]], i32 0, [[FUN2_BLOCK1:.*]], null} -// CHECK: [[FUN2_BLOCK1]] = !{!"0xb{{[^,]*}}", {{[^,]*}}, [[FUN2]]} +// CHECK: [[DTOR_CALL2_LOC]] = !{i32 [[@LINE+1]], i32 0, [[FUN2]], null} bool fun2() { return (C(), b) && 0; } diff --git a/clang/test/CodeGenCXX/debug-info-line.cpp b/clang/test/CodeGenCXX/debug-info-line.cpp index 7a6d654..d7c29ba 100644 --- a/clang/test/CodeGenCXX/debug-info-line.cpp +++ b/clang/test/CodeGenCXX/debug-info-line.cpp @@ -1,4 +1,7 @@ -// RUN: %clang_cc1 -fexceptions -fcxx-exceptions -g -std=c++11 -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -gline-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -gline-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - -triple i686-linux-gnu | FileCheck %s + +// XFAIL: win32 int &src(); int *sink(); @@ -123,6 +126,10 @@ struct bar { // CHECK: invoke{{ }} // CHECK: invoke{{ }} // CHECK: to label {{.*}}, !dbg [[DBG_GLBL_CTOR_B:!.*]] + +// terminate caller +// CHECK-LABEL: define + // global dtor cleanup // CHECK-LABEL: define // CHECK: invoke{{ }} @@ -133,6 +140,32 @@ bar b[1] = { // (fn(), // bar())}; +// 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, @@ -149,3 +182,6 @@ bar b[1] = { // // CHECK: [[DBG_F10_STORE]] = !{i32 1100, // CHECK: [[DBG_GLBL_CTOR_B]] = !{i32 1500, // CHECK: [[DBG_GLBL_DTOR_B]] = !{i32 1500, +// CHECK: [[DBG_F11]] = !{i32 1200, +// CHECK: [[DBG_F12]] = !{i32 1300, +// CHECK: [[DBG_F13]] = !{i32 1400, diff --git a/clang/test/CodeGenCXX/debug-info-scope.cpp b/clang/test/CodeGenCXX/debug-info-scope.cpp index f72c4aa..e66588d 100644 --- a/clang/test/CodeGenCXX/debug-info-scope.cpp +++ b/clang/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: = !{!"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 ] + // 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 ] bool b = i % 2; } -- 2.7.4