Skip to content

Commit c745f74

Browse files
authored
[FlowSensitive] [StatusOr] [7/N] Support StatusOr::emplace
This always makes the StatusOr OK. Reviewers: jvoung, Xazax-hun Reviewed By: jvoung Pull Request: #163876
1 parent a909ec6 commit c745f74

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,18 @@ static void transferNotOkStatusCall(const CallExpr *Expr,
516516
State.Env.assume(A.makeNot(OkVal.formula()));
517517
}
518518

519+
static void transferEmplaceCall(const CXXMemberCallExpr *Expr,
520+
const MatchFinder::MatchResult &,
521+
LatticeTransferState &State) {
522+
RecordStorageLocation *StatusOrLoc =
523+
getImplicitObjectLocation(*Expr, State.Env);
524+
if (StatusOrLoc == nullptr)
525+
return;
526+
527+
auto &OkVal = valForOk(locForStatus(*StatusOrLoc), State.Env);
528+
State.Env.assume(OkVal.formula());
529+
}
530+
519531
CFGMatchSwitch<LatticeTransferState>
520532
buildTransferMatchSwitch(ASTContext &Ctx,
521533
CFGMatchSwitchBuilder<LatticeTransferState> Builder) {
@@ -559,6 +571,8 @@ buildTransferMatchSwitch(ASTContext &Ctx,
559571
})
560572
.CaseOfCFGStmt<CallExpr>(isOkStatusCall(), transferOkStatusCall)
561573
.CaseOfCFGStmt<CallExpr>(isNotOkStatusCall(), transferNotOkStatusCall)
574+
.CaseOfCFGStmt<CXXMemberCallExpr>(isStatusOrMemberCallWithName("emplace"),
575+
transferEmplaceCall)
562576
.Build();
563577
}
564578

clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2928,6 +2928,53 @@ TEST_P(UncheckedStatusOrAccessModelTest, PointerEqualityCheck) {
29282928
)cc");
29292929
}
29302930

2931+
TEST_P(UncheckedStatusOrAccessModelTest, Emplace) {
2932+
ExpectDiagnosticsFor(R"cc(
2933+
#include "unchecked_statusor_access_test_defs.h"
2934+
2935+
struct Foo {
2936+
Foo(int);
2937+
};
2938+
2939+
void target(absl::StatusOr<Foo> sor, int value) {
2940+
sor.emplace(value);
2941+
sor.value();
2942+
}
2943+
)cc");
2944+
ExpectDiagnosticsFor(R"cc(
2945+
#include "unchecked_statusor_access_test_defs.h"
2946+
2947+
struct Foo {
2948+
Foo(std::initializer_list<int>, int);
2949+
};
2950+
2951+
void target(absl::StatusOr<Foo> sor, int value) {
2952+
sor.emplace({1, 2, 3}, value);
2953+
sor.value();
2954+
}
2955+
)cc");
2956+
ExpectDiagnosticsFor(R"cc(
2957+
#include "unchecked_statusor_access_test_defs.h"
2958+
2959+
void target() {
2960+
STATUSOR_INT sor;
2961+
bool sor_ok = sor.ok();
2962+
if (!sor_ok)
2963+
sor.emplace(42);
2964+
sor.value();
2965+
}
2966+
)cc");
2967+
ExpectDiagnosticsFor(R"cc(
2968+
#include "unchecked_statusor_access_test_defs.h"
2969+
2970+
void target(bool b) {
2971+
STATUSOR_INT sor;
2972+
if (b) sor.emplace(42);
2973+
if (b) sor.value();
2974+
}
2975+
)cc");
2976+
}
2977+
29312978
} // namespace
29322979

29332980
std::string

0 commit comments

Comments
 (0)