llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
26.67k stars 10.92k forks source link

[clang-analyzer] False report about virtual method during construction #47826

Open dmpolukhin opened 3 years ago

dmpolukhin commented 3 years ago
Bugzilla Link 48482
Version trunk
OS All
CC @steakhal,@devincoughlin,@Szelethus,@haoNoQ,@Xazax-hun

Extended Description

Minimal reproducer:

// clang++ --analyze -Xanalyzer -analyzer-output=text -Xanalyzer -analyzer-checker='optin.cplusplus'

class Attribute { public: virtual ~Attribute() = default; virtual int encode() const = 0;

protected: Attribute() {} };

class Number : public Attribute { public: explicit Number() : Attribute() {}

int encode() const override;

private: int number_; };

void foo() { Number number; number.encode(); }

Output: test.cpp:23:3: warning: Call to virtual method 'Number::encode' during construction bypasses virtual dispatch number.encode(); ^~~~~~ test.cpp:23:3: note: Call to virtual method 'Number::encode' during construction bypasses virtual dispatch number.encode(); ^~~~~~ 1 warning generated.

To trigger this bug it is required to have uninitialised in c-tor member number_. In full example the member was initialised later with member function call before calling the virtual function. Problem exists starting from at least clang 9 up to current trunk.

haoNoQ commented 2 years ago

mentioned in issue llvm/llvm-bugzilla-archive#48633

haoNoQ commented 3 years ago

In llvm/llvm-bugzilla-archive#48633 there are a couple more examples of false positives in other checkers with the same root cause.

haoNoQ commented 3 years ago

Bug llvm/llvm-bugzilla-archive#48633 has been marked as a duplicate of this bug.

haoNoQ commented 3 years ago

Uh-oh, yeah, this is clearly broken.

This false positive is caused by presence of a seemingly unrelated checker in your run-line, namely optin.cplusplus.UninitializedObject. If you explicitly disable this checker the false positive goes away.

Looks like one of the two checkers performs transitions incorrectly which causes a sudden state split near the exit from Number::Number.

Thanks for the bug report, I'll investigate further.

dmpolukhin commented 3 years ago

assigned to @haoNoQ