Skip to content

Commit 9762b8e

Browse files
authored
[NFC][analyzer] Document the VirtualCall checkers (#131861)
This commit documents `cplusplus.PureVirtualCall` (which was previously completely undocumented) and improves the documentation of `optin.cplusplus.VirtualCall` (which was very barebones). Note that in this documentation I do not mention the checker options of `optin.cplusplus.VirtualCall`, because `ShowFixIts` is apparently in an unfinished alpha state (since 2019 when it was added by commit 6cee434) and `PureOnly` is a deprecated option that I'm going to remove very soon.
1 parent 434ac46 commit 9762b8e

File tree

1 file changed

+64
-12
lines changed

1 file changed

+64
-12
lines changed

clang/docs/analyzer/checkers.rst

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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 void 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
548584
deadcode
@@ -833,24 +869,40 @@ This checker has several options which can be set from command line (e.g.
833869
834870
optin.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 void 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

Comments
 (0)