aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
diff options
context:
space:
mode:
authorJan Voung <jvoung@google.com>2024-10-28 15:13:29 -0400
committerGitHub <noreply@github.com>2024-10-28 15:13:29 -0400
commit66bbbf2e951a486f972a5a54378e6791193ade60 (patch)
treed5ef38ccfe482ee7e499f03da1d45dc5912da5da /clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
parent8274be509ed9e07188a8a64d95907a46cbe8e657 (diff)
downloadllvm-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.cpp20
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)