@@ -43,6 +43,13 @@ class TestUninitVar : public TestFixture {
4343 TEST_CASE (uninitvar_alloc); // data is allocated but not initialized
4444 TEST_CASE (uninitvar_arrays); // arrays
4545 TEST_CASE (uninitvar_class); // class/struct
46+ TEST_CASE (uninitvar_ownedArrow);
47+ TEST_CASE (uninitvar_ownedArrowEscapes);
48+ TEST_CASE (valueFlowUninit_ownedArrow);
49+ TEST_CASE (valueFlowUninit_ownedArrowWrites);
50+ TEST_CASE (valueFlowUninit_ownedArrowReadModify);
51+ TEST_CASE (valueFlowUninit_ownedArrowReceivers);
52+ TEST_CASE (valueFlowUninit_ownedArrowConditional);
4653 TEST_CASE (uninitvar_enum); // enum variables
4754 TEST_CASE (uninitvar_if); // handling if
4855 TEST_CASE (uninitvar_loops); // handling for/while
@@ -3677,6 +3684,172 @@ class TestUninitVar : public TestFixture {
36773684 (checkuninitvar.valueFlowUninit )();
36783685 }
36793686
3687+ void uninitvar_ownedArrow () { // #6572
3688+ checkUninitVar (" struct CCommitPointer { int m_place; };\n "
3689+ " struct iterator {\n "
3690+ " CCommitPointer m_ptr;\n "
3691+ " CCommitPointer& operator*() { return m_ptr; }\n "
3692+ " CCommitPointer* operator->() { return &m_ptr; }\n "
3693+ " iterator& operator++() { ++m_ptr.m_place; return *this; }\n "
3694+ " };\n "
3695+ " iterator begin() {\n "
3696+ " iterator it;\n "
3697+ " it->m_place = 0;\n "
3698+ " return it;\n "
3699+ " }\n " );
3700+ ASSERT_EQUALS (" " , errout_str ());
3701+ }
3702+
3703+ void uninitvar_ownedArrowEscapes () {
3704+ checkUninitVar (" struct Item { int value; };\n "
3705+ " struct Cursor { Item item; Item* operator->() { return &item; } };\n "
3706+ " Cursor f(bool b) {\n "
3707+ " Cursor it;\n "
3708+ " b && (it->value = 1);\n "
3709+ " return it;\n "
3710+ " }\n " );
3711+ ASSERT_EQUALS (" [test.cpp:6:12]: (error) Uninitialized struct member: it.item [uninitStructMember]\n " , errout_str ());
3712+
3713+ checkUninitVar (" struct Item { int value; };\n "
3714+ " struct Cursor { Item item; Item* operator->() { return &item; } };\n "
3715+ " Cursor f() {\n "
3716+ " Cursor it;\n "
3717+ " (void)noexcept(it->value = 1);\n "
3718+ " return it;\n "
3719+ " }\n " );
3720+ ASSERT_EQUALS (" [test.cpp:6:12]: (error) Uninitialized struct member: it.item [uninitStructMember]\n " , errout_str ());
3721+
3722+ checkUninitVar (" struct Item { int value; };\n "
3723+ " struct Cursor { Item item; Item* operator->() { return &item; } };\n "
3724+ " Cursor f() {\n "
3725+ " Cursor it;\n "
3726+ " int& r = it->value;\n "
3727+ " ++r;\n "
3728+ " return it;\n "
3729+ " }\n " );
3730+ ASSERT_EQUALS (" [test.cpp:7:12]: (error) Uninitialized struct member: it.item [uninitStructMember]\n " , errout_str ());
3731+
3732+
3733+ }
3734+
3735+ void valueFlowUninit_ownedArrow () { // #6572
3736+ valueFlowUninit (" struct CCommitPointer { int m_place; };\n "
3737+ " struct iterator {\n "
3738+ " CCommitPointer m_ptr;\n "
3739+ " CCommitPointer& operator*() { return m_ptr; }\n "
3740+ " CCommitPointer* operator->() { return &m_ptr; }\n "
3741+ " iterator& operator++() { ++m_ptr.m_place; return *this; }\n "
3742+ " };\n "
3743+ " iterator begin() {\n "
3744+ " iterator it;\n "
3745+ " it->m_place = 0;\n "
3746+ " return it;\n "
3747+ " }\n " );
3748+ ASSERT_EQUALS (" " , errout_str ());
3749+ }
3750+
3751+ void valueFlowUninit_ownedArrowWrites () {
3752+ valueFlowUninit (" struct Item { int value; };\n "
3753+ " struct Cursor { Item item; Item* operator->() { return &this->item; }\n "
3754+ " const Item* operator->() const { return &item; } };\n "
3755+ " int f(bool b) {\n "
3756+ " Cursor it;\n "
3757+ " if (b) it->value = 1; else it->value = 2;\n "
3758+ " it->value += 1;\n "
3759+ " return it->value;\n "
3760+ " }\n " );
3761+ ASSERT_EQUALS (" " , errout_str ());
3762+ }
3763+
3764+ void valueFlowUninit_ownedArrowReadModify () {
3765+ valueFlowUninit (" struct Item { int value; };\n "
3766+ " struct Cursor { Item item; Item* operator->() { return &item; } };\n "
3767+ " Cursor f() {\n "
3768+ " Cursor it;\n "
3769+ " it->value++;\n "
3770+ " return it;\n "
3771+ " }\n " );
3772+ ASSERT_EQUALS (" [test.cpp:5:5]: (error) Uninitialized variable: it [uninitvar]\n " , errout_str ());
3773+
3774+ valueFlowUninit (" struct Item { int value; };\n "
3775+ " struct Cursor { Item item; Item* operator->() { return &item; } };\n "
3776+ " Cursor f() {\n "
3777+ " Cursor it;\n "
3778+ " --it->value;\n "
3779+ " return it;\n "
3780+ " }\n " );
3781+ ASSERT_EQUALS (" [test.cpp:5:7]: (error) Uninitialized variable: it [uninitvar]\n " , errout_str ());
3782+
3783+ valueFlowUninit (" struct Item { int value; };\n "
3784+ " struct Cursor { Item item; Item* operator->() { return &item; } };\n "
3785+ " Cursor f() {\n "
3786+ " Cursor it;\n "
3787+ " it->value += 1;\n "
3788+ " return it;\n "
3789+ " }\n " );
3790+ ASSERT_EQUALS (" [test.cpp:5:5]: (error) Uninitialized variable: it [uninitvar]\n " , errout_str ());
3791+ }
3792+
3793+ void valueFlowUninit_ownedArrowReceivers () {
3794+ valueFlowUninit (" struct Item { int value; };\n "
3795+ " struct Cursor { Item item; Item* operator->() { return &item; } };\n "
3796+ " Cursor f() {\n "
3797+ " Cursor it;\n "
3798+ " it->value = it->value + 1;\n "
3799+ " return it;\n "
3800+ " }\n " );
3801+ ASSERT_EQUALS (" [test.cpp:5:17]: (error) Uninitialized variable: it [uninitvar]\n " , errout_str ());
3802+
3803+ valueFlowUninit (" struct Item { int value; };\n "
3804+ " struct Cursor { Item item; Item* operator->() { return &item; } };\n "
3805+ " Cursor f() {\n "
3806+ " Cursor first, second;\n "
3807+ " first->value = second->value;\n "
3808+ " return first;\n "
3809+ " }\n " );
3810+ ASSERT_EQUALS (" [test.cpp:5:20]: (error) Uninitialized variable: second [uninitvar]\n " , errout_str ());
3811+
3812+ valueFlowUninit (" struct Item { int value; };\n "
3813+ " struct Cursor { Item item; Item* operator->() { return &item; } };\n "
3814+ " Cursor f() {\n "
3815+ " Cursor first, second;\n "
3816+ " first->value = 1;\n "
3817+ " second->value = first->value;\n "
3818+ " return second;\n "
3819+ " }\n " );
3820+ ASSERT_EQUALS (" " , errout_str ());
3821+ }
3822+
3823+ void valueFlowUninit_ownedArrowConditional () {
3824+ valueFlowUninit (" struct Item { int value; };\n "
3825+ " struct Cursor { Item item; Item* operator->() { return &item; } };\n "
3826+ " Cursor f(bool b) {\n "
3827+ " Cursor it;\n "
3828+ " if (b) it->value = 1;\n "
3829+ " return it;\n "
3830+ " }\n " );
3831+ ASSERT_EQUALS (" [test.cpp:5:9] -> [test.cpp:6:12]: (warning) Uninitialized variable: it.item [uninitvar]\n " , errout_str ());
3832+
3833+ valueFlowUninit (" struct Item { int value; };\n "
3834+ " struct Cursor { Item item; Item* operator->() { return &item; } };\n "
3835+ " Cursor f() {\n "
3836+ " Cursor it;\n "
3837+ " auto l = [&it] { it->value = 1; };\n "
3838+ " return it;\n "
3839+ " }\n " );
3840+ ASSERT_EQUALS (" [test.cpp:6:12]: (error) Uninitialized variable: it [uninitvar]\n " , errout_str ());
3841+
3842+ // Reference writes are not projected into the owning object.
3843+ valueFlowUninit (" struct Item { int value; };\n "
3844+ " struct Cursor { Item item; Item* operator->() { return &item; } };\n "
3845+ " void f() {\n "
3846+ " Cursor it;\n "
3847+ " int& r = it->value;\n "
3848+ " ++r;\n "
3849+ " }\n " );
3850+ ASSERT_EQUALS (" [test.cpp:5:14]: (error) Uninitialized variable: it [uninitvar]\n " , errout_str ());
3851+ }
3852+
36803853 void uninitvar15 () { // #13685
36813854 const char code[] = " int f() {\n "
36823855 " int x;\n "
0 commit comments