Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[clang-tidy]bugprone-unchecked-optional-access: handleBloombergLP::bdlb:NullableValue::makeValue to prevent false-positives#144313

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
BaLiKfromUA wants to merge3 commits intollvm:main
base:main
Choose a base branch
Loading
fromBaLiKfromUA-education:makeValue-false-positive

Conversation

BaLiKfromUA
Copy link
Contributor

@BaLiKfromUABaLiKfromUA commentedJun 16, 2025
edited
Loading

#101450 added support forBloombergLP::bdlb::NullableValue.

However,NullableValue::makeValue andNullableValue::makeValueInplace have been missed which impacts code like this:

if (opt.isNull()) {    opt.makeValue(42);  }  opt.value();// triggers false positive warning from `bugprone-unchecked-optional-access`

My patch addresses this issue.

Docs that I used for methods mocks

@llvmbotllvmbot added clangClang issues not falling into any other category clang-tools-extra clang-tidy clang:dataflowClang Dataflow Analysis framework - https://clang.llvm.org/docs/DataFlowAnalysisIntro.html clang:analysis labelsJun 16, 2025
@BaLiKfromUABaLiKfromUA changed the title[clang-tidy]bugprone-unchecked-optional-access: handleNullableValue::makeValue to prevent false-positives[clang-tidy]bugprone-unchecked-optional-access: handleBloombergLP::bdlb:NullableValue::makeValue to prevent false-positivesJun 16, 2025
@llvmbot
Copy link
Member

llvmbot commentedJun 16, 2025
edited
Loading

@llvm/pr-subscribers-clang-tidy
@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-analysis

Author: Valentyn Yukhymenko (BaLiKfromUA)

Changes

#101450 added support forBloombergLP::bdlb::NullableValue.

However,NullableValue::makeValue andNullableValue::makeValueInplace have been missed which impacts code like this:

if (opt.isNull()) {    opt.makeValue(42);  }  opt.value();// triggers false positive warning from `bugprone-unchecked-optional-access`

My patch addresses this issue.


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

3 Files Affected:

  • (modified) clang-tools-extra/test/clang-tidy/checkers/bugprone/Inputs/unchecked-optional-access/bde/types/bdlb_nullablevalue.h (+8)
  • (modified) clang-tools-extra/test/clang-tidy/checkers/bugprone/unchecked-optional-access.cpp (+14)
  • (modified) clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp (+13)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/Inputs/unchecked-optional-access/bde/types/bdlb_nullablevalue.h b/clang-tools-extra/test/clang-tidy/checkers/bugprone/Inputs/unchecked-optional-access/bde/types/bdlb_nullablevalue.hindex 4411bcfd60a74..0812677111995 100644--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/Inputs/unchecked-optional-access/bde/types/bdlb_nullablevalue.h+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/Inputs/unchecked-optional-access/bde/types/bdlb_nullablevalue.h@@ -20,6 +20,14 @@ class NullableValue : public bsl::optional<T> {   const T &value() const &;   T &value() &;+  constexpr T &makeValue();++  template <typename U>+  constexpr T &makeValue(U&& v);++  template <typename... ARGS>+  constexpr T &makeValueInplace(ARGS &&... args);+   // 'operator bool' is inherited from bsl::optional    constexpr bool isNull() const noexcept;diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unchecked-optional-access.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unchecked-optional-access.cppindex 3167b85f0e024..b910db20b3c2e 100644--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unchecked-optional-access.cpp+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unchecked-optional-access.cpp@@ -141,6 +141,20 @@ void nullable_value_after_swap(BloombergLP::bdlb::NullableValue<int> &opt1, Bloo   } }+void nullable_value_make_value(BloombergLP::bdlb::NullableValue<int> &opt1, BloombergLP::bdlb::NullableValue<int> &opt2) {+  if (opt1.isNull()) {+    opt1.makeValue(42);+  }++  opt1.value();++  if (opt2.isNull()) {+    opt2.makeValueInplace(42);+  }++  opt2.value();+}+ template <typename T> void function_template_without_user(const absl::optional<T> &opt) {   opt.value(); // no-warningdiff --git a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cppindex 164d2574132dd..decb32daa9410 100644--- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp+++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp@@ -985,6 +985,19 @@ auto buildTransferMatchSwitch() {           isOptionalMemberCallWithNameMatcher(hasName("isNull")),           transferOptionalIsNullCall)+      // NullableValue::makeValue, NullableValue::makeValueInplace+      // Only NullableValue has these methods, but this+      // will also pass for other types+      .CaseOfCFGStmt<CXXMemberCallExpr>(+          isOptionalMemberCallWithNameMatcher(hasAnyName("makeValue", "makeValueInplace")),+          [](const CXXMemberCallExpr *E, const MatchFinder::MatchResult &,+             LatticeTransferState &State) {+            if (RecordStorageLocation *Loc =+                    getImplicitObjectLocation(*E, State.Env)) {+              setHasValue(*Loc, State.Env.getBoolLiteralValue(true), State.Env);+            }+          })+       // optional::emplace       .CaseOfCFGStmt<CXXMemberCallExpr>(           isOptionalMemberCallWithNameMatcher(hasName("emplace")),

@BaLiKfromUA
Copy link
ContributorAuthor

At the moment of the previous PR, there was a concern about configurability of check --#101450 (review)

I am happy to address it separately if it's still a concern and if someone can guide me for first steps :)

@github-actionsGitHub Actions
Copy link

github-actionsbot commentedJun 16, 2025
edited
Loading

✅ With the latest revision this PR passed the C/C++ code formatter.

@vbvictor
Copy link
Contributor

At the moment of the previous PR, there was a concern about configurability of check

I think I was about adding an option to configure list of optional classes. ProbablyOptionalClasses or similar.
I haven't seen issues about it, so it may not be a high priority.

BaLiKfromUA reacted with thumbs up emoji

Comment on lines +988 to +1001
// NullableValue::makeValue, NullableValue::makeValueInplace
// Only NullableValue has these methods, but this
// will also pass for other types
.CaseOfCFGStmt<CXXMemberCallExpr>(
isOptionalMemberCallWithNameMatcher(
hasAnyName("makeValue", "makeValueInplace")),
[](const CXXMemberCallExpr *E, const MatchFinder::MatchResult &,
LatticeTransferState &State) {
if (RecordStorageLocation *Loc =
getImplicitObjectLocation(*E, State.Env)) {
setHasValue(*Loc, State.Env.getBoolLiteralValue(true), State.Env);
}
})

Copy link
Contributor

Choose a reason for hiding this comment

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

I think configurable option is needed instead of hard code function name for non-std libarary.

Copy link
ContributorAuthor

@BaLiKfromUABaLiKfromUAJun 16, 2025
edited
Loading

Choose a reason for hiding this comment

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

@HerrCai0907 I am happy to do so! Are there any examples how it looks for other clang-tidy checks?

Also, do you want to do it in scope of this PR or as a separate one?
Since non-std function names (e.g.hasValue) are also processed forfolly::Optional in code above my change.

Thanks for review!

Copy link
Contributor

Choose a reason for hiding this comment

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

You can look atno-malloc check for similar option with function names.

You can add function-lists both forbdlb and other libraries. The code must be very similar.

BaLiKfromUA reacted with eyes emoji
Copy link
ContributorAuthor

@BaLiKfromUABaLiKfromUAJun 23, 2025
edited
Loading

Choose a reason for hiding this comment

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

@vbvictor, thank you for the help! I checked the implementation ofno-malloc configuration, and it does make sense to me.

Just want to double-check expectation, do we want to have a configuration like this, with just method names (name of options is subject to change):

NonStdMakeValue: makeValue;makeValueInplace.// BloombergLP::bdlb:NullableValueNonStdHasValue: hasValue.// folly::OptionalNonStdNoValue: isNull.// BloombergLP::bdlb:NullableValue

Or do we want to specify which class method belongs to:

NonStdMakeValue: BloombergLP::bdlb:NullableValue::makeValue;BloombergLP::bdlb:NullableValue::makeValueInplace.NonStdHasValue: folly::Optional::hasValue. NonStdNoValue: BloombergLP::bdlb:NullableValue::isNull.

For me, the first version looks better because:

  • It's easier
  • It makes it possible to easily enable this check for more "make value" custom methods in classes inherited from the optional.

However, it's less intuitive to me than option two because different non-standard methods belong to different classes. But this is how it works now, so maybe we could build on top of it, just with method names, and then improve it or extend it.

Copy link
Contributor

@vbvictorvbvictorJun 24, 2025
edited
Loading

Choose a reason for hiding this comment

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

I'd prefer 2nd option because we have more control over what method belong to what class. Imagine this situation:

structoptional1() {hasNull();// check that it has value but it's nullptrisNull();// check that it has no value inside}structoptional2() {hasNull();// check that it has no value inside}

If we go with 1st option, we would writeNonStdNoValue: hasNull;isNull, but that would produce errors becauseoptional1::hasNull doesn't actually check for no value,optional1::isNull does.
To express intentional behavior, we need to writeNonStdNoValue: optional2::hasNull;optional1::isNull.

Copy link
Contributor

@vbvictorvbvictorJun 24, 2025
edited
Loading

Choose a reason for hiding this comment

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

But if it works like option1 right now, I don't oppose implementing option1.
I suppose we could harden it in the future if ever needed. My example withoptional1 andoptional2 wouldn't likely appear in real life IMO.

Copy link
ContributorAuthor

@BaLiKfromUABaLiKfromUAJul 6, 2025
edited
Loading

Choose a reason for hiding this comment

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

I started experimenting with implementing the mentioned configuration and have a doubt that I would like to talk about.

What is the preferred way to passUncheckedOptionalAccessModelOptions intoUncheckedOptionalAccessModel?

Currently, the existing configuration (IgnoreSmartPointerDereference) is being passed only intoUncheckedOptionalAccessDiagnoser, which is not what I need in my case.

If I understand correctly, passingOptions intoModel requires changes toDataflowAnalysis.h.

The "cheapest" solution might be to implement code like thishere:

template<typename AnalysisT,typename OptionsT>autocreateAnalysis(ASTContext &ASTCtx, Environment &Env, OptionsT &Options)    -> decltype(AnalysisT(ASTCtx, Env, OptionsT)) {returnAnalysisT(ASTCtx, Env, Options);}

Plus, modify the code that calls it and extend the constructor of theUncheckedOptionalAccessModel.

But,theFIXME comment nearby highlights that this approach is rather a hack and should be refactored later.

I also see that there isDataflowAnalysisContext::Options, but I am not sure if it's super useful for my case.

@vbvictor would appreciate your feedback!

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not familiar with dataflow framework and I can't give a good direction for implementing this.
Addedymand as one of the previous reviewers of the code andXazax-hun,gribozavr as maintainers of analysis framework.
They may share an opinion on this matter.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'll defer to@ymand on the final decision what is the best way to do this. But in my opinion, this make a strong argument that the analysis instance should always be created by the client (e.g., we should pass the analysis instance todiagnoseFunction and similar) as all analyses might need different configuration options and we definitely don't want to deal with all that in a generic way in the framework.

@vbvictor
Copy link
Contributor

Analysis reviewers, could you please take a look at this#144313 (comment). Your opinion is highly appreciated!

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@PiotrZSLPiotrZSLAwaiting requested review from PiotrZSL

@carlosgalvezpcarlosgalvezpAwaiting requested review from carlosgalvezp

@vbvictorvbvictorAwaiting requested review from vbvictor

@HerrCai0907HerrCai0907Awaiting requested review from HerrCai0907

@ymandymandAwaiting requested review from ymand

@Xazax-hunXazax-hunAwaiting requested review from Xazax-hun

@gribozavrgribozavrAwaiting requested review from gribozavr

Assignees
No one assigned
Labels
clang:analysisclang:dataflowClang Dataflow Analysis framework - https://clang.llvm.org/docs/DataFlowAnalysisIntro.htmlclangClang issues not falling into any other categoryclang-tidyclang-tools-extra
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

5 participants
@BaLiKfromUA@llvmbot@vbvictor@Xazax-hun@HerrCai0907

[8]ページ先頭

©2009-2025 Movatter.jp