diff options
author | Jan Voung <jvoung@google.com> | 2024-10-28 15:13:29 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-28 15:13:29 -0400 |
commit | 66bbbf2e951a486f972a5a54378e6791193ade60 (patch) | |
tree | d5ef38ccfe482ee7e499f03da1d45dc5912da5da /clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp | |
parent | 8274be509ed9e07188a8a64d95907a46cbe8e657 (diff) | |
download | llvm-66bbbf2e951a486f972a5a54378e6791193ade60.zip llvm-66bbbf2e951a486f972a5a54378e6791193ade60.tar.gz llvm-66bbbf2e951a486f972a5a54378e6791193ade60.tar.bz2 |
[clang][dataflow] Cache accessors returning pointers in bugprone-unchecked-optional-access (#113922)
Previously, we covered returning refs, or copies of optional, and bools.
Now cover returning pointers (to any type).
This is useful for cases like operator-> of smart pointers.
Addresses more of issue llvm#58510
Diffstat (limited to 'clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp')
-rw-r--r-- | clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp index 31ae2b9..da5dda0 100644 --- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp +++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp @@ -338,6 +338,11 @@ auto isZeroParamConstMemberCall() { callee(cxxMethodDecl(parameterCountIs(0), isConst()))); } +auto isZeroParamConstMemberOperatorCall() { + return cxxOperatorCallExpr( + callee(cxxMethodDecl(parameterCountIs(0), isConst()))); +} + auto isNonConstMemberCall() { return cxxMemberCallExpr(callee(cxxMethodDecl(unless(isConst())))); } @@ -572,9 +577,10 @@ void handleConstMemberCall(const CallExpr *CE, return; } - // Cache if the const method returns a boolean type. + // Cache if the const method returns a boolean or pointer type. // We may decide to cache other return types in the future. - if (RecordLoc != nullptr && CE->getType()->isBooleanType()) { + if (RecordLoc != nullptr && + (CE->getType()->isBooleanType() || CE->getType()->isPointerType())) { Value *Val = State.Lattice.getOrCreateConstMethodReturnValue(*RecordLoc, CE, State.Env); if (Val == nullptr) @@ -597,6 +603,14 @@ void transferValue_ConstMemberCall(const CXXMemberCallExpr *MCE, MCE, dataflow::getImplicitObjectLocation(*MCE, State.Env), Result, State); } +void transferValue_ConstMemberOperatorCall( + const CXXOperatorCallExpr *OCE, const MatchFinder::MatchResult &Result, + LatticeTransferState &State) { + auto *RecordLoc = cast_or_null<dataflow::RecordStorageLocation>( + State.Env.getStorageLocation(*OCE->getArg(0))); + handleConstMemberCall(OCE, RecordLoc, Result, State); +} + void handleNonConstMemberCall(const CallExpr *CE, dataflow::RecordStorageLocation *RecordLoc, const MatchFinder::MatchResult &Result, @@ -1020,6 +1034,8 @@ auto buildTransferMatchSwitch() { // const accessor calls .CaseOfCFGStmt<CXXMemberCallExpr>(isZeroParamConstMemberCall(), transferValue_ConstMemberCall) + .CaseOfCFGStmt<CXXOperatorCallExpr>(isZeroParamConstMemberOperatorCall(), + transferValue_ConstMemberOperatorCall) // non-const member calls that may modify the state of an object. .CaseOfCFGStmt<CXXMemberCallExpr>(isNonConstMemberCall(), transferValue_NonConstMemberCall) |