GeneralPurpose-BaseClassDestructor

Destructor of a polymorphic class shall be virtual or protected non-virtual

Required inputs: IR

This rule checks base classes that have existing delete operations through pointers to base:

class Base { // Violation: Destructor of a base class with existing delete operations through pointers-to-base shall be virtual.
public:
    int a;
};
class Derived : public Base {
public:
    std::string b;
};

void delete_base(Base* ptr) {
    delete ptr; // Undefined behavior if ptr points to a Derived object, because Base's destructor is not virtual.
    // Violation: Delete operations through pointer-to-base should only be used with classes that have virtual destructors.
}

This rule does not keep track of pointer targets; it merely checks whether a class used with delete operations has derived classes and a non-virtual destructor. It also recognizes delete operations happening within the std::unique_ptr implementation.

Additionally, this rule reports violations for polymorphic base classes, even if the class is currently not used with delete operations:

class PolymorphicBase {
    // Violation: Destructor of a polymorphic base class shall be virtual or protected non-virtual.
public:
    virtual void foo() {}
};
class PolymorphicDerived : public PolymorphicBase {};
The destructor of PolymorphicBase should be declared as virtual or protected to make the class safe for use. These extra messages for polymorphic classes can be disabled via option msg.polymorphic_class_destructor.disabled.

See also: AutosarC++19_03-A12.4.1, a stricter version of this rule.

Possible Messages

Key

Text

Severity

Disabled

base_class_destructor

Destructor of a base class with existing delete operations through pointers-to-base shall be virtual.

None

False

delete_through_pointer_to_base

Delete operations through pointer-to-base should only be used with classes that have virtual destructors.

None

False

polymorphic_class_destructor

Destructor of a polymorphic base class shall be virtual or protected non-virtual.

None

False

Options

allowed_inheriting_classes

allowed_inheriting_classes

Type: set[bauhaus.analysis.config.QualifiedName]

Default: {'std::_Compressed_pair', 'std::__compressed_pair_elem', 'std::__detail::_Hashtable_ebo_helper', 'std::__libcpp_compressed_pair_imp', 'std::__map_value_compare', 'std::__unordered_map_hasher'}

A set of full qualified type names that are ignored when determining whether a class is a base class or not. This is mainly a workaround for some libc++ implementation details: The standard library uses private inheritance from empty base classes to implement EBO (Empty Base Optimization) for some of its data structures.