-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Description
Hi folks!
Recently, I found an interesting bug related to accessing an optional field by reference via a method.
Initially, I thought that it might be in the same nature as #128437, but now I think it's much more complicated.
Let's assume we have next code:
class A {
private:
std::optional<int> d_field;
public:
const std::optional<int>& getField() const {
return d_field;
}
std::optional<int>& setField() {
return d_field;
}
private:
// no violations
void do_something_with_optional() {
if (!d_field.has_value()) {
d_field = 42;
}
std::cout << d_field.value();
}
};
Code below triggers warnings from check even though it's technically similar to A::do_something_with_optional()
:
// false positive
void foo1(A data) {
if (!data.getField().has_value()) {
data.setField() = 42;
}
std::cout << data.getField().value();
}
It also can be reproduced even by code like this:
// false positive
void foo2(A data) {
data.setField() = 42;
std::cout << data.getField().value();
}
My understanding why it doesn't work
IIRC the implementation of a given check, we don't analyze the access to non-const methods, even if they return optional field by reference. Plus, any access to them invalidate the stored state of related optional field that we have seen before.
Probably the fix is not simple since we cannot just rely on the method name (as I did in my previous fix), we need to understand that it returns exactly the same optional field as was modified before.
I believe the proper fix also might address the issue like #151287 when we call non-const method which doesn't modify optional data, but maybe I am wrong :)
I am happy to explore the solution but need an initial guidance.
Thanks!