Main Content

AUTOSAR C++14 Rule A5-5-1

A pointer to member shall not access non-existent class members

Since R2022a

Description

Rule Definition

A pointer to member shall not access non-existent class members.

Rationale

You use pointer-to-member operators .* and ->* to refer to a non-static class member of the first operand object. For instance, in this code snippet, the call (obj.*ptrToMember)(); is equivalent to obj.f();. Both calls refer to member function f() of class myObj:

class myObj {
  public:
    void f();
};

void func() {
    myObj obj;
    void (myObj::*ptrToMember)() = &myObj::f;

    (obj.*ptrToMember)(); // Equivalent to obj.f();
}
The use of pointer-to-member operators results in undefined behavior in these cases:

  • The dynamic type of the first operand does not contain the member referred to by the second operand.

  • The second operand pointer is null.

Polyspace Implementation

Polyspace® flags the use of pointer-to-member operators in these instances:

  • You cast a pointer-to-member type to another pointer-to-member type which does not contain the class member pointed to. For instance, in this code snippet, pointer-to-member ptrToMember is obtained from myObj::f but is then upcast to baseObj::* which does not contain a method f.

    class baseObj {
      public:
        virtual ~baseObj() = default;
    };
    
    class myObj : public baseObj {
      public:
        void f();
    };
    
    
    void func() {
        baseObj* foo = new baseObj();
        void (baseObj::*ptrToMember)() =
            static_cast<void (baseObj::*)()>(&myObj::f); //Noncompliant
        (foo->*ptrToMember)();
    }
    
    Polyspace does not flag the casting operation if the type being cast to inherits from the other type. For example, in the preceding code, if baseObj inherits from myObj.

  • The second operand of the pointer-to-member operator is a null pointer. For instance, in this code snippet, ptrToMember is declared but not initialized and defaults to a null pointer.

    class baseObj {
      public:
        virtual ~baseObj() = default;
    };
    static void (baseObj::*ptrToMember)(); //Not initialized 
    
    void func() {
        baseObj* foo = new baseObj();
    
        (foo->*ptrToMember)(); //Noncompliant
    }
    

Troubleshooting

If you expect a rule violation but Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

class Base {
  public:
    void f() {
    }
};

class Derived : public Base {
  public:
    int myVar;
};

void func() {
    Base myObj;
    auto ptrToMethod =
        static_cast<void (Base::*)()>(&Derived::f); // Compliant
    auto ptrToMember =
        static_cast<int(Base::*)>(&Derived::myVar); // Noncompliant

    (myObj.*ptrToMethod)(); // OK, equivalent to myObj.f()
    myObj.*ptrToMember;     // Undefined behavior
}

In this example, Polyspace flags the casting of ptrToMember, which is obtained from Derived::myVar, to Base::* because this class does not contain a member myVar. If you execute the code, the call myObj.*ptrToMember; results in undefined behavior.

Polyspace does not flag the casting of ptrToMethod to Base::* because class Derived inherits method f from Base.

Check Information

Group: Expressions
Category: Required, Automated

Version History

Introduced in R2022a