[llvm] add some test files for a more generalised attribute implementation proposal (PR #212730)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 29 03:18:25 PDT 2026
github-actions[bot] wrote:
<!--LLVM CODE FORMAT COMMENT: {clang-format}-->
:warning: C/C++ code formatter, clang-format found issues in your code. :warning:
<details>
<summary>
You can test this locally with the following command:
</summary>
``````````bash
git-clang-format --diff origin/main HEAD --extensions h,cpp -- hicketts/hicketts_optional_general.h hicketts/hicketts_vector.h hicketts/test_hicketts_optional_general.cpp hicketts/test_hicketts_vector.cpp --diff_from_common_commit
``````````
:warning:
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing `origin/main` to the base branch/commit you want to compare against.
:warning:
</details>
<details>
<summary>
View the diff from clang-format here.
</summary>
``````````diff
diff --git a/hicketts/hicketts_optional_general.h b/hicketts/hicketts_optional_general.h
index be0ff9471..44c7d888e 100644
--- a/hicketts/hicketts_optional_general.h
+++ b/hicketts/hicketts_optional_general.h
@@ -48,10 +48,16 @@ public:
HickettsOptional(HickettsOptional &&) = default;
// Equivalent to std::optional::value()
- [[clang::analyze_as_method("value")]] const T &unwrap() const & { return *storage_; }
+ [[clang::analyze_as_method("value")]] const T &unwrap() const & {
+ return *storage_;
+ }
[[clang::analyze_as_method("value")]] T &unwrap() & { return *storage_; }
- [[clang::analyze_as_method("value")]] const T &&unwrap() const && { return static_cast<const T &&>(*storage_); }
- [[clang::analyze_as_method("value")]] T &&unwrap() && { return static_cast<T &&>(*storage_); }
+ [[clang::analyze_as_method("value")]] const T &&unwrap() const && {
+ return static_cast<const T &&>(*storage_);
+ }
+ [[clang::analyze_as_method("value")]] T &&unwrap() && {
+ return static_cast<T &&>(*storage_);
+ }
const T &value() const & { return *storage_; }
T &value() & { return *storage_; }
@@ -59,30 +65,38 @@ public:
T &&value() && { return static_cast<T &&>(*storage_); }
// Equivalent to std::optional::operator*()
- [[clang::analyze_as_method("value")]] const T &deref() const & { return *storage_; }
+ [[clang::analyze_as_method("value")]] const T &deref() const & {
+ return *storage_;
+ }
[[clang::analyze_as_method("value")]] T &deref() & { return *storage_; }
// Equivalent to std::optional::operator->()
- const T* operator ->() const { return storage_; }
- T* operator ->() { return storage_; }
+ const T *operator->() const { return storage_; }
+ T *operator->() { return storage_; }
const T *arrow() const { return storage_; }
T *arrow() { return storage_; }
// Equivalent to std::optional::operator bool / hasValue()
constexpr bool has_value() const noexcept { return storage_ != nullptr; }
- constexpr explicit operator bool() const noexcept { return storage_ != nullptr; }
- [[clang::analyze_as_method("has_value")]] constexpr bool isPresent() const noexcept { return storage_ != nullptr; }
+ constexpr explicit operator bool() const noexcept {
+ return storage_ != nullptr;
+ }
+ [[clang::analyze_as_method("has_value")]] constexpr bool
+ isPresent() const noexcept {
+ return storage_ != nullptr;
+ }
// Equivalent to std::optional::value_or()
- template <typename U>
- constexpr T unwrapOr(U &&fallback) const & {
+ template <typename U> constexpr T unwrapOr(U &&fallback) const & {
return storage_ ? *storage_ : static_cast<T>(fallback);
}
// Equivalent to std::optional::emplace()
template <typename... Args>
[[clang::analyze_as_method("emplace(Args&&...)")]]
- T& construct(Args&&... args) { return *storage_; }
+ T &construct(Args &&...args) {
+ return *storage_;
+ }
// Demo of malformed-signature rejection — disabled. The parameter-balance
// validation in Sema (isValidAnalyzeAsMethodAttr) that rejected this string
@@ -93,22 +107,28 @@ public:
// T& load() { return *storage_; }
// Equivalent to std::optional::reset()
- [[clang::analyze_as_method("reset")]] void clear() noexcept { storage_ = nullptr; }
+ [[clang::analyze_as_method("reset")]] void clear() noexcept {
+ storage_ = nullptr;
+ }
// Equivalent to std::optional::swap()
- [[clang::analyze_as_method("swap")]] void exchange(HickettsOptional &other) noexcept {
+ [[clang::analyze_as_method("swap")]] void
+ exchange(HickettsOptional &other) noexcept {
T *tmp = storage_;
storage_ = other.storage_;
other.storage_ = tmp;
}
// Assignment
- template <typename U>
- HickettsOptional &operator=(const U &u) { return *this; }
+ template <typename U> HickettsOptional &operator=(const U &u) {
+ return *this;
+ }
[[clang::analyze_as_method("operator=(nullopt_t)")]]
- HickettsOptional &operator=(mylib::nothing_t){ storage_ = nullptr; return *this;}
-
+ HickettsOptional &operator=(mylib::nothing_t) {
+ storage_ = nullptr;
+ return *this;
+ }
};
} // namespace mylib
diff --git a/hicketts/hicketts_vector.h b/hicketts/hicketts_vector.h
index 08cd3b49e..80de82162 100644
--- a/hicketts/hicketts_vector.h
+++ b/hicketts/hicketts_vector.h
@@ -31,8 +31,7 @@ namespace mylib {
#define HV_REINITIALIZES [[clang::reinitializes]]
#endif
-template <typename T>
-class HV_OWNER HickettsVector {
+template <typename T> class HV_OWNER HickettsVector {
// Tiny fixed buffer keeps the fixture simple (no allocator); big enough for
// small tests, and irrelevant to the static lifetime analysis anyway.
T buf_[16] = {};
diff --git a/hicketts/test_hicketts_optional_general.cpp b/hicketts/test_hicketts_optional_general.cpp
index 1ddea121c..a5eaf7a11 100644
--- a/hicketts/test_hicketts_optional_general.cpp
+++ b/hicketts/test_hicketts_optional_general.cpp
@@ -3,11 +3,13 @@
//
// Run from hicketts/ with:
// ../build-llvm/bin/clang-tidy -checks='bugprone-unchecked-optional-access' \
-// test_hicketts_optional_general.cpp -- -I . -std=c++17 -Wno-undefined-inline
+// test_hicketts_optional_general.cpp -- -I . -std=c++17
+// -Wno-undefined-inline
#include "hicketts_optional_general.h"
-// --- Unchecked access (should warn if the checker recognises HickettsOptional) ---
+// --- Unchecked access (should warn if the checker recognises HickettsOptional)
+// ---
static void uncheckedUnwrap(mylib::HickettsOptional<int> &Val) {
Val.unwrap(); // unchecked access — may be empty
@@ -49,8 +51,9 @@ static void checkedWithIsPresent(mylib::HickettsOptional<int> &Val) {
// --- State changes ---
-// construct() is annotated "emplace(Args&&...)"; the bare "emplace" query matches
-// it via the name-part (accept-either) branch -> engaged, so unwrap is safe.
+// construct() is annotated "emplace(Args&&...)"; the bare "emplace" query
+// matches it via the name-part (accept-either) branch -> engaged, so unwrap is
+// safe.
static void safeAfterConstruct(mylib::HickettsOptional<int> &Val) {
Val.construct(42);
Val.unwrap(); // safe — just constructed a value
@@ -63,7 +66,7 @@ static void unsafeAfterClear(mylib::HickettsOptional<int> &Val) {
}
static void unsafeAfterExchange(mylib::HickettsOptional<int> &A,
- mylib::HickettsOptional<int> &B) {
+ mylib::HickettsOptional<int> &B) {
if (A) {
A.exchange(B);
A.unwrap(); // unsafe — a's state is now unknown
@@ -71,7 +74,8 @@ static void unsafeAfterExchange(mylib::HickettsOptional<int> &A,
}
// Works today WITHOUT any annotation: default construction matches no
-// constructor case, so has_value is unconstrained -> access conservatively warns.
+// constructor case, so has_value is unconstrained -> access conservatively
+// warns.
static void unsafeAfterEmptyConstr() {
mylib::HickettsOptional<int> A;
A.unwrap(); // expected: warn (empty)
@@ -79,8 +83,8 @@ static void unsafeAfterEmptyConstr() {
// nothing_t is not std::nullopt_t, so the structural nullopt matcher misses.
// The "optional(std::nullopt_t)" annotation routes this constructor to the
-// nullopt transfer (empty) via isOptionalNulloptConstructor's annotation branch,
-// so the following unwrap is correctly flagged.
+// nullopt transfer (empty) via isOptionalNulloptConstructor's annotation
+// branch, so the following unwrap is correctly flagged.
static void unsafeAfterNullConstr() {
mylib::HickettsOptional<int> A(mylib::nothing);
A.unwrap(); // warns (empty) — routed to nullopt via the annotation
diff --git a/hicketts/test_hicketts_vector.cpp b/hicketts/test_hicketts_vector.cpp
index 9cc29515a..d5ecdf2f3 100644
--- a/hicketts/test_hicketts_vector.cpp
+++ b/hicketts/test_hicketts_vector.cpp
@@ -22,7 +22,8 @@ int dangling_reference_from_temporary() {
}
int dangling_iterator_from_temporary() {
- auto it = HickettsVector<int>{}.begin(); // it dangles into destroyed temporary
+ auto it =
+ HickettsVector<int>{}.begin(); // it dangles into destroyed temporary
return *it;
}
@@ -49,6 +50,6 @@ int safe_iterator() {
// the gap the role vocabulary is meant to fill.
int precondition_gap() {
- HickettsVector<int> v; // empty
- return v.front(); // UB today: no warning from any attribute
+ HickettsVector<int> v; // empty
+ return v.front(); // UB today: no warning from any attribute
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/212730
More information about the llvm-commits
mailing list