[clang] [clang][DebugInfo] Attribute beginning of catch to opening brace (PR #177032)
Aaron Puchert via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 21 09:51:32 PDT 2026
https://github.com/aaronpuchert updated https://github.com/llvm/llvm-project/pull/177032
>From c802fd53a8eabf29ece2711dde12d767e3e748dc Mon Sep 17 00:00:00 2001
From: Aaron Puchert <aaron.puchert at sap.com>
Date: Tue, 20 Jan 2026 22:47:02 +0100
Subject: [PATCH] [clang][DebugInfo] Attribute beginning of catch to opening
brace
It was previously attributed to the end of the last catch or the end of
the try block. Attributing it to the beginning of the right catch block
is especially interesting when e.g. using `catch catch` in GDB.
Fixes #164414.
---
clang/lib/CodeGen/CGException.cpp | 3 ++
clang/test/DebugInfo/CXX/try-catch.cpp | 42 ++++++++++++++++++++++++++
2 files changed, 45 insertions(+)
create mode 100644 clang/test/DebugInfo/CXX/try-catch.cpp
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp
index b0fb3b4d85d15..a4f3225c9c0c4 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -1283,6 +1283,9 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
// Catch the exception if this isn't a catch-all.
const CXXCatchStmt *C = S.getHandler(I-1);
+ ApplyDebugLocation DebugLoc = ApplyDebugLocation::CreateDefaultArtificial(
+ *this, C->getHandlerBlock()->getBeginLoc());
+
// Enter a cleanup scope, including the catch variable and the
// end-catch.
RunCleanupsScope CatchScope(*this);
diff --git a/clang/test/DebugInfo/CXX/try-catch.cpp b/clang/test/DebugInfo/CXX/try-catch.cpp
new file mode 100644
index 0000000000000..4cc33617078b4
--- /dev/null
+++ b/clang/test/DebugInfo/CXX/try-catch.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -o- %s | FileCheck %s
+
+#line 100
+int main() {
+ try {
+ throw 0;
+ } catch (bool) {
+ return 0;
+ } catch (int) {
+ return 1;
+ }
+}
+
+// CHECK: %{{.*}} = landingpad { ptr, i32 }
+// CHECK-NEXT: catch ptr @_ZTIb
+// CHECK-NEXT: catch ptr @_ZTIi, !dbg [[LPAD:![0-9]*]]
+// CHECK: br label %[[DISP:.*]], !dbg [[LPAD]]
+// CHECK: [[DISP]]:
+// CHECK-NEXT: %{{.*}} = load i32, ptr %{{.*}}, align 4, !dbg [[DISPATCH:![0-9]*]]
+// CHECK-NEXT: [[TIBOOL:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIb) #{{[0-9]+}}, !dbg [[DISPATCH]]
+// CHECK-NEXT: [[ISBOOL:%.*]] = icmp eq i32 %{{.*}}, [[TIBOOL]], !dbg [[DISPATCH]]
+// CHECK-NEXT: br i1 [[ISBOOL]], label %[[CATCHBOOL:.*]], label %[[FALLTHROUGH:.*]], !dbg [[DISPATCH]]
+// CHECK: [[CATCHBOOL]]
+// CHECK: %{{.*}} = call ptr @__cxa_begin_catch(ptr %{{.*}}) #{{[0-9]+}}, !dbg [[BEGINCATCHBOOL:![0-9]*]]
+// CHECK: call void @__cxa_end_catch() #{{[0-9]+}}, !dbg [[ENDCATCHBOOL:![0-9]*]]
+// CHECK: [[FALLTHROUGH]]:
+// CHECK-NEXT: [[TIINT:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) #{{[0-9]+}}, !dbg [[DISPATCH]]
+// CHECK-NEXT: [[ISINT:%.*]] = icmp eq i32 %{{.*}}, [[TIINT]], !dbg [[DISPATCH]]
+// CHECK-NEXT: br i1 [[ISINT]], label %[[CATCHINT:.*]], label %[[RESUME:.*]], !dbg [[DISPATCH]]
+// CHECK: [[CATCHINT]]:
+// CHECK: %{{.*}} = call ptr @__cxa_begin_catch(ptr %{{.*}}) #{{[0-9]+}}, !dbg [[BEGINCATCHINT:![0-9]*]]
+// CHECK: call void @__cxa_end_catch() #{{[0-9]+}}, !dbg [[ENDCATCHINT:![0-9]*]]
+// CHECK: [[RESUME]]:
+// CHECK: resume { ptr, i32 } %{{.*}}, !dbg [[DISPATCH]]
+
+// TODO: LPAD is arguably off.
+// CHECK-DAG: [[LPAD]] = !DILocation(line: 108, column: 1, scope: !{{[0-9]+}})
+// CHECK-DAG: [[DISPATCH]] = !DILocation(line: 103, column: 3, scope: !{{[0-9]+}})
+// CHECK-DAG: [[BEGINCATCHBOOL]] = !DILocation(line: 103, column: 18, scope: !{{[0-9]+}})
+// CHECK-DAG: [[ENDCATCHBOOL]] = !DILocation(line: 105, column: 3, scope: !{{[0-9]+}})
+// CHECK-DAG: [[BEGINCATCHINT]] = !DILocation(line: 105, column: 17, scope: !{{[0-9]+}})
+// CHECK-DAG: [[ENDCATCHINT]] = !DILocation(line: 107, column: 3, scope: !{{[0-9]+}})
More information about the cfe-commits
mailing list