This rule is part of MISRA C++:2023.
Usage of this content is governed by Sonar’s terms and conditions. Redistribution is
prohibited.
Rule 8.2.4 - Casts shall not be performed between a pointer to function and any other type
[expr.reinterpret.cast] Unspecified 6
Category: Required
Analysis: Decidable,Single Translation Unit
Amplification
For the purposes of this rule, a pointer to a member is considered to be a pointer to function.
The following standard conversions are permitted by this rule, even if they are the result of a cast:
- Function-to-pointer conversions (implicitly taking the address of a function); and
- Function pointer conversions (from a pointer to noexcept function to pointer to function); and
- Null pointer conversions (from
nullptr to a pointer to function); and
- User-defined conversions, including converting from a lambda with no capture to a pointer to function.
Note: the cast notation that is used to disambiguate an overloaded function name ([over.over]) is compliant with this rule because
the target type is a function type that is compatible with the source type.
Rationale
Converting a pointer to function into or from any of the following may result in undefined behaviour:
- Pointer to object;
- Pointer to non-static data member;
- Pointer to an object of incomplete type;
-
void *.
Calling a function by means of a pointer whose type is not compatible with the called function also results in undefined behaviour.
Casts that are equivalent to a standard conversion cannot lead to those problems and are therefore permitted.
Note: this rule also applies to pointer to member objects as they are callable and can be used with
std::invoke.
Exception
A cast to void may be used to signify that a function pointer returned by a function call is being intentionally discarded (see
M23_007: MISRA C++ 2023 Rule 0.1.2).
Example
using pf16_t = void (*)( int16_t n );
using pf32_t = void (*)( int32_t n );
pf16_t getPf16();
pf16_t p1 = static_cast< pf16_t >( nullptr ); // Compliant - cast is equivalent
// to a standard conversion
pf32_t p2 = reinterpret_cast< pf32_t >( p1 ); // Non-compliant - function pointer
// types are different
( void ) getPf16(); // Compliant by exception
if ( p1 ) // Rule does not apply - no cast;
{ // contextually converted to bool
}
pf16_t p3 = ( pf16_t ) 0x8000; // Non-compliant
pf16_t p4 = reinterpret_cast< pf16_t >( 0xdeadbeef ); // Non-compliant
int16_t * p5 = reinterpret_cast< int16_t * >( p4 ); // Non-compliant
void f5();
void f5( int16_t );
template< typename T >
void f6( T );
void f7()
{
f6( static_cast< void (*)() >( f5 ) ); // Compliant - overload selection
}
struct A { void foo(); int32_t i; };
struct B : A { };
auto pm1 = static_cast< void ( B::* )() >( &A::foo ); // Non-compliant
auto pm2 = static_cast< int32_t ( B::* ) >( &A::i ); // Non-compliant
Copyright The MISRA Consortium Limited © 2023