Skip to content

Commit 825b9a9

Browse files
fmayermikolaj-pirog
authored andcommitted
[FlowSensitive] [StatusOr] [5/N] Support absl::OkStatus et al (llvm#163872)
This allows comparison which these status codes
1 parent 2bd6c77 commit 825b9a9

File tree

3 files changed

+68
-1
lines changed

3 files changed

+68
-1
lines changed

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,24 @@ static auto isComparisonOperatorCall(llvm::StringRef operator_name) {
150150
hasArgument(1, anyOf(hasType(statusType()), hasType(statusOrType()))));
151151
}
152152

153+
static auto isOkStatusCall() {
154+
using namespace ::clang::ast_matchers; // NOLINT: Too many names
155+
return callExpr(callee(functionDecl(hasName("::absl::OkStatus"))));
156+
}
157+
158+
static auto isNotOkStatusCall() {
159+
using namespace ::clang::ast_matchers; // NOLINT: Too many names
160+
return callExpr(callee(functionDecl(hasAnyName(
161+
"::absl::AbortedError", "::absl::AlreadyExistsError",
162+
"::absl::CancelledError", "::absl::DataLossError",
163+
"::absl::DeadlineExceededError", "::absl::FailedPreconditionError",
164+
"::absl::InternalError", "::absl::InvalidArgumentError",
165+
"::absl::NotFoundError", "::absl::OutOfRangeError",
166+
"::absl::PermissionDeniedError", "::absl::ResourceExhaustedError",
167+
"::absl::UnauthenticatedError", "::absl::UnavailableError",
168+
"::absl::UnimplementedError", "::absl::UnknownError"))));
169+
}
170+
153171
static auto
154172
buildDiagnoseMatchSwitch(const UncheckedStatusOrAccessModelOptions &Options) {
155173
return CFGMatchSwitchBuilder<const Environment,
@@ -420,6 +438,23 @@ static void transferComparisonOperator(const CXXOperatorCallExpr *Expr,
420438
State.Env.setValue(*Expr, *LhsAndRhsVal);
421439
}
422440

441+
static void transferOkStatusCall(const CallExpr *Expr,
442+
const MatchFinder::MatchResult &,
443+
LatticeTransferState &State) {
444+
auto &OkVal =
445+
initializeStatus(State.Env.getResultObjectLocation(*Expr), State.Env);
446+
State.Env.assume(OkVal.formula());
447+
}
448+
449+
static void transferNotOkStatusCall(const CallExpr *Expr,
450+
const MatchFinder::MatchResult &,
451+
LatticeTransferState &State) {
452+
auto &OkVal =
453+
initializeStatus(State.Env.getResultObjectLocation(*Expr), State.Env);
454+
auto &A = State.Env.arena();
455+
State.Env.assume(A.makeNot(OkVal.formula()));
456+
}
457+
423458
CFGMatchSwitch<LatticeTransferState>
424459
buildTransferMatchSwitch(ASTContext &Ctx,
425460
CFGMatchSwitchBuilder<LatticeTransferState> Builder) {
@@ -447,6 +482,8 @@ buildTransferMatchSwitch(ASTContext &Ctx,
447482
transferComparisonOperator(Expr, State,
448483
/*IsNegative=*/true);
449484
})
485+
.CaseOfCFGStmt<CallExpr>(isOkStatusCall(), transferOkStatusCall)
486+
.CaseOfCFGStmt<CallExpr>(isNotOkStatusCall(), transferNotOkStatusCall)
450487
.Build();
451488
}
452489

clang/unittests/Analysis/FlowSensitive/MockHeaders.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1356,7 +1356,7 @@ bool operator==(const Status &lhs, const Status &rhs);
13561356
bool operator!=(const Status &lhs, const Status &rhs);
13571357
13581358
Status OkStatus();
1359-
Status InvalidArgumentError(char *);
1359+
Status InvalidArgumentError(const char *);
13601360
13611361
#endif // STATUS_H
13621362
)cc";

clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2723,6 +2723,36 @@ TEST_P(UncheckedStatusOrAccessModelTest, EqualityCheck) {
27232723
}
27242724
}
27252725
)cc");
2726+
ExpectDiagnosticsFor(R"cc(
2727+
#include "unchecked_statusor_access_test_defs.h"
2728+
2729+
void target(STATUSOR_INT sor) {
2730+
if (sor.status() == absl::OkStatus())
2731+
sor.value();
2732+
else
2733+
sor.value(); // [[unsafe]]
2734+
}
2735+
)cc");
2736+
ExpectDiagnosticsFor(R"cc(
2737+
#include "unchecked_statusor_access_test_defs.h"
2738+
2739+
void target(STATUSOR_INT sor) {
2740+
if (sor.status() != absl::OkStatus())
2741+
sor.value(); // [[unsafe]]
2742+
else
2743+
sor.value();
2744+
}
2745+
)cc");
2746+
ExpectDiagnosticsFor(R"cc(
2747+
#include "unchecked_statusor_access_test_defs.h"
2748+
2749+
void target(STATUSOR_INT sor) {
2750+
if (sor.status() != absl::InvalidArgumentError("oh no"))
2751+
sor.value(); // [[unsafe]]
2752+
else
2753+
sor.value(); // [[unsafe]]
2754+
}
2755+
)cc");
27262756
ExpectDiagnosticsFor(
27272757
R"cc(
27282758
#include "unchecked_statusor_access_test_defs.h"

0 commit comments

Comments
 (0)