Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 17 additions & 17 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -12581,7 +12581,7 @@ let CategoryName = "BoundsSafety Pointer Attributes Issue" in {
def err_bounds_safety_conflicting_pointer_attributes : Error<
"%select{array|pointer}0 cannot have more than one %select{bound|type|count|end|terminator}1 attribute">;
def note_bounds_safety_conflicting_pointer_attribute_args : Note<
"conflicting arguments for %select{count|end|terminator}0 were '%1' and '%2'">;
"conflicting arguments for %select{count|end|terminator}0 were %1 and %2">;
def warn_bounds_safety_duplicate_pointer_attributes : Warning<
"%select{array|pointer}0 annotated with %select{__unsafe_indexable|__bidi_indexable|__indexable|__single|__terminated_by}1 "
"multiple times. Annotate only once to remove this warning">, InGroup<BoundsSafetyRedundantAttribute>;
Expand All @@ -12603,7 +12603,7 @@ def err_bounds_safety_dynamic_count_function_call : Error<
"argument of '%select{__counted_by|__sized_by|__counted_by_or_null|__sized_by_or_null}0' attribute can only reference "
"function with 'const' attribute">;
def err_bounds_safety_dynamic_count_function_call_argument : Error<
"argument of function call '%0' in '%select{__counted_by|__sized_by|__counted_by_or_null|__sized_by_or_null}1' attribute is not a constant expression">;
"argument of function call %0 in '%select{__counted_by|__sized_by|__counted_by_or_null|__sized_by_or_null}1' attribute is not a constant expression">;
def err_attribute_invalid_argument_expression_for_pointer_bounds_attribute : Error<
"invalid argument expression to bounds attribute">;
def err_invalid_decl_kind_bounds_safety_dynamic_count : Error<
Expand Down Expand Up @@ -12761,7 +12761,7 @@ def warn_bounds_safety_conv_single_to_implicit_indexable_unsafe_zeroth_element :
"returning|" // UnsafeOpKind::Return
"passing|" // UnsafeOpKind::CallArg
"UNUSED" // UnsafeOpKind::Cast
"}0 __bidi_indexable '%1'"
"}0 __bidi_indexable %1"
"%select{"
" at any index|||||||}0 "
"will %select{"
Expand All @@ -12774,7 +12774,7 @@ def warn_bounds_safety_conv_single_to_implicit_indexable_unsafe_zeroth_element :
"pass an out-of-bounds pointer|" // UnsafeOpKind::CallArg
"UNUSED" // UnsafeOpKind::Cast
"}0. At runtime %4 is assigned a __single pointer that"
" results in '%1' having bounds smaller than a single %2 (%3 byte%s3)">,
" results in %1 having bounds smaller than a single %2 (%3 byte%s3)">,
InGroup<BoundsSafetyConvSingleToImplicitIndexableThenConvertToLargerType>;

def warn_bounds_safety_conv_single_to_implicit_indexable_unsafely_cast :
Expand All @@ -12800,7 +12800,7 @@ def note_single_entity_assigned_here_with_pointee_sizes : Note<
"struct member|" // AssignmentSourceKind::StructMember
"union member" // AssignmentSourceKind::UnionMember
"}0 %1 %select{assigned to|used to initialize}9 %2 here results in %2 having the bounds of a single %3 "
"(%4 bytes) but %select{'%8'|cast of %2 to %8}7 has pointee type %5 (%6 bytes)">;
"(%4 bytes) but %select{%8|cast of %2 to %8}7 has pointee type %5 (%6 bytes)">;

def warn_bounds_safety_conv_single_to_implicit_indexable_dynamic_count_conversion :
Warning<
Expand Down Expand Up @@ -12899,7 +12899,7 @@ def err_bounds_safety_typeof_dbpt : Error<
"__typeof__ on an expression of type %0 is not yet supported">;

def err_bounds_safety_single_pointer_arithmetic : Error<
"pointer arithmetic on single pointer '%0' is out of bounds%select{|; consider adding '__counted_by' to '%2'}1">;
"pointer arithmetic on single pointer %0 is out of bounds%select{|; consider adding '__counted_by' to '%2'}1">;
def err_bounds_safety_flexible_array_member_record_pointer_arithmetic : Error<
"-fbounds-safety forbids arithmetic on pointers to types with a flexible array "
"member">;
Expand Down Expand Up @@ -12965,16 +12965,16 @@ def err_bounds_safety_counted_by_on_incomplete_type_on_var_decl : Error<
>;

def err_bounds_safety_pointer_subscript : Error<
"array subscript on %select{single|'__terminated_by'}0 pointer '%1' "
"array subscript on %select{single|'__terminated_by'}0 pointer %1 "
"%select{must use a constant index of 0 to be in bounds|is not allowed}0">;
def err_bounds_safety_indexable_pointer_arithmetic : Error<
"decremented indexable pointer '%0' is out of bounds">;
"decremented indexable pointer %0 is out of bounds">;
def err_bounds_safety_indexable_pointer_subscript : Error<
"array subscript with a negative index on indexable pointer '%0' is out of bounds">;
"array subscript with a negative index on indexable pointer %0 is out of bounds">;
def err_bounds_safety_terminated_by_pointer_arithmetic_dec : Error<
"cannot decrement '__terminated_by' pointer '%0'">;
"cannot decrement '__terminated_by' pointer %0">;
def err_bounds_safety_terminated_by_pointer_arithmetic : Error<
"pointer arithmetic on '__terminated_by' pointer '%0' can only increase the "
"pointer arithmetic on '__terminated_by' pointer %0 can only increase the "
"value by one">;

def err_bounds_safety_dynamic_bound_pointer_unary_arithmetic : Error<
Expand Down Expand Up @@ -13073,7 +13073,7 @@ def err_bounds_safety_dependent_assignments_order : Error<
def note_bounds_safety_decl_assignment : Note<
"'%0' has been assigned here">;
def err_bounds_safety_dependent_struct_assignment : Error<
"cannot assign '%0' because it contains field %1 referred to by flexible array member %2">;
"cannot assign %0 because it contains field %1 referred to by flexible array member %2">;
def note_bounds_safety_count_param_loc : Note<
"referred to by count parameter here">;
def err_bounds_safety_dependent_field_duplicates : Error<
Expand All @@ -13083,7 +13083,7 @@ def note_bounds_safety_struct_fields_only_in_fam : Note<
def error_bounds_safety_no_arrow_members : Error<
"arrow notation not allowed for struct member in count parameter">;
def error_bounds_safety_no_count_in_unions : Error<
"count parameter refers to union '%0' of type %1">;
"count parameter refers to union %0 of type %1">;

def err_bounds_safety_taking_address_dynamic_bound_dependent : Error<
"%select{variable|field}1 referred to by '%select{__counted_by|__sized_by|__counted_by_or_null|__sized_by_or_null|__ended_by}0' "
Expand All @@ -13105,7 +13105,7 @@ def err_bounds_safety_incompatible_dynamic_bound_argument: Error<
def err_bounds_safety_mismatching_count_type_argument: Error<
"incompatible pointer types assigning %0 with an expression with mismatching size attributes %1">;
def err_bounds_safety_incompatible_count_expression: Error<
"incompatible count expression (%0) vs. (%1) in argument to function">;
"incompatible count expression %0 vs. %1 in argument to function">;
def err_bounds_safety_unsynchronized_indirect_param: Error<
"passing%select{| address of}1 %0 as an indirect parameter; "
"must also pass %2 %select{|or its address }3because the type of %select{%0|%2}4, "
Expand Down Expand Up @@ -13190,7 +13190,7 @@ def note_bounds_safety_consider_adding_to_return : Note<

def warn_bounds_safety_initlist_range_partial_null : Warning<
"%select{|implicitly }0initializing field %1 of type %2 to NULL while "
"'%3' is initialized with a value rarely succeeds">, InGroup<BoundsSafetyInitListPartialNull>;
"%3 is initialized with a value rarely succeeds">, InGroup<BoundsSafetyInitListPartialNull>;

def err_bounds_safety_dynamic_bound_init_side_effect : Error<
"initalizer for %select{count|size|'__counted_by' pointer|'__sized_by' pointer|'__counted_by_or_null' pointer|'__sized_by_or_null' pointer|'__ended_by' pointer|end pointer}0 with side effects is not yet supported">;
Expand All @@ -13206,7 +13206,7 @@ def err_bounds_safety_flexible_global_wrong_count : Error<
def err_bounds_safety_flexible_global_not_counted : Error<
"flexible array member is initialized without a count">;
def err_bounds_safety_flexible_global_non_int_count_init : Error<
"count '%0' has non-integer value '%1' of type %2">;
"count %0 has non-integer value %1 of type %2">;

def err_bounds_safety_local_external_dynamic_count : Error<
"attribute %0 is not allowed for local variables with external storage">;
Expand Down Expand Up @@ -13399,7 +13399,7 @@ def err_bounds_safety_terminated_by_wrong_initializer_kind : Error<
"string literal or an initializer list">;
def err_bounds_safety_terminated_by_terminator_mismatch : Error<
"array '%0' with '__terminated_by' attribute is initialized with an "
"incorrect terminator (expected: %1; got %2)">;
"incorrect terminator (expected: %quoted1; got %quoted2)">;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems new. Looking at the implementation it looks like this just adds single quotes around the argument. Presumably this is related to llvm#134769 (comment) and now we have double single quotes in the outputted diagnostics?


def err_bounds_safety_irrecoverable_attr : Error<
"bounds attribute '%select{__bidi_indexable|__indexable|__single|__unsafe_indexable}0' cannot be applied to attributed type %1 in this context%select{| due to the surrounding 'typeof' specifier}2">;
Expand Down
4 changes: 2 additions & 2 deletions clang/test/BoundsSafety/AST/struct-init-with-side-effects.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ void test_count_annot() {
struct s_count_annot s1 = {
.len = 10,
.ptr = arr,
// expected-warning@+1{{initializer getlen() has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}}
// expected-warning@+1{{initializer 'getlen()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}}
.dummy = getlen()
};
struct s_count_annot s2;
Expand Down Expand Up @@ -157,7 +157,7 @@ void test_range_annot() {
struct s_range_annot s1 = {
.end = arr + 10,
.start = arr,
// expected-warning@+1{{initializer getlen() has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}}
// expected-warning@+1{{initializer 'getlen()' has a side effect; this may lead to an unexpected result because the evaluation order of initialization list expressions is indeterminate}}
.dummy = getlen()
};
struct s_count_annot s2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,10 @@ void consume(int* __bidi_indexable);
// LEGACY-SAME: i32 noundef [[COUNT:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
// LEGACY-NEXT: [[ENTRY:.*:]]
// LEGACY-NEXT: [[BYVAL_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8
// LEGACY-NEXT: [[IDX_EXT:%.*]] = sext i32 [[COUNT]] to i64
// LEGACY-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr null, i64 [[IDX_EXT]]
// LEGACY-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BYVAL_TEMP]]) #[[ATTR3:[0-9]+]]
// LEGACY-NEXT: store ptr null, ptr [[BYVAL_TEMP]], align 8
// LEGACY-NEXT: [[PTR_SROA_4_0_BYVAL_TEMP_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[BYVAL_TEMP]], i64 8
// LEGACY-NEXT: store ptr [[ADD_PTR]], ptr [[PTR_SROA_4_0_BYVAL_TEMP_SROA_IDX]], align 8
// LEGACY-NEXT: [[PTR_SROA_5_0_BYVAL_TEMP_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[BYVAL_TEMP]], i64 16
// LEGACY-NEXT: store ptr null, ptr [[PTR_SROA_5_0_BYVAL_TEMP_SROA_IDX]], align 8, !tbaa [[TBAA2:![0-9]+]]
// LEGACY-NEXT: call void @consume(ptr noundef nonnull [[BYVAL_TEMP]]) #[[ATTR3]]
// LEGACY-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[BYVAL_TEMP]]) #[[ATTR3]]
// LEGACY-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BYVAL_TEMP]]) #[[ATTR4:[0-9]+]]
// LEGACY-NEXT: call void @llvm.memset.p0.i64(ptr noundef nonnull align 8 dereferenceable(24) [[BYVAL_TEMP]], i8 0, i64 24, i1 false)
// LEGACY-NEXT: call void @consume(ptr noundef nonnull [[BYVAL_TEMP]]) #[[ATTR4]]
// LEGACY-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[BYVAL_TEMP]]) #[[ATTR4]]
// LEGACY-NEXT: ret void
//
void use_inline_header_func_unspecified_ptr(int count) {
Expand Down Expand Up @@ -62,16 +56,10 @@ void use_inline_header_func_unspecified_ptr(int count) {
// LEGACY-SAME: i32 noundef [[COUNT:%.*]]) local_unnamed_addr #[[ATTR0]] {
// LEGACY-NEXT: [[ENTRY:.*:]]
// LEGACY-NEXT: [[BYVAL_TEMP:%.*]] = alloca %"__bounds_safety::wide_ptr.bidi_indexable", align 8
// LEGACY-NEXT: [[IDX_EXT:%.*]] = sext i32 [[COUNT]] to i64
// LEGACY-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr null, i64 [[IDX_EXT]]
// LEGACY-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BYVAL_TEMP]]) #[[ATTR3]]
// LEGACY-NEXT: store ptr null, ptr [[BYVAL_TEMP]], align 8
// LEGACY-NEXT: [[PTR_SROA_4_0_BYVAL_TEMP_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[BYVAL_TEMP]], i64 8
// LEGACY-NEXT: store ptr [[ADD_PTR]], ptr [[PTR_SROA_4_0_BYVAL_TEMP_SROA_IDX]], align 8
// LEGACY-NEXT: [[PTR_SROA_5_0_BYVAL_TEMP_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[BYVAL_TEMP]], i64 16
// LEGACY-NEXT: store ptr null, ptr [[PTR_SROA_5_0_BYVAL_TEMP_SROA_IDX]], align 8, !tbaa [[TBAA2]]
// LEGACY-NEXT: call void @consume(ptr noundef nonnull [[BYVAL_TEMP]]) #[[ATTR3]]
// LEGACY-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[BYVAL_TEMP]]) #[[ATTR3]]
// LEGACY-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BYVAL_TEMP]]) #[[ATTR4]]
// LEGACY-NEXT: call void @llvm.memset.p0.i64(ptr noundef nonnull align 8 dereferenceable(24) [[BYVAL_TEMP]], i8 0, i64 24, i1 false)
// LEGACY-NEXT: call void @consume(ptr noundef nonnull [[BYVAL_TEMP]]) #[[ATTR4]]
// LEGACY-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[BYVAL_TEMP]]) #[[ATTR4]]
// LEGACY-NEXT: ret void
//
void use_inline_header_func_unsafe_indexable_ptr(int count) {
Expand All @@ -82,9 +70,3 @@ void use_inline_header_func_unsafe_indexable_ptr(int count) {
// CHECK: [[META2]] = !{!"bounds-safety-generic"}
// CHECK: [[PROF3]] = !{!"branch_weights", i32 1048575, i32 1}
//.
// LEGACY: [[TBAA2]] = !{[[META3:![0-9]+]], [[META3]], i64 0}
// LEGACY: [[META3]] = !{!"p1 int", [[META4:![0-9]+]], i64 0}
// LEGACY: [[META4]] = !{!"any pointer", [[META5:![0-9]+]], i64 0}
// LEGACY: [[META5]] = !{!"omnipotent char", [[META6:![0-9]+]], i64 0}
// LEGACY: [[META6]] = !{!"Simple C/C++ TBAA"}
//.
16 changes: 4 additions & 12 deletions clang/test/BoundsSafety/CodeGen/nested-struct-member-count-O2.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,24 +42,21 @@ char access(struct Outer *bar, int index) {



// CHECK-LABEL: define dso_local ptr @assign(
// CHECK-LABEL: define dso_local noundef nonnull ptr @assign(
// CHECK-SAME: ptr noundef readonly captures(none) [[BAR:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[AGG_TEMP1_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr [[BAR]], align 8
// CHECK-NEXT: [[AGG_TEMP1_SROA_0_0_COPYLOAD:%.*]] = load ptr, ptr [[BAR]], align 8, !nonnull {{![0-9]+}}, !noundef {{![0-9]+}}
// CHECK-NEXT: [[AGG_TEMP1_SROA_2_0_BAR_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[BAR]], i64 8
// CHECK-NEXT: [[AGG_TEMP1_SROA_2_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP1_SROA_2_0_BAR_SROA_IDX]], align 8
// CHECK-NEXT: [[AGG_TEMP1_SROA_3_0_BAR_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[BAR]], i64 16
// CHECK-NEXT: [[AGG_TEMP1_SROA_3_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP1_SROA_3_0_BAR_SROA_IDX]], align 8, !tbaa {{![0-9]+}}
// CHECK-NEXT: [[FLEX_BASE_NULL_CHECK_NOT:%.*]] = icmp eq ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], null, !annotation {{![0-9]+}}
// CHECK-NEXT: br i1 [[FLEX_BASE_NULL_CHECK_NOT]], label [[BOUNDSCHECK_CONT_THREAD:%.*]], label [[FLEX_BASE_NONNULL:%.*]], !annotation {{![0-9]+}}
// CHECK: flex.base.nonnull:
// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], i64 8
// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], [[TMP0]], !annotation {{![0-9]+}}
// CHECK-NEXT: br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT:%.*]], !prof {{![0-9]+}}, !annotation {{![0-9]+}}
// CHECK: trap:
// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR2]], !annotation {{![0-9]+}}
// CHECK-NEXT: unreachable, !annotation {{![0-9]+}}
// CHECK: cont:
// CHECK-NEXT: [[AGG_TEMP1_SROA_3_0_BAR_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[BAR]], i64 16
// CHECK-NEXT: [[AGG_TEMP1_SROA_3_0_COPYLOAD:%.*]] = load ptr, ptr [[AGG_TEMP1_SROA_3_0_BAR_SROA_IDX]], align 8, !tbaa {{![0-9]+}}
// CHECK-NEXT: [[TMP1:%.*]] = icmp ule ptr [[TMP0]], [[AGG_TEMP1_SROA_2_0_COPYLOAD]], !annotation {{![0-9]+}}
// CHECK-NEXT: [[TMP2:%.*]] = icmp ule ptr [[AGG_TEMP1_SROA_3_0_COPYLOAD]], [[AGG_TEMP1_SROA_0_0_COPYLOAD]], !annotation {{![0-9]+}}
// CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[TMP1]], i1 [[TMP2]], i1 false, !annotation {{![0-9]+}}
Expand All @@ -75,14 +72,9 @@ char access(struct Outer *bar, int index) {
// CHECK-NEXT: [[TMP3:%.*]] = icmp ult ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], [[AGG_TEMP1_SROA_2_0_COPYLOAD]], !annotation {{![0-9]+}}
// CHECK-NEXT: [[OR_COND60:%.*]] = select i1 [[OR_COND49]], i1 [[TMP3]], i1 false, !annotation {{![0-9]+}}
// CHECK-NEXT: br i1 [[OR_COND60]], label [[BOUNDSCHECK_CONT:%.*]], label [[TRAP]], !prof {{![0-9]+}}, !annotation {{![0-9]+}}
// CHECK: boundscheck.cont.thread:
// CHECK-NEXT: store i32 [[LEN]], ptr inttoptr (i64 4 to ptr), align 4, !tbaa {{![0-9]+}}
// CHECK-NEXT: br label [[CONT46:%.*]]
// CHECK: boundscheck.cont:
// CHECK-NEXT: [[LEN31:%.*]] = getelementptr inbounds nuw i8, ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]], i64 4
// CHECK-NEXT: store i32 [[LEN]], ptr [[LEN31]], align 4, !tbaa {{![0-9]+}}
// CHECK-NEXT: br label [[CONT46]], !annotation {{![0-9]+}}
// CHECK: cont46:
// CHECK-NEXT: ret ptr [[AGG_TEMP1_SROA_0_0_COPYLOAD]]
//
struct Outer * assign(void * __bidi_indexable bar, int len) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,17 @@ const char *__indexable good_chars_unsafe(void) {
}

// CHECK-LABEL: @bad_null(
// CHECK-NEXT: entry:
// CHECK-NEXT: unreachable
// CHECK-NEXT: terminated_by.loop_end:
// CHECK-NEXT: ret { ptr, ptr } zeroinitializer
//
int *__indexable bad_null(void) {
int *__null_terminated p = 0;
return __terminated_by_to_indexable(p);
}

// CHECK-LABEL: @bad_null_unsafe(
// CHECK-NEXT: entry:
// CHECK-NEXT: unreachable
// CHECK-NEXT: terminated_by.loop_end:
// CHECK-NEXT: ret { ptr, ptr } zeroinitializer
//
int *__indexable bad_null_unsafe(void) {
int *__null_terminated p = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ int main() {

foo(&s.len, &s.buf);
foo(&local_len, &s.buf); // expected-error{{incompatible dynamic count pointer argument to parameter of type}}
foo(&t.len, &t.buf); // expected-error{{incompatible count expression (*out_len) vs. (len + 1) in argument to function}}
foo(&t.len, &t.buf); // expected-error{{incompatible count expression '*out_len' vs. 'len + 1' in argument to function}}
// expected-error@+1{{passing address of 'len' as an indirect parameter; must also pass 'buf2' or its address because the type of 'buf2', 'int *__single __counted_by(len)' (aka 'int *__single'), refers to 'len'}}
foo(&u.len, &u.buf);
bar(&s.len, &s.buf); // expected-error{{passing address of 'len' referred to by '__counted_by' to a parameter that is not referred to by the same attribute}}
Expand Down
Loading