diff options
| author | David Blaikie <dblaikie@gmail.com> | 2025-09-02 14:03:58 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-02 21:03:58 +0000 |
| commit | 665e875f1a86be650e044bb20744bb272d03e11d (patch) | |
| tree | 4a28f777685bd58931a11a684e6f89c003832946 /clang/lib/CodeGen/CGExpr.cpp | |
| parent | 3c7bf3b3c3a4871d13f7b7d5d60bbf190eaf8f3a (diff) | |
[DebugInfo] When referencing structured bindings use the reference's location, not the binding's declaration's location (#153637)
For structured bindings that use custom `get` specializations, the
resulting LLVM IR ascribes the load of the result of `get` to the
binding's declaration, rather than the place where the binding is
referenced - this caused awkward sequencing in the debug info where,
when stepping through the code you'd step back to the binding
declaration every time there was a reference to the binding.
To fix that - when we cross into IRGening a binding - suppress the debug
info location of that subexpression.
I don't represent this as a great bit of API design - certainly open to
ideas, but putting it out here as a place to start.
It's /possible/ this is an incomplete fix, even - if the binding decl
had other subexpressions, those would still get their location applied &
it'd likely be wrong.
So maybe that's a direction to go with to productionize this - add a new
location scoped device that suppresses any overriding - this might be
more robust. How do people feel about that?
Diffstat (limited to 'clang/lib/CodeGen/CGExpr.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 844b445b98c1..26fba751e6f9 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3387,7 +3387,14 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { auto *FD = LambdaCaptureFields.lookup(BD); return EmitCapturedFieldLValue(*this, FD, CXXABIThisValue); } - return EmitLValue(BD->getBinding()); + // Suppress debug location updates when visiting the binding, since the + // binding may emit instructions that would otherwise be associated with the + // binding itself, rather than the expression referencing the binding. (this + // leads to jumpy debug stepping behavior where the location/debugger jump + // back to the binding declaration, then back to the expression referencing + // the binding) + DisableDebugLocationUpdates D(*this); + return EmitLValue(BD->getBinding(), NotKnownNonNull); } // We can form DeclRefExprs naming GUID declarations when reconstituting |
