@@ -3419,6 +3419,15 @@ TEST_P(UncheckedStatusOrAccessModelTest, NestedStatusOr) {
34193419 result.value();
34203420 }
34213421 )cc" );
3422+ ExpectDiagnosticsFor (R"cc(
3423+ #include "unchecked_statusor_access_test_defs.h"
3424+
3425+ void target() {
3426+ absl::StatusOr<STATUSOR_INT> result = Make<STATUSOR_INT>();
3427+ if (result.value().ok())
3428+ result.value().value();
3429+ }
3430+ )cc" );
34223431}
34233432
34243433TEST_P (UncheckedStatusOrAccessModelTest, PtrConstruct) {
@@ -3739,6 +3748,168 @@ TEST_P(UncheckedStatusOrAccessModelTest, UniquePtrReset) {
37393748 )cc" );
37403749}
37413750
3751+ TEST_P (UncheckedStatusOrAccessModelTest, NestedStatusOrInStatusOrStruct) {
3752+ // Non-standard assignment with a nested StatusOr.
3753+ ExpectDiagnosticsFor (
3754+ R"cc(
3755+ #include "unchecked_statusor_access_test_defs.h"
3756+
3757+ struct Inner {
3758+ absl::StatusOr<std::string> sor;
3759+ };
3760+
3761+ struct Outer {
3762+ absl::StatusOr<Inner> inner;
3763+ };
3764+
3765+ void target() {
3766+ Outer foo = Make<Outer>();
3767+ foo.inner->sor = "a"; // [[unsafe]]
3768+ }
3769+ )cc" );
3770+
3771+ ExpectDiagnosticsFor (
3772+ R"cc(
3773+ #include "unchecked_statusor_access_test_defs.h"
3774+
3775+ struct Foo {
3776+ absl::StatusOr<std::string> sor;
3777+ };
3778+
3779+ void target(const absl::StatusOr<Foo>& foo) {
3780+ if (foo.ok() && foo->sor.ok()) foo->sor.value();
3781+ }
3782+ )cc" );
3783+
3784+ ExpectDiagnosticsFor (
3785+ R"cc(
3786+ #include "unchecked_statusor_access_test_defs.h"
3787+
3788+ struct Foo {
3789+ absl::StatusOr<std::string> sor;
3790+ };
3791+
3792+ void target(const absl::StatusOr<Foo>& foo) {
3793+ if (foo.ok() && foo.value().sor.ok()) foo->sor.value();
3794+ }
3795+ )cc" );
3796+
3797+ ExpectDiagnosticsFor (
3798+ R"cc(
3799+ #include "unchecked_statusor_access_test_defs.h"
3800+
3801+ struct Foo {
3802+ absl::StatusOr<std::string> sor;
3803+ };
3804+
3805+ void target(const absl::StatusOr<Foo>& foo) {
3806+ if (foo.ok() && (*foo).sor.ok()) (*foo).sor.value();
3807+ }
3808+ )cc" );
3809+
3810+ ExpectDiagnosticsFor (
3811+ R"cc(
3812+ #include "unchecked_statusor_access_test_defs.h"
3813+
3814+ struct Foo {
3815+ absl::StatusOr<std::string> sor;
3816+ };
3817+
3818+ void target(absl::StatusOr<Foo>& foo) {
3819+ if (foo.ok() && foo->sor.ok()) *foo->sor;
3820+ }
3821+ )cc" );
3822+ // With assignment.
3823+ ExpectDiagnosticsFor (
3824+ R"cc(
3825+ #include "unchecked_statusor_access_test_defs.h"
3826+
3827+ struct Foo {
3828+ absl::StatusOr<std::string> sor;
3829+ };
3830+
3831+ void target(absl::StatusOr<Foo>& foo) {
3832+ if (foo.ok() && foo->sor.ok()) {
3833+ foo->sor = Make<absl::StatusOr<std::string>>();
3834+ foo->sor.value(); // [[unsafe]]
3835+ }
3836+ }
3837+ )cc" );
3838+
3839+ ExpectDiagnosticsFor (
3840+ R"cc(
3841+ #include "unchecked_statusor_access_test_defs.h"
3842+
3843+ struct Foo {
3844+ absl::StatusOr<std::string> sor;
3845+ };
3846+
3847+ void target(absl::StatusOr<Foo>& foo) {
3848+ if (foo.ok() && foo->sor.ok()) {
3849+ auto n = Make<absl::StatusOr<std::string>>();
3850+ if (n.ok()) foo->sor = n;
3851+ foo->sor.value();
3852+ }
3853+ }
3854+ )cc" );
3855+
3856+ ExpectDiagnosticsFor (
3857+ R"cc(
3858+ #include "unchecked_statusor_access_test_defs.h"
3859+
3860+ struct Foo {
3861+ absl::StatusOr<std::string> sor;
3862+ };
3863+
3864+ void target(absl::StatusOr<Foo>& foo) {
3865+ if (foo.ok() && foo->sor.ok()) {
3866+ auto n = Make<absl::StatusOr<std::string>>();
3867+ if (n.ok()) foo->sor = std::move(n);
3868+ foo->sor.value();
3869+ }
3870+ }
3871+ )cc" );
3872+
3873+ // More complicated conditionals.
3874+ ExpectDiagnosticsFor (
3875+ R"cc(
3876+ #include "unchecked_statusor_access_test_defs.h"
3877+
3878+ struct Foo {
3879+ absl::StatusOr<std::string> sor;
3880+ };
3881+
3882+ void target(absl::StatusOr<Foo>& foo) {
3883+ if (!foo.ok()) return;
3884+ if (!foo->sor.ok())
3885+ foo->sor.value(); // [[unsafe]]
3886+ else
3887+ foo->sor.value();
3888+ }
3889+ )cc" );
3890+
3891+ ExpectDiagnosticsFor (
3892+ R"cc(
3893+ #include "unchecked_statusor_access_test_defs.h"
3894+
3895+ struct Foo {
3896+ absl::StatusOr<std::string> sor;
3897+ };
3898+
3899+ void target(absl::StatusOr<Foo>& foo, bool b) {
3900+ if (!foo.ok()) return;
3901+ if (b) {
3902+ if (!foo->sor.ok()) return;
3903+ foo->sor.value();
3904+ } else {
3905+ if (!foo->sor.ok()) return;
3906+ foo->sor.value();
3907+ }
3908+ foo->sor.value();
3909+ }
3910+ )cc" );
3911+ }
3912+
37423913} // namespace
37433914
37443915std::string
0 commit comments