@@ -543,6 +543,42 @@ Do not attempt to create a std::string from a null pointer
543543 }
544544 }
545545
546+ .. _cplusplus-PureVirtualCall :
547+
548+ cplusplus.PureVirtualCall (C++)
549+ """""""""""""""""""""""""""""""
550+
551+ When `virtual methods are called during construction and destruction
552+ <https://en.cppreference.com/w/cpp/language/virtual#During_construction_and_destruction> `__
553+ the polymorphism is restricted to the class that's being constructed or
554+ destructed because the more derived contexts are either not yet initialized or
555+ already destructed.
556+
557+ This checker reports situations where this restricted polymorphism causes a
558+ call to a pure virtual method, which is undefined behavior. (See also the
559+ related checker :ref: `optin-cplusplus-VirtualCall ` which reports situations
560+ where the restricted polymorphism affects a call and the called method is not
561+ pure virtual – but may be still surprising for the programmer.)
562+
563+ .. code-block :: cpp
564+
565+ struct A {
566+ virtual int getKind() = 0;
567+
568+ A() {
569+ // warn: This calls the pure virtual method A::getKind().
570+ log << "Constructing " << getKind();
571+ }
572+ virtual ~A() {
573+ releaseResources();
574+ }
575+ void releaseResources() {
576+ // warn: This can call the pure virtual method A::getKind() when this is
577+ // called from the destructor.
578+ callSomeFunction(getKind())
579+ }
580+ };
581+
546582 .. _deadcode-checkers :
547583
548584deadcode
@@ -833,24 +869,40 @@ This checker has several options which can be set from command line (e.g.
833869
834870optin.cplusplus .VirtualCall (C++)
835871"""""""""""""""""""""""""""""""""
836- Check virtual function calls during construction or destruction.
872+
873+ When `virtual methods are called during construction and destruction
874+ <https://en.cppreference.com/w/cpp/language/virtual#During_construction_and_destruction> `__
875+ the polymorphism is restricted to the class that's being constructed or
876+ destructed because the more derived contexts are either not yet initialized or
877+ already destructed.
878+
879+ Although this behavior is well-defined, it can surprise the programmer and
880+ cause unintended behavior, so this checker reports calls that appear to be
881+ virtual calls but can be affected by this restricted polymorphism.
882+
883+ Note that situations where this restricted polymorphism causes a call to a pure
884+ virtual method (which is definitely invalid, triggers undefined behavior) are
885+ **reported by another checker: ** :ref: `cplusplus-PureVirtualCall ` and **this
886+ checker does not report them **.
837887
838888.. code-block :: cpp
839889
840- class A {
841- public:
890+ struct A {
891+ virtual int getKind();
892+
842893 A() {
843- f(); // warn
894+ // warn: This calls A::getKind() even if we are constructing an instance
895+ // of a different class that is derived from A.
896+ log << "Constructing " << getKind();
844897 }
845- virtual void f();
846- } ;
847-
848- class A {
849- public:
850- ~A() {
851- this->f(); // warn
898+ virtual ~A() {
899+ releaseResources() ;
900+ }
901+ void releaseResources() {
902+ // warn: This can be called within ~A() and calls A::getKind() even if
903+ // we are destructing a class that is derived from A.
904+ callSomeFunction(getKind())
852905 }
853- virtual void f();
854906 };
855907
856908 .. _optin-mpi-MPI-Checker :
0 commit comments