Skip to content

[clang-tidy] bugprone-unchecked-optional-access: support detection of unsafe std::expected access #135045

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
BaLiKfromUA opened this issue Apr 9, 2025 · 4 comments
Assignees

Comments

@BaLiKfromUA
Copy link
Contributor

BaLiKfromUA commented Apr 9, 2025

I'd like to propose extending the existing clang-tidy check bugprone-unchecked-optional-access to also detect unsafe access to std::expected<T, E> values.

Just like std::optional<T>, std::expected<T, E> requires validation (e.g. via .has_value() or operator bool()) before accessing the contained value via .value(), operator*(), or operator->(). The same misuse patterns apply and can be caught using the same logic currently implemented in bugprone-unchecked-optional-access.

From my experience with bugprone-unchecked-optional-access implementation, code change should be quite straightforward.

I am planning to work on draft PR in upcoming weeks, but want to start this issue to gather feedback. I tried to search for existing opened issues but didn't find any.

Main questions from me:

  • Would it make sense to include this support directly in bugprone-unchecked-optional-access, or would a new check like bugprone-unchecked-expected-access be preferable?
  • Are there any std::expected-specific behaviors or edge cases I may have overlooked?

If we are happy to start supporting std::expected<T, E>, IMO we also should support tl::expected<T,E> (link) because it is widely used in codebases which don't use C++ 23.

@llvmbot
Copy link
Member

llvmbot commented Apr 9, 2025

@llvm/issue-subscribers-clang-tidy

Author: Valentyn Yukhymenko (BaLiKfromUA)

I'd like to propose extending the existing clang-tidy check `bugprone-unchecked-optional-access` to also detect unsafe access to `std::expected<T, E>` values.

Just like std::optional&lt;T&gt;, std::expected&lt;T, E&gt; requires validation (e.g. via .has_value() or operator bool()) before accessing the contained value via .value(), operator*(), or operator-&gt;(). The same kind of misuse patterns apply and can be caught using bugprone-unchecked-optional-access .

From my experience with bugprone-unchecked-optional-access implementation, code change should be quite straightforward.

I am planning to work on draft PR in upcoming weeks, but want to start this issue to gather feedback. I tried to search for existing opened issues but didn't find any.

Main questions for me:

  • Would it make sense to include this support directly in bugprone-unchecked-optional-access, or would a new check like bugprone-unchecked-expected-access be preferable?
  • Are there any std::expected-specific behaviors or edge cases I may have overlooked?

If we are happy to start supporting std::expected&lt;T, E&gt;, IMO we also should support tl::expected&lt;T,E&gt; Link because it is widely used in codebases which don't use C++ 23.

@vbvictor
Copy link
Contributor

vbvictor commented Apr 10, 2025

Would it make sense to include this support directly in bugprone-unchecked-optional-access, or would a new check like bugprone-unchecked-expected-access be preferable?

I think that writing a new bugprone-unchecked-expected-access is better because existing optional-access basically is a small wrapper around dataflow framework, so with the new check based on the same framework there will be hardly any unnecessary duplication of code in the UncheckedExpectedAccessCheck.cpp compared to UncheckedOptionalAccessCheck.cpp. Moreover, std::expected is a fresh feature that can evolve in the future and potentially diverge more from std::optional behavior, so having a different check will be future-proof.

@BaLiKfromUA
Copy link
Contributor Author

BaLiKfromUA commented Apr 11, 2025

@vbvictor thanks for feedback!

std::expected is a fresh feature that can evolve in the future and potentially diverge more from std::optional behavior

I agree — having a dedicated check for std::expected would make the tooling more future-proof.

That said, my main concern is maintainability: almost every false-positive fix or improvement made to bugprone-unchecked-optional-access would likely need to be replicated in bugprone-unchecked-expected-access, at least in near future. This could lead to duplication and a need to keep the logic in sync across two separate checks, which adds some ongoing maintenance overhead.


I will try to implement PoC as a separate check to see what we really need to duplicate.
So later I can try to refactor and reuse some logic of bugprone-unchecked-optional-access

@carlosgalvezp
Copy link
Contributor

Sounds good! If we are going to add it to bugprone-unchecked-optional-access it's probably good to rename it to something else more generic. Otherwise having a new check is probably not the end of the world.

Worth considering is that optional is available since C++20, while expected is from C++23, so the checks probably should be active in different standards. This would motivate having one check each. But it's also possible to implement this logic in one check, it's just not "the standard" (pun intended) way to do it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants