[clang] [Clang][counted-by][NFC] Add testcase for non-forward record decl (PR #153338)
Bill Wendling via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 5 10:12:58 PST 2026
https://github.com/bwendling updated https://github.com/llvm/llvm-project/pull/153338
>From 34f8ba7f20f0d5c7ea5646ac39ababc85667e9d5 Mon Sep 17 00:00:00 2001
From: Bill Wendling <morbo at google.com>
Date: Tue, 12 Aug 2025 19:53:11 -0700
Subject: [PATCH 1/2] [Clang][counted-by][NFC] Add testcase for non-forward
record decl
This tests that we don't ICE if a struct hasn't been forward declared.
Originally fixed in https://github.com/llvm/llvm-project/commit/160fb1121cdf703c3ef5e61fb26c5659eb581489
Link: https://github.com/clangbuiltlinux/linux/issues/2114
---
clang/test/CodeGen/attr-counted-by.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/clang/test/CodeGen/attr-counted-by.c b/clang/test/CodeGen/attr-counted-by.c
index 59e1b134850a9..cc11410c957bb 100644
--- a/clang/test/CodeGen/attr-counted-by.c
+++ b/clang/test/CodeGen/attr-counted-by.c
@@ -2481,3 +2481,20 @@ size_t test36() {
size_t test37(struct annotated *ptr) {
return __builtin_dynamic_object_size((1, 2, (4, 5, (7, 8, 9, (10, ptr->array)))), 1);
}
+
+// Don't abort when a structure isn't forward declared. This was fixed in
+// 160fb11.
+// See https://github.com/clangbuiltlinux/linux/issues/2114
+
+struct baz;
+
+struct foo {
+ unsigned short width;
+ struct bar *no_forward_decl;
+ struct baz *array[] __attribute__((__counted_by__(width)));
+};
+
+struct baz *test38(struct foo *q)
+{
+ return q->array[0];
+}
>From 1f4cd00f82408ca0ce0dac49b3a64aceaff41347 Mon Sep 17 00:00:00 2001
From: Bill Wendling <morbo at google.com>
Date: Tue, 12 Aug 2025 19:57:24 -0700
Subject: [PATCH 2/2] Generate checking code.
---
clang/test/CodeGen/attr-counted-by.c | 42 ++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/clang/test/CodeGen/attr-counted-by.c b/clang/test/CodeGen/attr-counted-by.c
index cc11410c957bb..b16c044869569 100644
--- a/clang/test/CodeGen/attr-counted-by.c
+++ b/clang/test/CodeGen/attr-counted-by.c
@@ -2494,6 +2494,48 @@ struct foo {
struct baz *array[] __attribute__((__counted_by__(width)));
};
+// SANITIZE-WITH-ATTR-LABEL: define dso_local ptr @test38(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[Q:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITH-ATTR-NEXT: entry:
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i16, ptr [[Q]], align 4
+// SANITIZE-WITH-ATTR-NEXT: [[DOTNOT:%.*]] = icmp eq i16 [[DOTCOUNTED_BY_LOAD]], 0
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[DOTNOT]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], label [[CONT3:%.*]], !prof [[PROF8]], !nosanitize [[META2]]
+// SANITIZE-WITH-ATTR: handler.out_of_bounds:
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB55:[0-9]+]], i64 0) #[[ATTR8]], !nosanitize [[META2]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]]
+// SANITIZE-WITH-ATTR: cont3:
+// SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 16
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAY]], align 8, !tbaa [[TBAA27:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: ret ptr [[TMP0]]
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local ptr @test38(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr noundef readonly captures(none) [[Q:%.*]]) local_unnamed_addr #[[ATTR2]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: entry:
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 16
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAY]], align 8, !tbaa [[TBAA24:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret ptr [[TMP0]]
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local ptr @test38(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[Q:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: entry:
+// SANITIZE-WITHOUT-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i16, ptr [[Q]], align 4
+// SANITIZE-WITHOUT-ATTR-NEXT: [[DOTNOT:%.*]] = icmp eq i16 [[DOTCOUNTED_BY_LOAD]], 0
+// SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[DOTNOT]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], label [[CONT3:%.*]], !prof [[PROF10]], !nosanitize [[META9]]
+// SANITIZE-WITHOUT-ATTR: handler.out_of_bounds:
+// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB23:[0-9]+]], i64 0) #[[ATTR8]], !nosanitize [[META9]]
+// SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]]
+// SANITIZE-WITHOUT-ATTR: cont3:
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 16
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAY]], align 8, !tbaa [[TBAA27:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: ret ptr [[TMP0]]
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local ptr @test38(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef readonly captures(none) [[Q:%.*]]) local_unnamed_addr #[[ATTR6]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry:
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 16
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAY]], align 8, !tbaa [[TBAA24:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret ptr [[TMP0]]
+//
struct baz *test38(struct foo *q)
{
return q->array[0];
More information about the cfe-commits
mailing list