[clang] 65e710c - [clang][dataflow] Model calls returning optionals
Stanislav Gatev via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 3 06:39:11 PDT 2022
Author: Stanislav Gatev
Date: 2022-06-03T13:38:22Z
New Revision: 65e710c3fc036706ec20b357a1bfce9cbadf5705
URL: https://github.com/llvm/llvm-project/commit/65e710c3fc036706ec20b357a1bfce9cbadf5705
DIFF: https://github.com/llvm/llvm-project/commit/65e710c3fc036706ec20b357a1bfce9cbadf5705.diff
LOG: [clang][dataflow] Model calls returning optionals
Model calls returning optionals
Differential Revision: https://reviews.llvm.org/D126759
Reviewed-by: ymandel, xazax.hun
Added:
Modified:
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
index c797e02cec990..22a33c397a644 100644
--- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
@@ -45,6 +45,11 @@ DeclarationMatcher optionalClass() {
auto hasOptionalType() { return hasType(optionalClass()); }
+auto hasOptionalOrAliasType() {
+ return hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(optionalClass())));
+}
+
auto isOptionalMemberCallWithName(
llvm::StringRef MemberName,
llvm::Optional<StatementMatcher> Ignorable = llvm::None) {
@@ -158,6 +163,12 @@ auto isValueOrNotEqX() {
ComparesToSame(integerLiteral(equals(0)))));
}
+auto isCallReturningOptional() {
+ return callExpr(callee(functionDecl(
+ returns(anyOf(hasOptionalOrAliasType(),
+ referenceType(pointee(hasOptionalOrAliasType())))))));
+}
+
/// Creates a symbolic value for an `optional` value using `HasValueVal` as the
/// symbolic value of its "has_value" property.
StructValue &createOptionalValue(Environment &Env, BoolValue &HasValueVal) {
@@ -322,6 +333,18 @@ void transferValueOrNotEqX(const Expr *ComparisonExpr,
});
}
+void transferCallReturningOptional(const CallExpr *E,
+ const MatchFinder::MatchResult &Result,
+ LatticeTransferState &State) {
+ if (State.Env.getStorageLocation(*E, SkipPast::None) != nullptr)
+ return;
+
+ auto &Loc = State.Env.createStorageLocation(*E);
+ State.Env.setStorageLocation(*E, Loc);
+ State.Env.setValue(
+ Loc, createOptionalValue(State.Env, State.Env.makeAtomicBoolValue()));
+}
+
void assignOptionalValue(const Expr &E, LatticeTransferState &State,
BoolValue &HasValueVal) {
if (auto *OptionalLoc =
@@ -547,6 +570,10 @@ auto buildTransferMatchSwitch(
// opt.value_or(X) != X
.CaseOf<Expr>(isValueOrNotEqX(), transferValueOrNotEqX)
+ // returns optional
+ .CaseOf<CallExpr>(isCallReturningOptional(),
+ transferCallReturningOptional)
+
.Build();
}
diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
index a501f549851f9..a4ea2bf5e5abc 100644
--- a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -2150,6 +2150,70 @@ TEST_P(UncheckedOptionalAccessTest, UniquePtrToStructWithOptionalField) {
UnorderedElementsAre(Pair("check-1", "safe"), Pair("check-2", "safe")));
}
+TEST_P(UncheckedOptionalAccessTest, CallReturningOptional) {
+ ExpectLatticeChecksFor(
+ R"(
+ #include "unchecked_optional_access_test.h"
+
+ $ns::$optional<int> MakeOpt();
+
+ void target() {
+ $ns::$optional<int> opt = 0;
+ opt = MakeOpt();
+ opt.value();
+ /*[[check-1]]*/
+ }
+ )",
+ UnorderedElementsAre(Pair("check-1", "unsafe: input.cc:9:7")));
+
+ ExpectLatticeChecksFor(
+ R"(
+ #include "unchecked_optional_access_test.h"
+
+ const $ns::$optional<int>& MakeOpt();
+
+ void target() {
+ $ns::$optional<int> opt = 0;
+ opt = MakeOpt();
+ opt.value();
+ /*[[check-2]]*/
+ }
+ )",
+ UnorderedElementsAre(Pair("check-2", "unsafe: input.cc:9:7")));
+
+ ExpectLatticeChecksFor(
+ R"(
+ #include "unchecked_optional_access_test.h"
+
+ using IntOpt = $ns::$optional<int>;
+ IntOpt MakeOpt();
+
+ void target() {
+ IntOpt opt = 0;
+ opt = MakeOpt();
+ opt.value();
+ /*[[check-3]]*/
+ }
+ )",
+ UnorderedElementsAre(Pair("check-3", "unsafe: input.cc:10:7")));
+
+ ExpectLatticeChecksFor(
+ R"(
+ #include "unchecked_optional_access_test.h"
+
+ using IntOpt = $ns::$optional<int>;
+ const IntOpt& MakeOpt();
+
+ void target() {
+ IntOpt opt = 0;
+ opt = MakeOpt();
+ opt.value();
+ /*[[check-4]]*/
+ }
+ )",
+ UnorderedElementsAre(Pair("check-4", "unsafe: input.cc:10:7")));
+}
+
// FIXME: Add support for:
// - constructors (copy, move)
// - assignment operators (default, copy, move)
More information about the cfe-commits
mailing list