Menu

False positive operatorEqVarError suppressed by initializer

CHR
2020-09-25
2020-10-05
  • CHR

    CHR - 2020-09-25

    In the code below, we get correct warnings about Base::noCopyBase and Derived2::noCopy2, and a false positive about Derived2::d2. All three warnings can be suppressed by adding in-class member initializers.
    At last, there is a false negative concerning Derived::noCopy. I could understand if cppcheck cannot see a copy operation hidden in a class hierarchy like that, but why does it then emit warnings about Derived2?

    class Base {
    public:
        Base() : noCopyBase(0) {}
        int b{};
        int noCopyBase; // add initializer {} to suppress warning
        void Copy(const Base& Src) {
            CopyBase(Src);
            CopyImpl(Src);
        }
    protected:  
        void CopyBase(const Base& Src) {
            b = Src.b;
        }
        virtual void CopyImpl(const Base& Src) = 0;
        Base& operator=(const Base& Src) {
            if (this != &Src)
                CopyBase(Src);
            return *this;
        }
    };
    
    class Derived : public Base {
    public:
        explicit Derived(int i) : d(i), noCopy(0) {}
        int d{};
        int noCopy; // no warning (false negative)
        Derived& operator=(const Derived& Src) {
            if (this != &Src)
                Copy(Src);
            return *this;
        }
    protected:  
        void CopyImpl(const Base& Src) override {
            const auto& DSrc = dynamic_cast<const Derived&>(Src);
            d = DSrc.d;
        }
    };
    
    class Derived2 : public Derived {
    public:
        explicit Derived2(int i) : Derived(0), d2(i), noCopy2(0) {}
        int d2; // add initializer {} to suppress false positive
        int noCopy2; // add initializer {} to suppress warning
        Derived2& operator=(const Derived2& Src) {
            if (this != &Src)
                Copy(Src);
            return *this;
        }
    protected:  
        void CopyImpl(const Base& Src) override {
            const auto& D2Src = dynamic_cast<const Derived2&>(Src);
            d2 = D2Src.d2;
        }
    };
    
    int main() {
        Derived d(0), copy(0);
        d.b = 1;
        copy = d;
        Derived2 d2(0), copy2(0);
        d2.b = 1;
        d2.d = 2;
        d2.d2 = 3;
        copy2 = d2;
        return copy.b == 1 && copy2.b == 1 ? 0 : 1; 
    }
    
     
  • CHR

    CHR - 2020-10-05

    bump
    This has actually been extracted from real-world code...

     
  • Daniel Marjamäki

    hmm.. is it possible to reduce it. A minimal example that writes a FP.

     
  • CHR

    CHR - 2020-10-05

    I think the hierarchy Base->Derived->Derived2 is needed for the FP.
    However, the legitimate warnings about noCopyBase and noCopy2 can still be suppressed by adding initializers in v2.2. This could be a different issue, though.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.