llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-modules
Author: Yeoul Na (rapidsna)
<details>
<summary>Changes</summary>
New tests exercising the late-parse fill-in mechanism:
- Sema/attr-counted-by-weird-type-positions{,-late-parsed}.c: counted_by
in assorted type positions, nested pointers, and rejection cases.
- Sema/attr-bounds-safety-function-ptr-param.c: attributes on
function-pointer-typed members.
- Modules/ and PCH/ bounds-safety-attributed-type-late-parsed: the
resolved type round-trips through serialization.
- Sema/attr-counted-by-late-parsed-regressions.c: guards against the
double-free on a nested-record decl-spec attribute and the null-count
escape on a free-function parameter.
---
Patch is 57.71 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/224553.diff
10 Files Affected:
- (added) clang/test/AST/attr-counted-by-eager-invalid-strip.c (+27)
- (added) clang/test/AST/attr-counted-by-late-parsed-invalid-recovery.c (+46)
- (modified) clang/test/AST/attr-counted-by-late-parsed-struct-ptrs.c (+19)
- (added) clang/test/Modules/bounds-safety-attributed-type-late-parsed.c (+111)
- (added) clang/test/PCH/Inputs/bounds-safety-attributed-type-late-parsed.h
(+58)
- (added) clang/test/PCH/bounds-safety-attributed-type-late-parsed.c (+69)
- (added) clang/test/Sema/attr-bounds-safety-function-ptr-param.c (+173)
- (added) clang/test/Sema/attr-counted-by-late-parsed-regressions.c (+92)
- (added) clang/test/Sema/attr-counted-by-weird-type-positions-late-parsed.c
(+456)
- (added) clang/test/Sema/attr-counted-by-weird-type-positions.c (+454)
``````````diff
diff --git a/clang/test/AST/attr-counted-by-eager-invalid-strip.c
b/clang/test/AST/attr-counted-by-eager-invalid-strip.c
new file mode 100644
index 0000000000000..51cd306aa1970
--- /dev/null
+++ b/clang/test/AST/attr-counted-by-eager-invalid-strip.c
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -verify %s -ast-dump | FileCheck %s
+
+// On the eager (non -fexperimental-late-parse-attributes) path a
+// counted_by-family CountAttributedType is built during type processing,
before
+// the FieldDecl-dependent checks run in ActOnFields. When those checks reject
+// the attribute, the CountAttributedType must be stripped so the field keeps
+// its plain wrapped type -- matching the pre-refactor behavior, which built
the
+// type only after the check passed. A surviving bogus CountAttributedType
would
+// otherwise flow downstream. This test pins the stripped type; the diagnostics
+// themselves are covered elsewhere.
+
+#define __counted_by(f) __attribute__((counted_by(f)))
+
+union invalid_union_member {
+ int n;
+ int *__counted_by(n) p; // expected-error {{'counted_by' cannot be applied
to a union member}}
+};
+// CHECK-LABEL: union invalid_union_member definition
+// CHECK: FieldDecl {{.*}} p 'int *'{{$}}
+
+struct invalid_non_fam_array {
+ int n;
+ int arr[10] __counted_by(n); // expected-error {{'counted_by' on arrays only
applies to C99 flexible array members}}
+ int last;
+};
+// CHECK-LABEL: struct invalid_non_fam_array definition
+// CHECK: FieldDecl {{.*}} arr 'int[10]'{{$}}
diff --git a/clang/test/AST/attr-counted-by-late-parsed-invalid-recovery.c
b/clang/test/AST/attr-counted-by-late-parsed-invalid-recovery.c
new file mode 100644
index 0000000000000..776f8422ad0fc
--- /dev/null
+++ b/clang/test/AST/attr-counted-by-late-parsed-invalid-recovery.c
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -fexperimental-late-parse-attributes -verify %s -ast-dump |
FileCheck %s
+
+// On the late-parsed path the CountAttributedType is built before its count
+// argument is parsed, so a rejected argument is only discovered at completion,
+// when the node is already embedded in the field's type. Rather than strip a
+// (possibly nested) node -- which would force the enclosing types to be
rebuilt
+// -- the node is kept and completed in place with the raw argument, and the
+// field is marked invalid. Consumers bail on such a count (see
+// FieldDecl::findCountedByField). This applies whether the argument is
unusable
+// (a parse failure, or a non-declaration-reference such as `sizeof(...)`) or
is
+// a valid reference in an invalid position (a union member).
+//
+// A nested counted_by is the exception: it is diagnosed and dropped while the
+// declarator is built -- before the enclosing pointer/array wraps the node, so
+// the drop needs no rebuild -- leaving the field its plain wrapped type,
exactly
+// as on the eager path.
+
+#define __counted_by(f) __attribute__((counted_by(f)))
+
+// Non-declaration-reference argument: the node is kept with the raw argument
as
+// its count and the field is marked invalid.
+struct bad_count_expr {
+ int n;
+ int *__counted_by(sizeof(int)) p; // expected-error {{'counted_by' argument
must be a simple declaration reference}}
+};
+// CHECK-LABEL: struct bad_count_expr definition
+// CHECK: FieldDecl {{.*}} invalid p 'int * __counted_by(sizeof(int))':'int *'
+
+// Valid reference in an invalid position: also kept with the raw argument and
+// the field marked invalid.
+union valid_ref_bad_position {
+ int n;
+ int *__counted_by(n) p; // expected-error {{'counted_by' cannot be applied
to a union member}}
+};
+// CHECK-LABEL: union valid_ref_bad_position definition
+// CHECK: FieldDecl {{.*}} invalid p 'int * __counted_by(n)':'int *'
+
+// Nested under another pointer: diagnosed and dropped while the declarator is
+// built, so the field keeps its plain wrapped type (no CountAttributedType)
and
+// stays valid -- exactly as on the eager path.
+struct nested_under_pointer {
+ int n;
+ int *__counted_by(n) *pp; // expected-error {{'counted_by' attribute on
nested pointer type is not allowed}}
+};
+// CHECK-LABEL: struct nested_under_pointer definition
+// CHECK: FieldDecl {{.*}} pp 'int **'{{$}}
diff --git a/clang/test/AST/attr-counted-by-late-parsed-struct-ptrs.c
b/clang/test/AST/attr-counted-by-late-parsed-struct-ptrs.c
index f9772db8b6554..9d43523bf3180 100644
--- a/clang/test/AST/attr-counted-by-late-parsed-struct-ptrs.c
+++ b/clang/test/AST/attr-counted-by-late-parsed-struct-ptrs.c
@@ -43,3 +43,22 @@ struct on_pointer_anon_count {
//
// See `clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs.c` for test
// cases.
+
+//==============================================================================
+// A declaration-specifier-position attribute shared by several declarators
+//==============================================================================
+// All declarators share one CountAttributedType, so every field must print a
+// resolved count. Previously only the last one did: each declarator built its
+// own (un-uniqued) node and only the last was ever completed, leaving the
+// earlier fields with an empty '__counted_by()'.
+
+typedef int *ptr_ty;
+
+struct shared_declspec_attr {
+ int count;
+ ptr_ty __counted_by(count) a, b;
+};
+// CHECK-LABEL: struct shared_declspec_attr definition
+// CHECK-NEXT: |-FieldDecl {{.*}} referenced count 'int'
+// CHECK-NEXT: |-FieldDecl {{.*}} a 'ptr_ty __counted_by(count)':'int *'
+// CHECK-NEXT: `-FieldDecl {{.*}} b 'ptr_ty __counted_by(count)':'int *'
diff --git a/clang/test/Modules/bounds-safety-attributed-type-late-parsed.c
b/clang/test/Modules/bounds-safety-attributed-type-late-parsed.c
new file mode 100644
index 0000000000000..58df0761f2022
--- /dev/null
+++ b/clang/test/Modules/bounds-safety-attributed-type-late-parsed.c
@@ -0,0 +1,111 @@
+// Test serialization of late-parsed bounds-safety attributes via Modules
+// This verifies that LateParsedAttrType is transformed to CountAttributedType
+// before serialization and remains as CountAttributedType after
deserialization.
+
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fexperimental-late-parse-attributes -fmodules
-fmodules-cache-path=%t -verify %s
+// RUN: %clang_cc1 -fexperimental-late-parse-attributes -fmodules
-fmodules-cache-path=%t -ast-dump-all %s | FileCheck %s
+// expected-no-diagnostics
+
+#pragma clang module build bounds_safety_late_parsed
+module bounds_safety_late_parsed {}
+#pragma clang module contents
+#pragma clang module begin bounds_safety_late_parsed
+
+// Test where counted_by references a field declared later
+struct LateRefPointer {
+ int *__attribute__((counted_by(count))) buf;
+ int count;
+};
+
+// Test with sized_by referencing later field
+struct LateRefSized {
+ int *__attribute__((sized_by(size))) data;
+ int size;
+};
+
+// Test with counted_by_or_null referencing later field
+struct LateRefCountedByOrNull {
+ int *__attribute__((counted_by_or_null(count))) buf;
+ int count;
+};
+
+// Test with sized_by_or_null referencing later field
+struct LateRefSizedByOrNull {
+ int *__attribute__((sized_by_or_null(size))) data;
+ int size;
+};
+
+// Test with nested struct
+struct LateRefNested {
+ struct Inner {
+ int value;
+ } *__attribute__((counted_by(n))) items;
+ int n;
+};
+
+// Test with multiple late-parsed attributes
+struct MultipleLateRefs {
+ int *__attribute__((counted_by(count1))) buf1;
+ int *__attribute__((sized_by(count2))) buf2;
+ int *__attribute__((counted_by_or_null(count3))) buf3;
+ int *__attribute__((sized_by_or_null(count4))) buf4;
+ int count1;
+ int count2;
+ int count3;
+ int count4;
+};
+
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module import bounds_safety_late_parsed
+
+struct LateRefPointer *p1;
+struct LateRefSized *p2;
+struct LateRefCountedByOrNull *p3;
+struct LateRefSizedByOrNull *p4;
+struct LateRefNested *p5;
+struct MultipleLateRefs *p6;
+
+// CHECK: RecordDecl {{.*}} imported in bounds_safety_late_parsed
<undeserialized declarations> struct LateRefPointer definition
+// CHECK-NEXT: |-FieldDecl {{.*}} imported in bounds_safety_late_parsed buf
'int * __counted_by(count)':'int *'
+// CHECK-NEXT: `-FieldDecl {{.*}} imported in bounds_safety_late_parsed
referenced count 'int'
+
+// CHECK: RecordDecl {{.*}} imported in bounds_safety_late_parsed
<undeserialized declarations> struct LateRefSized definition
+// CHECK-NEXT: |-FieldDecl {{.*}} imported in bounds_safety_late_parsed data
'int * __sized_by(size)':'int *'
+// CHECK-NEXT: `-FieldDecl {{.*}} imported in bounds_safety_late_parsed
referenced size 'int'
+
+// CHECK: RecordDecl {{.*}} imported in bounds_safety_late_parsed
<undeserialized declarations> struct LateRefCountedByOrNull definition
+// CHECK-NEXT: |-FieldDecl {{.*}} imported in bounds_safety_late_parsed buf
'int * __counted_by_or_null(count)':'int *'
+// CHECK-NEXT: `-FieldDecl {{.*}} imported in bounds_safety_late_parsed
referenced count 'int'
+
+// CHECK: RecordDecl {{.*}} imported in bounds_safety_late_parsed
<undeserialized declarations> struct LateRefSizedByOrNull definition
+// CHECK-NEXT: |-FieldDecl {{.*}} imported in bounds_safety_late_parsed data
'int * __sized_by_or_null(size)':'int *'
+// CHECK-NEXT: `-FieldDecl {{.*}} imported in bounds_safety_late_parsed
referenced size 'int'
+
+// CHECK: RecordDecl {{.*}} imported in bounds_safety_late_parsed
<undeserialized declarations> struct LateRefNested definition
+// CHECK: |-FieldDecl {{.*}} imported in bounds_safety_late_parsed items
'struct Inner * __counted_by(n)':'struct Inner *'
+// CHECK: `-FieldDecl {{.*}} imported in bounds_safety_late_parsed referenced
n 'int'
+
+// CHECK: RecordDecl {{.*}} imported in bounds_safety_late_parsed
<undeserialized declarations> struct MultipleLateRefs definition
+// CHECK-NEXT: |-FieldDecl {{.*}} imported in bounds_safety_late_parsed buf1
'int * __counted_by(count1)':'int *'
+// CHECK-NEXT: |-FieldDecl {{.*}} imported in bounds_safety_late_parsed buf2
'int * __sized_by(count2)':'int *'
+// CHECK-NEXT: |-FieldDecl {{.*}} imported in bounds_safety_late_parsed buf3
'int * __counted_by_or_null(count3)':'int *'
+// CHECK-NEXT: |-FieldDecl {{.*}} imported in bounds_safety_late_parsed buf4
'int * __sized_by_or_null(count4)':'int *'
+// CHECK-NEXT: |-FieldDecl {{.*}} imported in bounds_safety_late_parsed
referenced count1 'int'
+// CHECK-NEXT: |-FieldDecl {{.*}} imported in bounds_safety_late_parsed
referenced count2 'int'
+// CHECK-NEXT: |-FieldDecl {{.*}} imported in bounds_safety_late_parsed
referenced count3 'int'
+// CHECK-NEXT: `-FieldDecl {{.*}} imported in bounds_safety_late_parsed
referenced count4 'int'
+
+// Verify that LateParsedAttrType does not appear in the AST dump
+// CHECK-NOT: LateParsedAttr
+
+// Verify the import and variable declarations
+// CHECK: ImportDecl {{.*}} implicit bounds_safety_late_parsed
+// CHECK: VarDecl {{.*}} p1 'struct LateRefPointer *'
+// CHECK: VarDecl {{.*}} p2 'struct LateRefSized *'
+// CHECK: VarDecl {{.*}} p3 'struct LateRefCountedByOrNull *'
+// CHECK: VarDecl {{.*}} p4 'struct LateRefSizedByOrNull *'
+// CHECK: VarDecl {{.*}} p5 'struct LateRefNested *'
+// CHECK: VarDecl {{.*}} p6 'struct MultipleLateRefs *'
diff --git a/clang/test/PCH/Inputs/bounds-safety-attributed-type-late-parsed.h
b/clang/test/PCH/Inputs/bounds-safety-attributed-type-late-parsed.h
new file mode 100644
index 0000000000000..c0751408045c7
--- /dev/null
+++ b/clang/test/PCH/Inputs/bounds-safety-attributed-type-late-parsed.h
@@ -0,0 +1,58 @@
+// Header for testing late-parsed bounds-safety attributes serialization
+
+#define __counted_by(f) __attribute__((counted_by(f)))
+#define __sized_by(f) __attribute__((sized_by(f)))
+#define __counted_by_or_null(f) __attribute__((counted_by_or_null(f)))
+#define __sized_by_or_null(f) __attribute__((sized_by_or_null(f)))
+
+// Test where counted_by references a field declared later
+struct LateRefPointer {
+ int *__counted_by(count) buf;
+ int count;
+};
+
+// Test with sized_by referencing later field
+struct LateRefSized {
+ int *__sized_by(size) data;
+ int size;
+};
+
+// Test with counted_by_or_null referencing later field
+struct LateRefCountedByOrNull {
+ int *__counted_by_or_null(count) buf;
+ int count;
+};
+
+// Test with sized_by_or_null referencing later field
+struct LateRefSizedByOrNull {
+ int *__sized_by_or_null(size) data;
+ int size;
+};
+
+// Test with nested struct
+struct LateRefNested {
+ struct Inner {
+ int value;
+ } *__counted_by(n) items;
+ int n;
+};
+
+// Test with multiple late-parsed attributes
+struct MultipleLateRefs {
+ int *__counted_by(count1) buf1;
+ int *__sized_by(count2) buf2;
+ int *__counted_by_or_null(count3) buf3;
+ int *__sized_by_or_null(count4) buf4;
+ int count1;
+ int count2;
+ int count3;
+ int count4;
+};
+
+// Test with anonymous struct/union
+struct LateRefAnon {
+ int *__counted_by(count) buf;
+ struct {
+ int count;
+ };
+};
diff --git a/clang/test/PCH/bounds-safety-attributed-type-late-parsed.c
b/clang/test/PCH/bounds-safety-attributed-type-late-parsed.c
new file mode 100644
index 0000000000000..1d77bbe13927c
--- /dev/null
+++ b/clang/test/PCH/bounds-safety-attributed-type-late-parsed.c
@@ -0,0 +1,69 @@
+// Test serialization of late-parsed bounds-safety attributes via PCH
+// This verifies that LateParsedAttrType is transformed to CountAttributedType
+// before serialization and remains as CountAttributedType after
deserialization.
+
+// RUN: %clang_cc1 -fexperimental-late-parse-attributes -include
%S/Inputs/bounds-safety-attributed-type-late-parsed.h -fsyntax-only -verify %s
+
+// Test with pch.
+// RUN: %clang_cc1 -fexperimental-late-parse-attributes -emit-pch -o %t
%S/Inputs/bounds-safety-attributed-type-late-parsed.h
+// RUN: %clang_cc1 -fexperimental-late-parse-attributes -include-pch %t
-fsyntax-only -verify %s
+// RUN: %clang_cc1 -fexperimental-late-parse-attributes -include-pch %t
-ast-print %s | FileCheck %s --check-prefix PRINT
+// RUN: %clang_cc1 -fexperimental-late-parse-attributes -include-pch %t
-ast-dump-all %s | FileCheck %s --check-prefix DUMP
+// expected-no-diagnostics
+
+// PRINT: struct LateRefPointer {
+// PRINT-NEXT: int * __counted_by(count)buf;
+// PRINT-NEXT: int count;
+// PRINT-NEXT: };
+
+// PRINT: struct LateRefSized {
+// PRINT-NEXT: int * __sized_by(size)data;
+// PRINT-NEXT: int size;
+// PRINT-NEXT: };
+
+// PRINT: struct LateRefCountedByOrNull {
+// PRINT-NEXT: int * __counted_by_or_null(count)buf;
+// PRINT-NEXT: int count;
+// PRINT-NEXT: };
+
+// PRINT: struct LateRefSizedByOrNull {
+// PRINT-NEXT: int * __sized_by_or_null(size)data;
+// PRINT-NEXT: int size;
+// PRINT-NEXT: };
+
+// DUMP: RecordDecl {{.*}} imported <undeserialized declarations> struct
LateRefPointer definition
+// DUMP-NEXT: |-FieldDecl {{.*}} imported buf 'int * __counted_by(count)':'int
*'
+// DUMP-NEXT: `-FieldDecl {{.*}} imported referenced count 'int'
+
+// DUMP: RecordDecl {{.*}} imported <undeserialized declarations> struct
LateRefSized definition
+// DUMP-NEXT: |-FieldDecl {{.*}} imported data 'int * __sized_by(size)':'int *'
+// DUMP-NEXT: `-FieldDecl {{.*}} imported referenced size 'int'
+
+// DUMP: RecordDecl {{.*}} imported <undeserialized declarations> struct
LateRefCountedByOrNull definition
+// DUMP-NEXT: |-FieldDecl {{.*}} imported buf 'int *
__counted_by_or_null(count)':'int *'
+// DUMP-NEXT: `-FieldDecl {{.*}} imported referenced count 'int'
+
+// DUMP: RecordDecl {{.*}} imported <undeserialized declarations> struct
LateRefSizedByOrNull definition
+// DUMP-NEXT: |-FieldDecl {{.*}} imported data 'int *
__sized_by_or_null(size)':'int *'
+// DUMP-NEXT: `-FieldDecl {{.*}} imported referenced size 'int'
+
+// DUMP: RecordDecl {{.*}} imported <undeserialized declarations> struct
LateRefNested definition
+// DUMP: |-FieldDecl {{.*}} imported items 'struct Inner *
__counted_by(n)':'struct Inner *'
+// DUMP: `-FieldDecl {{.*}} imported referenced n 'int'
+
+// DUMP: RecordDecl {{.*}} imported <undeserialized declarations> struct
MultipleLateRefs definition
+// DUMP-NEXT: |-FieldDecl {{.*}} imported buf1 'int *
__counted_by(count1)':'int *'
+// DUMP-NEXT: |-FieldDecl {{.*}} imported buf2 'int * __sized_by(count2)':'int
*'
+// DUMP-NEXT: |-FieldDecl {{.*}} imported buf3 'int *
__counted_by_or_null(count3)':'int *'
+// DUMP-NEXT: |-FieldDecl {{.*}} imported buf4 'int *
__sized_by_or_null(count4)':'int *'
+// DUMP-NEXT: |-FieldDecl {{.*}} imported referenced count1 'int'
+// DUMP-NEXT: |-FieldDecl {{.*}} imported referenced count2 'int'
+// DUMP-NEXT: |-FieldDecl {{.*}} imported referenced count3 'int'
+// DUMP-NEXT: `-FieldDecl {{.*}} imported referenced count4 'int'
+
+// DUMP: RecordDecl {{.*}} imported <undeserialized declarations> struct
LateRefAnon definition
+// DUMP-NEXT: |-FieldDecl {{.*}} imported buf 'int * __counted_by(count)':'int
*'
+// DUMP: `-IndirectFieldDecl {{.*}} imported implicit referenced count 'int'
+
+// Verify that LateParsedAttrType does not appear in the AST dump
+// DUMP-NOT: LateParsedAttr
diff --git a/clang/test/Sema/attr-bounds-safety-function-ptr-param.c
b/clang/test/Sema/attr-bounds-safety-function-ptr-param.c
new file mode 100644
index 0000000000000..091220e313958
--- /dev/null
+++ b/clang/test/Sema/attr-bounds-safety-function-ptr-param.c
@@ -0,0 +1,173 @@
+// XFAIL: *
+// FIXME: https://github.com/llvm/llvm-project/issues/166454
+
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fexperimental-late-parse-attributes -fsyntax-only -verify
%s
+
+#define __counted_by(N) __attribute__((counted_by(N)))
+#define __counted_by_or_null(N) __attribute__((counted_by_or_null(N)))
+#define __sized_by(N) __attribute__((sized_by(N)))
+#define __sized_by_or_null(N) __attribute__((sized_by_or_null(N)))
+
+//==============================================================================
+// Test bounds safety attributes on function pointer parameters
+//==============================================================================
+
+struct counted_by_function_pointer_param {
+ // expected-error@+1{{'counted_by' attribute cannot be applied to a
parameter in a function pointer type}}
+ int (*callback)(int *__counted_by(len));
+ int len;
+};
+
+struct counted_by_or_null_function_pointer_param {
+ // expected-error@+1{{'counted_by_or_null' attribute cannot be applied to a
parameter in a function pointer type}}
+ int (*callback)(int *__counted_by_or_null(len));
+ int len;
+};
+
+struct sized_by_function_pointer_param {
+ // expected-error@+1{{'sized_by' attribute cannot be applied to a parameter
in a function pointer type}}
+ int (*callback)(char *__sized_by(len));
+ int len;
+};
+
+struct sized_by_or_null_function_pointer_param {
+ // expected-error@+1{{'sized_by_or_null' attribute cannot be applied to a
parameter in a function pointer type}}
+ int (*callback)(char *__sized_by_or_null(len));
+ int len;
+};
+
+//==============================================================================
+// Test multiple parameters with bounds safety attributes
+//==============================================================================
+
+struct multiple_params_with_bounds_safety {
+ // expected-error@+1{{'counted_by' attribute cannot be applied to a
parameter in a function pointer type}}
+ int (*multi_callback)(int *__counted_by(len1), char *data, int len1);
+ int len1;
+};
+
+struct mixed_bounds_safety_params {
+ // expected-error@+2{{'counted_by' attribute cannot be applied to a
parameter in a function pointer type}}
+ // expected-error@+1{{'sized_by_or_null' attribute cannot be applied to a
parameter in a function pointer type}}
+ int (*mixed_callback)(int *__counted_by(count), char
*__sized_by_or_null(size), int count, int size);
+ int count;
+ int size;
+};
+
+//==============================================================================
+// Test cases that do not require late parsing (count field defined before use)
+//==============================================================================
+
+struct counted_by_no_late_parse {
+ int len;
+ // expected-error@+1{{'counted_by' attribute cannot be applied to a
parameter in a function pointer type}}
+ int (*callback)(int *__counted_by(len));
+};
+
+struct counted_by_or_null_no_late_parse {
+ int len;
+ // expected-error@+1{{'counted_by_or_null' attribute cannot be applied to a
parameter in a function pointer type}}
+ int (*callback)(int *__counted_by_or_null(len...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/224553
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits