From 0c6eedc835ace00b93fb2e8d28b21fb8ccc799d3 Mon Sep 17 00:00:00 2001 From: Daiva Naudziuniene Date: Thu, 17 Dec 2020 01:50:44 -0800 Subject: [PATCH] [pulse] Model std::__optional_storage_base::has_value Summary: Model ` std::__optional_storage_base::has_value` as this is what we see in clang AST when translating `std::optional::has_value` for libc++. For libstdc++, we get `std::optional::has_value` as expected. Reviewed By: skcho, jvillard Differential Revision: D25585543 fbshipit-source-id: b8d9d2902 --- infer/src/pulse/PulseModels.ml | 8 +++--- .../codetoanalyze/cpp/pulse/optional.cpp | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/infer/src/pulse/PulseModels.ml b/infer/src/pulse/PulseModels.ml index ebceb47e5..8da884e47 100644 --- a/infer/src/pulse/PulseModels.ml +++ b/infer/src/pulse/PulseModels.ml @@ -1075,14 +1075,14 @@ module ProcNameDispatcher = struct ~desc:"std::optional::optional(std::optional arg)" ; -"std" &:: "optional" &:: "optional" $ capt_arg_payload $+ capt_arg_payload $+...$--> Optional.assign_value ~desc:"std::optional::optional(Value arg)" - ; -"std" &:: "optional" &:: "operator=" <>$ capt_arg_payload + ; -"std" &:: "optional" &:: "operator=" $ capt_arg_payload $+ any_arg_of_typ (-"std" &:: "nullopt_t") $--> Optional.assign_none ~desc:"std::optional::operator=(None)" - ; -"std" &:: "optional" &:: "operator=" <>$ capt_arg_payload + ; -"std" &:: "optional" &:: "operator=" $ capt_arg_payload $+ capt_arg_payload_of_typ (-"std" &:: "optional") $--> Optional.assign_optional_value ~desc:"std::optional::operator=(std::optional arg)" - ; -"std" &:: "optional" &:: "operator=" <>$ capt_arg_payload $+ capt_arg_payload + ; -"std" &:: "optional" &:: "operator=" $ capt_arg_payload $+ capt_arg_payload $+...$--> Optional.assign_value ~desc:"std::optional::operator=(Value arg)" ; -"std" &:: "optional" &:: "emplace<>" $ capt_arg_payload $+...$--> Optional.emplace ~desc:"std::optional::emplace()" @@ -1090,6 +1090,8 @@ module ProcNameDispatcher = struct $+...$--> Optional.emplace ~desc:"std::optional::emplace()" ; -"std" &:: "optional" &:: "has_value" <>$ capt_arg_payload $+...$--> Optional.has_value ~desc:"std::optional::has_value()" + ; -"std" &:: "__optional_storage_base" &:: "has_value" $ capt_arg_payload + $+...$--> Optional.has_value ~desc:"std::optional::has_value()" ; -"std" &:: "optional" &:: "operator_bool" <>$ capt_arg_payload $+...$--> Optional.has_value ~desc:"std::optional::operator_bool()" ; -"std" &:: "optional" &:: "reset" <>$ capt_arg_payload diff --git a/infer/tests/codetoanalyze/cpp/pulse/optional.cpp b/infer/tests/codetoanalyze/cpp/pulse/optional.cpp index d9b90e73d..fac78061a 100644 --- a/infer/tests/codetoanalyze/cpp/pulse/optional.cpp +++ b/infer/tests/codetoanalyze/cpp/pulse/optional.cpp @@ -238,6 +238,14 @@ int std_none_check_ok() { return -1; } +int std_none_check_has_value_ok() { + std::optional foo{std::nullopt}; + if (foo.has_value()) { + return foo.value(); + } + return -1; +} + int std_none_no_check_bad() { std::optional foo{std::nullopt}; return foo.value(); @@ -305,6 +313,7 @@ int std_value_or_check_value_ok_FP() { } return -1; } + struct Container final { std::vector _vec; @@ -324,3 +333,19 @@ struct Container final { return -1; } }; + +std::optional might_return_none(bool b, std::string x) { + if (b) { + return std::nullopt; + } + return x; +} + +std::string reassing_non_empty_ok(const std::string& x) { + std::optional foo = might_return_none(true, x); + if (!foo.has_value()) { + foo = x; + } + + return foo.value(); +}