Skip to content

[Wunsafe-buffer-usage] Turn off unsafe-buffer warning for methods annotated with clang::unsafe_buffer_usage attribute #125671

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

Merged
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
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ Removed Compiler Flags

Attribute Changes in Clang
--------------------------
Adding [[clang::unsafe_buffer_usage]] attribute to a method definition now turns off all -Wunsafe-buffer-usage
related warnings within the method body.

Improvements to Clang's diagnostics
-----------------------------------
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/AnalysisBasedWarnings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2610,6 +2610,9 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(

// The Callback function that performs analyses:
auto CallAnalyzers = [&](const Decl *Node) -> void {
if (Node->hasAttr<UnsafeBufferUsageAttr>())
return;

// Perform unsafe buffer usage analysis:
if (!Diags.isIgnored(diag::warn_unsafe_buffer_operation,
Node->getBeginLoc()) ||
Expand Down
75 changes: 69 additions & 6 deletions clang/test/SemaCXX/warn-unsafe-buffer-usage-function-attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,16 +119,15 @@ struct HoldsUnsafeMembers {

[[clang::unsafe_buffer_usage]]
HoldsUnsafeMembers(int i)
: FromCtor(i), // expected-warning{{function introduces unsafe buffer manipulation}}
FromCtor2{i} // expected-warning{{function introduces unsafe buffer manipulation}}
{}
: FromCtor(i),
FromCtor2{i} {}

HoldsUnsafeMembers(float f)
: HoldsUnsafeMembers(0) {} // expected-warning{{function introduces unsafe buffer manipulation}}

UnsafeMembers FromCtor;
UnsafeMembers FromCtor2;
UnsafeMembers FromField{3}; // expected-warning 2{{function introduces unsafe buffer manipulation}}
UnsafeMembers FromField{3}; // expected-warning {{function introduces unsafe buffer manipulation}}
};

struct SubclassUnsafeMembers : public UnsafeMembers {
Expand All @@ -138,8 +137,7 @@ struct SubclassUnsafeMembers : public UnsafeMembers {

[[clang::unsafe_buffer_usage]]
SubclassUnsafeMembers(int i)
: UnsafeMembers(i) // expected-warning{{function introduces unsafe buffer manipulation}}
{}
: UnsafeMembers(i){}
};

// https://github.com/llvm/llvm-project/issues/80482
Expand Down Expand Up @@ -245,3 +243,68 @@ struct AggregateViaDefaultInit {
void testAggregateViaDefaultInit() {
AggregateViaDefaultInit A;
};

struct A {
int arr[2];

[[clang::unsafe_buffer_usage]]
int *ptr;
};

namespace std{
template <typename T> class span {

T *elements;

public:

constexpr span(T *, unsigned){}

template<class Begin, class End>
constexpr span(Begin first, End last){}

constexpr T* data() const noexcept {
return elements;
}
};
}

[[clang::unsafe_buffer_usage]]
void check_no_warnings(unsigned idx) {
int *arr = new int[20];

int k = arr[idx]; // no-warning

std::span<int> sp = {arr, 20}; // no-warning
A *ptr = reinterpret_cast<A*> (sp.data()); // no-warning
A a;
a.ptr = arr; // no-warning
}

[[clang::unsafe_buffer_usage]]
void check_no_warning_variadic(unsigned idx, int arr[20], ...) {
int k = arr[idx]; // no-warning

std::span<int> sp = {arr, 20}; // no-warning
A *ptr = reinterpret_cast<A*> (sp.data()); // no-warning
A a;
a.ptr = arr; // no-warning
}

template<typename T>
[[clang::unsafe_buffer_usage]]
void check_no_warnings_template(unsigned idx, T* arr) {
int k = arr[idx]; // no-warning

std::span<int> sp = {arr, 20}; // no-warning
A *ptr = reinterpret_cast<A*> (sp.data()); // no-warning
A a;
a.ptr = arr; // no-warning
}

void invoke_methods() {
int array[20];
check_no_warnings(30); //expected-warning{{function introduces unsafe buffer manipulation}}
check_no_warning_variadic(15, array); //expected-warning{{function introduces unsafe buffer manipulation}}
check_no_warnings_template(10, array); //expected-warning{{function introduces unsafe buffer manipulation}}
}