0

The following class hierarchy will cause a [-Wvirtual-move-assign] warning in GCC if a move assign is invoked for an instance of B.

struct A {

    std::vector<int> v;

};

struct B : public virtual A {};

The following scenarios indeed cause the warning to occur

/*** SCENARIO 1 ***/
class C {

    B a;

    public:
        void foo(B& b) {

            b = a; // warning
            // or
            a = b; // warning

        }

};

/*** SCENARIO 2 ***/
void foo(const B& a, B& b) {

    b = a; // warning

}


int main() {

    /*** SCENARIO 3 ***/
    B b;
    std::vector<B> v1;
    v1.push_back(b); // warning

    /*** SCENARIO 4 ***/
    B b1;
    B b2;
    b1 = b2; // warning

    /*** SCENARIO 5 ***/
    B b3;
    b3 = B(); // warning

}

The warnings still occur even if the assigned from object is used again later. With the exception of Scenario 5 which involves an rvalue on the right side and therefore would involve a move assignment, I would expect (and indeed I want) a copy assignment to occur rather than a move assignment in these scenarios. If that is the case, then why is this warning occurring? Is a move assignment actually happening somewhere in the expressions?

Adam Sperry
  • 143
  • 8

1 Answers1

1

It looks like you hit a false positive. The answer to Why does gcc warn about calling a non-trivial move assignment operator with std::tuple and virtual inheritance? suggests that gcc emits this warning more often than is really necessary, and that clang does not. So I beefed up your example (as was done in that answer) and gave it to clang.

struct A {
    std::vector<int> v;
};

struct AA : public virtual A {};
struct AB : public virtual A {};

struct B : public AA, AB {};

With this setup, clang warns only for the b3 = B(); line (scenario 5). It accepts the other scenarios, suggesting that gcc is just being paranoid. (Either gcc is issuing a false positive or clang has a bug. Your analysis appears correct, though, so probably the former.)

JaMiT
  • 9,693
  • 2
  • 12
  • 26