-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[Clang][Sema] Allow counted_by on void* as GNU extension #164737
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
kees
wants to merge
6
commits into
llvm:main
Choose a base branch
from
kees:void-counted_by
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+229
−21
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
4609f8c
[Clang][Sema] Allow counted_by on void* in GNU mode
kees 478a582
add note after warning
kees a277f51
assert that InvalidTypeKind is unchanged
kees 2edf440
add void* usage tests
kees 84fe612
avoid using library functions for selftest
kees f50ef58
Do not use GNUMode; just rely on -Wpointer-arith
kees File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| // RUN: %clang_cc1 -std=gnu11 -triple x86_64-unknown-linux-gnu -O2 -emit-llvm -o - %s | FileCheck %s | ||
|
|
||
| // Test that counted_by on void* in GNU mode treats void as having size 1 (byte count) | ||
|
|
||
| #define __counted_by(f) __attribute__((counted_by(f))) | ||
| #define __sized_by(f) __attribute__((sized_by(f))) | ||
|
|
||
| struct with_counted_by_void { | ||
| int count; | ||
| void* buf __counted_by(count); | ||
| }; | ||
|
|
||
| struct with_sized_by_void { | ||
| int size; | ||
| void* buf __sized_by(size); | ||
| }; | ||
|
|
||
| struct with_counted_by_int { | ||
| int count; | ||
| int* buf __counted_by(count); | ||
| }; | ||
|
|
||
| // CHECK-LABEL: define dso_local {{.*}}@test_counted_by_void( | ||
| // CHECK: %[[COUNT:.*]] = load i32, ptr %s | ||
| // CHECK: %[[NARROW:.*]] = tail call i32 @llvm.smax.i32(i32 %[[COUNT]], i32 0) | ||
| // CHECK: %[[ZEXT:.*]] = zext nneg i32 %[[NARROW]] to i64 | ||
| // CHECK: ret i64 %[[ZEXT]] | ||
| // | ||
| // Verify: counted_by on void* returns the count directly (count * 1 byte) | ||
| long long test_counted_by_void(struct with_counted_by_void *s) { | ||
| return __builtin_dynamic_object_size(s->buf, 0); | ||
| } | ||
|
|
||
| // CHECK-LABEL: define dso_local {{.*}}@test_sized_by_void( | ||
| // CHECK: %[[SIZE:.*]] = load i32, ptr %s | ||
| // CHECK: %[[NARROW:.*]] = tail call i32 @llvm.smax.i32(i32 %[[SIZE]], i32 0) | ||
| // CHECK: %[[ZEXT:.*]] = zext nneg i32 %[[NARROW]] to i64 | ||
| // CHECK: ret i64 %[[ZEXT]] | ||
| // | ||
| // Verify: sized_by on void* returns the size directly | ||
| long long test_sized_by_void(struct with_sized_by_void *s) { | ||
| return __builtin_dynamic_object_size(s->buf, 0); | ||
| } | ||
|
|
||
| // CHECK-LABEL: define dso_local {{.*}}@test_counted_by_int( | ||
| // CHECK: %[[COUNT:.*]] = load i32, ptr %s | ||
| // CHECK: %[[SEXT:.*]] = sext i32 %[[COUNT]] to i64 | ||
| // CHECK: %[[SIZE:.*]] = shl nsw i64 %[[SEXT]], 2 | ||
| // CHECK: ret i64 | ||
| // | ||
| // Verify: counted_by on int* returns count * sizeof(int) = count * 4 | ||
| long long test_counted_by_int(struct with_counted_by_int *s) { | ||
| return __builtin_dynamic_object_size(s->buf, 0); | ||
| } | ||
|
|
||
| // CHECK-LABEL: define dso_local ptr @test_void_ptr_arithmetic( | ||
| // CHECK: %[[BUF:.*]] = load ptr, ptr | ||
| // CHECK: %[[EXT:.*]] = sext i32 %offset to i64 | ||
| // CHECK: %[[PTR:.*]] = getelementptr inbounds i8, ptr %[[BUF]], i64 %[[EXT]] | ||
| // CHECK: ret ptr %[[PTR]] | ||
| // | ||
| // Verify: pointer arithmetic on void* uses i8 (byte offsets), not i32 or other sizes | ||
| void* test_void_ptr_arithmetic(struct with_counted_by_void *s, int offset) { | ||
| return s->buf + offset; // GNU extension: void* arithmetic | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| // RUN: %clang_cc1 -fsyntax-only -verify=expected-nowarn %s | ||
| // RUN: %clang_cc1 -Wpointer-arith -fsyntax-only -verify=expected-warn %s | ||
| // RUN: %clang_cc1 -fexperimental-bounds-safety -fsyntax-only -verify=expected-bounds %s | ||
|
|
||
| // expected-nowarn-no-diagnostics | ||
| // expected-bounds-no-diagnostics | ||
|
|
||
| #define NULL (void*)0 | ||
| #define __counted_by(f) __attribute__((counted_by(f))) | ||
| #define __counted_by_or_null(f) __attribute__((counted_by_or_null(f))) | ||
| #define __sized_by(f) __attribute__((sized_by(f))) | ||
|
|
||
| //============================================================================== | ||
| // Test: counted_by on void* is allowed (warns with -Wpointer-arith) | ||
| //============================================================================== | ||
|
|
||
| struct test_void_ptr_gnu { | ||
| int count; | ||
| // expected-warn-warning@+2{{'counted_by' on a pointer to void is a GNU extension, treated as 'sized_by'}} | ||
| // expected-warn-note@+1{{use '__sized_by' to suppress this warning}} | ||
| void* buf __counted_by(count); | ||
| }; | ||
|
|
||
| struct test_const_void_ptr_gnu { | ||
| int count; | ||
| // expected-warn-warning@+2{{'counted_by' on a pointer to void is a GNU extension, treated as 'sized_by'}} | ||
| // expected-warn-note@+1{{use '__sized_by' to suppress this warning}} | ||
| const void* buf __counted_by(count); | ||
| }; | ||
|
|
||
| struct test_volatile_void_ptr_gnu { | ||
| int count; | ||
| // expected-warn-warning@+2{{'counted_by' on a pointer to void is a GNU extension, treated as 'sized_by'}} | ||
| // expected-warn-note@+1{{use '__sized_by' to suppress this warning}} | ||
| volatile void* buf __counted_by(count); | ||
| }; | ||
|
|
||
| struct test_const_volatile_void_ptr_gnu { | ||
| int count; | ||
| // expected-warn-warning@+2{{'counted_by' on a pointer to void is a GNU extension, treated as 'sized_by'}} | ||
| // expected-warn-note@+1{{use '__sized_by' to suppress this warning}} | ||
| const volatile void* buf __counted_by(count); | ||
| }; | ||
|
|
||
| // Verify sized_by still works the same way (always allowed, no warning) | ||
| struct test_sized_by_void_ptr { | ||
| int size; | ||
| void* buf __sized_by(size); // OK in both modes, no warning | ||
| }; | ||
|
|
||
| //============================================================================== | ||
| // Test: counted_by_or_null on void* behaves the same | ||
| //============================================================================== | ||
|
|
||
| struct test_void_ptr_or_null_gnu { | ||
| int count; | ||
| // expected-warn-warning@+2{{'counted_by_or_null' on a pointer to void is a GNU extension, treated as 'sized_by_or_null'}} | ||
| // expected-warn-note@+1{{use '__sized_by_or_null' to suppress this warning}} | ||
| void* buf __counted_by_or_null(count); | ||
| }; | ||
|
|
||
| struct test_const_void_ptr_or_null_gnu { | ||
| int count; | ||
| // expected-warn-warning@+2{{'counted_by_or_null' on a pointer to void is a GNU extension, treated as 'sized_by_or_null'}} | ||
| // expected-warn-note@+1{{use '__sized_by_or_null' to suppress this warning}} | ||
| const void* buf __counted_by_or_null(count); | ||
| }; | ||
|
|
||
| //============================================================================== | ||
| // Test: Using void* __counted_by(...) pointers (not just declaring them) | ||
| //============================================================================== | ||
|
|
||
| // Verify that void* __counted_by pointers can be used as rvalues, assigned to, | ||
| // passed to functions, etc. | ||
|
|
||
| void* use_as_rvalue(struct test_void_ptr_gnu* t) { | ||
| return t->buf; | ||
| } | ||
|
|
||
| void assign_to_pointer(struct test_void_ptr_gnu* t) { | ||
| t->buf = NULL; | ||
| t->count = 0; | ||
| } | ||
|
|
||
| extern void* my_allocator(unsigned long); | ||
|
|
||
| void assign_from_allocator(struct test_void_ptr_gnu* t) { | ||
| t->buf = my_allocator(100); | ||
| t->count = 100; | ||
| } | ||
|
|
||
| void takes_void_ptr(void* p); | ||
|
|
||
| void pass_to_function(struct test_void_ptr_gnu* t) { | ||
| takes_void_ptr(t->buf); | ||
| } | ||
|
|
||
| void* pointer_arithmetic(struct test_void_ptr_gnu* t) { | ||
| // expected-warn-warning@+1{{arithmetic on a pointer to void is a GNU extension}} | ||
| return t->buf + 10; | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.