@@ -3918,9 +3918,129 @@ TEST_P(UncheckedOptionalAccessTest, ConstRefAccessorToOptionalViaConstRefAccesso
39183918 )cc" );
39193919}
39203920
3921- // todo: non const accessor
3922- // todo: different accessor in between
3923- // todo: const copy
3921+ TEST_P (UncheckedOptionalAccessTest, ConstRefToOptionalSavedAsTemporaryVariable) {
3922+ ExpectDiagnosticsFor (R"cc(
3923+ #include "unchecked_optional_access_test.h"
3924+
3925+ class A {
3926+ public:
3927+ const $ns::$optional<int>& get() const { return x; }
3928+
3929+ private:
3930+ $ns::$optional<int> x;
3931+ };
3932+
3933+ class B {
3934+ public:
3935+ const A& getA() const { return a; }
3936+
3937+ private:
3938+ A a;
3939+ };
3940+
3941+ void target(B& b) {
3942+ const auto& opt = b.getA().get();
3943+ if (opt.has_value()) {
3944+ opt.value();
3945+ }
3946+ }
3947+ )cc" );
3948+ }
3949+
3950+ TEST_P (UncheckedOptionalAccessTest, ConstRefAccessorToOptionalViaConstValueAccessorToHoldingObject) {
3951+ ExpectDiagnosticsFor (R"cc(
3952+ #include "unchecked_optional_access_test.h"
3953+
3954+ class A {
3955+ public:
3956+ const $ns::$optional<int>& get() const { return x; }
3957+
3958+ private:
3959+ $ns::$optional<int> x;
3960+ };
3961+
3962+ class B {
3963+ public:
3964+ const A copyA() const { return a; }
3965+
3966+ private:
3967+ A a;
3968+ };
3969+
3970+ void target(B& b) {
3971+ if (b.copyA().get().has_value()) {
3972+ b.copyA().get().value(); // [[unsafe]]
3973+ }
3974+ }
3975+ )cc" );
3976+ }
3977+
3978+ TEST_P (UncheckedOptionalAccessTest, ConstRefAccessorToOptionalViaNonConstRefAccessorToHoldingObject) {
3979+ ExpectDiagnosticsFor (R"cc(
3980+ #include "unchecked_optional_access_test.h"
3981+
3982+ class A {
3983+ public:
3984+ const $ns::$optional<int>& get() const { return x; }
3985+
3986+ private:
3987+ $ns::$optional<int> x;
3988+ };
3989+
3990+ class B {
3991+ public:
3992+ A& getA() { return a; }
3993+
3994+ private:
3995+ A a;
3996+ };
3997+
3998+ void target(B& b) {
3999+ if (b.getA().get().has_value()) {
4000+ b.getA().get().value(); // [[unsafe]]
4001+ }
4002+ }
4003+ )cc" );
4004+ }
4005+
4006+ TEST_P (UncheckedOptionalAccessTest, ConstRefAccessorToOptionalViaNonConstRefAccessorToHoldingObjectWithModAfterCheck) {
4007+ ExpectDiagnosticsFor (R"cc(
4008+ #include "unchecked_optional_access_test.h"
4009+
4010+ class A {
4011+ public:
4012+ const $ns::$optional<int>& get() const { return x; }
4013+ private:
4014+ $ns::$optional<int> x;
4015+ };
4016+
4017+ class B {
4018+ public:
4019+ const A& getA() const { return a; }
4020+
4021+ A& getA() { return a; }
4022+
4023+ void clear() { a = A{}; };
4024+
4025+ private:
4026+ A a;
4027+ };
4028+
4029+ void target(B& b) {
4030+ // changing field A via non-const getter after const getter check
4031+ if (b.getA().get().has_value()) {
4032+ b.getA() = A{};
4033+ b.getA().get().value(); // [[unsafe]]
4034+ }
4035+
4036+ // calling non-const method which might change field A
4037+ if (b.getA().get().has_value()) {
4038+ b.clear();
4039+ b.getA().get().value(); // [[unsafe]]
4040+ }
4041+ }
4042+ )cc" );
4043+ }
39244044
39254045// FIXME: Add support for:
39264046// - constructors (copy, move)
0 commit comments