Currently the unchecked-optional-access model fails on this example:
#include <memory> #include <optional> void foo() { std::unique_ptr<std::optional<float>> x; *x = std::nullopt; }
You can verify the failure by saving the file as foo.cpp and running this command:
clang-tidy -checks='-*,bugprone-unchecked-optional-access' foo.cpp -- -std=c++17
The failing assert is in the transferAssignment function of the UncheckedOptionalAccessModel.cpp file:
assert(OptionalLoc != nullptr);
The symptom can be treated by replacing that assert with an early return:
if (OptionalLoc == nullptr) return;
That would be better anyway since we cannot expect to always cover all possible LHS expressions, but it is out of scope for this patch and left as a followup.
Note that the failure did not occur on this very similar example:
#include <optional> template <typename T> struct smart_ptr { T& operator*() &; T* operator->(); }; void foo() { smart_ptr<std::optional<float>> x; *x = std::nullopt; }
The difference is caused by the isCallReturningOptional matcher, which was previously checking the functionDecl of the callee. This patch changes it to instead use hasType directly on the call expression, fixing the failure for the std::unique_ptr example above.
Since we're using the ast_matchers namespace, no need to qualify. Also, there's a type alias TypeMatcher that's not in the internal namespace which would be good here. That said, I'd use QualType and write it like this:
Or, I think even better in this case, just inline it: