Skip to content
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

[clang-tidy] Ignore unevaluated context in bugprone-optional-value-conversion #90410

Conversation

PiotrZSL
Copy link
Member

Ignore optionals in unevaluated context, like static_assert or decltype.

Closes #89593

…nversion

Ignore optionals in unevaluated context, like static_assert or decltype.

Closes llvm#89593
@llvmbot
Copy link
Collaborator

llvmbot commented Apr 28, 2024

@llvm/pr-subscribers-clang-tools-extra

@llvm/pr-subscribers-clang-tidy

Author: Piotr Zegar (PiotrZSL)

Changes

Ignore optionals in unevaluated context, like static_assert or decltype.

Closes #89593


Full diff: https://github.com/llvm/llvm-project/pull/90410.diff

3 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp (+3-1)
  • (modified) clang-tools-extra/docs/ReleaseNotes.rst (+4)
  • (modified) clang-tools-extra/test/clang-tidy/checkers/bugprone/optional-value-conversion.cpp (+2)
diff --git a/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp
index 9ab59e6b0474f0..600eab37552766 100644
--- a/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp
@@ -71,7 +71,9 @@ void OptionalValueConversionCheck::registerMatchers(MatchFinder *Finder) {
               ofClass(matchers::matchesAnyListedName(OptionalTypes)))),
           hasType(ConstructTypeMatcher),
           hasArgument(0U, ignoringImpCasts(anyOf(OptionalDereferenceMatcher,
-                                                 StdMoveCallMatcher))))
+                                                 StdMoveCallMatcher))),
+          unless(anyOf(hasAncestor(typeLoc()),
+                       hasAncestor(expr(matchers::hasUnevaluatedContext())))))
           .bind("expr"),
       this);
 }
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 3038d2b125f20d..062e619e0fe141 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -190,6 +190,10 @@ Changes in existing checks
   eliminating false positives resulting from direct usage of bitwise operators
   within parentheses.
 
+- Improved :doc:`bugprone-optional-value-conversion
+  <clang-tidy/checks/bugprone/optional-value-conversion>` check by eliminating
+  false positives resulting from use of optionals in unevaluated context.
+
 - Improved :doc:`bugprone-suspicious-include
   <clang-tidy/checks/bugprone/suspicious-include>` check by replacing the local
   options `HeaderFileExtensions` and `ImplementationFileExtensions` by the
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/optional-value-conversion.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/optional-value-conversion.cpp
index 72ef35c956d2e8..1228d64bb6909e 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/optional-value-conversion.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/optional-value-conversion.cpp
@@ -210,4 +210,6 @@ void correct(std::optional<int> param)
   std::optional<long>* p2 = &p;
   takeOptionalValue(p2->value_or(5U));
   takeOptionalRef(p2->value_or(5U));
+
+  using Type = decltype(takeOptionalValue(*param));
 }

Copy link
Contributor

@5chmidti 5chmidti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we maybe want to explicitly match decltype, sizeof, static_cast etc. instead of typeLoc?
Because I don't think we would want to ignore https://godbolt.org/z/r3bK961do

#include <optional>

constexpr std::optional<int> foo() { return 42; }

constexpr int select(std::optional<int> val) { return val.value_or(0); }

template <int val>
struct bar {};

void use() { using F = bar<select(foo().value())>; }

(There are other checks with this ignore pattern, depending on the answer to my question we should check those as well)

@PiotrZSL
Copy link
Member Author

PiotrZSL commented May 8, 2024

@5chmidti
I did some testing with this. And in example that you provided there is no issue.
This is because if optional will be uninitialized, then this code won't compile regardless if .value() or operator * is used.
Compiler will simply complain that expression is not constexpr.

When used normally, you will get undefined behavior or exception.

@5chmidti
Copy link
Contributor

5chmidti commented May 9, 2024

And in example that you provided there is no issue.

Alright, at least not a bugrprone issue. And the argument for a readability issue (which is the direction I initially was going) would probably end in someone saying we use this to diagnose compile errors earlier, not deeper in any instantiations

@PiotrZSL PiotrZSL merged commit 6993798 into llvm:main May 13, 2024
8 checks passed
@PiotrZSL PiotrZSL deleted the 89593-clang-tidy-bugprone-optional-value-conversion-should-ignore-unevaluated-context branch May 13, 2024 18:41
nhasabni pushed a commit to nhasabni/llvm-project that referenced this pull request May 14, 2024
…nversion (llvm#90410)

Ignore optionals in unevaluated context, like static_assert or decltype.

Closes llvm#89593
mub-at-arm pushed a commit to mub-at-arm/llvm-project that referenced this pull request May 16, 2024
…nversion (llvm#90410)

Ignore optionals in unevaluated context, like static_assert or decltype.

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

Successfully merging this pull request may close these issues.

[clang-tidy] bugprone-optional-value-conversion - should ignore unevaluated context
3 participants