-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[libc++] Add nodiscard attribute to std::make_unique/std::make_shared #153115
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
base: main
Are you sure you want to change the base?
Conversation
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-libcxx Author: Lukas (lukasx999) ChangesI think Full diff: https://github.com/llvm/llvm-project/pull/153115.diff 1 Files Affected:
diff --git a/libcxx/include/memory b/libcxx/include/memory
index ca880c83a544d..5a4100155fc94 100644
--- a/libcxx/include/memory
+++ b/libcxx/include/memory
@@ -566,15 +566,15 @@ class bad_weak_ptr
};
template<class T, class... Args>
-constexpr unique_ptr<T> make_unique(Args&&... args); // C++14, constexpr since C++23
+[[nodiscard]] constexpr unique_ptr<T> make_unique(Args&&... args); // C++14, constexpr since C++23
template<class T>
-constexpr unique_ptr<T> make_unique(size_t n); // C++14, constexpr since C++23
+[[nodiscard]] constexpr unique_ptr<T> make_unique(size_t n); // C++14, constexpr since C++23
template<class T, class... Args> unspecified make_unique(Args&&...) = delete; // C++14, T == U[N]
template<class T>
- constexpr unique_ptr<T> make_unique_for_overwrite(); // T is not array, C++20, constexpr since C++23
+ [[nodiscard]] constexpr unique_ptr<T> make_unique_for_overwrite(); // T is not array, C++20, constexpr since C++23
template<class T>
- constexpr unique_ptr<T> make_unique_for_overwrite(size_t n); // T is U[], C++20, constexpr since C++23
+ [[nodiscard]] constexpr unique_ptr<T> make_unique_for_overwrite(size_t n); // T is U[], C++20, constexpr since C++23
template<class T, class... Args>
unspecified make_unique_for_overwrite(Args&&...) = delete; // T is U[N], C++20
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is incorrect. You've modified a comment.
Do you mean the whitespace between the function and the comment? |
No, you didn't modify any code. You just modified a comment. |
You will need to also add tests. |
Sorry, my editor was not syntax-highlighting the comment - as it should, I just though that was because of some |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think the
memory
synopsis should still contain the nodiscard attribute?
No
Please also add tests. You can take a look at libcxx/test/libcxx/mem/mem.res/nodiscard.verify.cpp
for an example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you refer in the commit message to https://libcxx.llvm.org/CodingGuidelines.html#apply-nodiscard-where-relevant instead of "I think it makes a lot of sense"?
S() = default; | ||
}; | ||
|
||
std::make_unique<S>(S{}); // expected-warning {{ignoring return value of function}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like you're missing a few test cases. I count 12 new annotations above, but this tests only 6 functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where do you see 12 annotations? I only see 6.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also counted 12.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sorry but you're not being very helpful, you do mind pointing me to a resource that explains how "annotations" in this test system work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These .verify.cpp
tests use Clang-verify: https://clang.llvm.org/docs/InternalsManual.html#verifying-diagnostics
I think what @philnik777 is referring to is that you added [[__nodiscard__]]
to 12 functions or function overloads, yet you are only testing that the diagnostic is firing on 6 functions. This means that you are missing coverage for 6 functions or function overloads to which the attribute was added, but you have nothing testing it.
You can test this locally with the following command:git-clang-format --diff HEAD~1 HEAD --extensions h,cpp -- libcxx/test/libcxx/memory/nodiscard.verify.cpp libcxx/include/__memory/shared_ptr.h libcxx/include/__memory/unique_ptr.h View the diff from clang-format here.diff --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h
index 7a2b4a507..87c46ecc9 100644
--- a/libcxx/include/__memory/unique_ptr.h
+++ b/libcxx/include/__memory/unique_ptr.h
@@ -755,7 +755,8 @@ operator<=>(const unique_ptr<_T1, _D1>& __x, nullptr_t) {
#if _LIBCPP_STD_VER >= 14
template <class _Tp, class... _Args, enable_if_t<!is_array<_Tp>::value, int> = 0>
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp> make_unique(_Args&&... __args) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp>
+make_unique(_Args&&... __args) {
return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...));
}
@@ -778,7 +779,8 @@ template <class _Tp, enable_if_t<!is_array_v<_Tp>, int> = 0>
}
template <class _Tp, enable_if_t<is_unbounded_array_v<_Tp>, int> = 0>
-[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp> make_unique_for_overwrite(size_t __n) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp>
+make_unique_for_overwrite(size_t __n) {
return unique_ptr<_Tp>(__private_constructor_tag(), new __remove_extent_t<_Tp>[__n], __n);
}
diff --git a/libcxx/test/libcxx/memory/nodiscard.verify.cpp b/libcxx/test/libcxx/memory/nodiscard.verify.cpp
index 316ce0b47..34f751fb5 100644
--- a/libcxx/test/libcxx/memory/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/memory/nodiscard.verify.cpp
@@ -20,14 +20,12 @@
#include <memory>
void f() {
+ std::make_unique<int>(1); // expected-warning {{ignoring return value of function}}
+ std::make_shared<int>(1); // expected-warning {{ignoring return value of function}}
- std::make_unique<int>(1); // expected-warning {{ignoring return value of function}}
- std::make_shared<int>(1); // expected-warning {{ignoring return value of function}}
-
- std::make_unique<int[]>(5); // expected-warning {{ignoring return value of function}}
- std::make_shared<int[]>(5); // expected-warning {{ignoring return value of function}}
-
- std::make_unique_for_overwrite<int>(); // expected-warning {{ignoring return value of function}}
- std::make_shared_for_overwrite<int>(); // expected-warning {{ignoring return value of function}}
+ std::make_unique<int[]>(5); // expected-warning {{ignoring return value of function}}
+ std::make_shared<int[]>(5); // expected-warning {{ignoring return value of function}}
+ std::make_unique_for_overwrite<int>(); // expected-warning {{ignoring return value of function}}
+ std::make_shared_for_overwrite<int>(); // expected-warning {{ignoring return value of function}}
}
|
I think
nodiscard
makes a lot of sense as a sensible default for smart pointer factory functions.Calling
make_unique
and discarding the return value, will lead to an unnecessary allocation and therefore is a misuse of the function. (see https://libcxx.llvm.org/CodingGuidelines.html#apply-nodiscard-where-relevant)Im kind of surprised that this isn't the default in libc++, aswell as libstdc++, since the standard says that
nodiscard
attributes are implementation defined.