Main Content

MISRA C:2023 Rule 23.4

A generic association shall list an appropriate type

Since R2024a

Description

Rule Definition

A generic association shall list an appropriate type.

Rationale

The controlling expression of a generic selection undergoes lvalue conversion before its type is compared to the type names in the association list. This lvalue conversion:

  • Removes top-level qualifications such as const, volatile, or atomic

  • Converts functions and arrays to pointers

If your association list contains qualified types, arrays, or function types, then the controlling expression cannot match the association list. Consider this code:

typedef const uint32_t const_int;

#define get_type_id_of(X) _Generic((X), const_int : 0, int : 1)

const_int x = 7;
get_type_id_of(x);
The macro get_type_id_of(x) evaluates to 1 because after lvalue conversion, the type of x matches with int. To avoid this behavior, use appropriate types in the association list.

Using an unnamed struct or union in the association list violates this rule because every unnamed struct or union is a distinct type. An unnamed struct in the controlling expression does not match with an unnamed struct in the association list. Rather, the unnamed struct in the controlling expression matches the default association.

Polyspace Implementation

The rule checker reports a violation if the association list for a generic selection contains any of these:

  • A const qualified type

  • A volatile qualified type

  • An atomic type

  • An array or function type

  • An unnamed type

Troubleshooting

If you expect a rule violation but do not see it, refer to Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

In this example, the association lists of the generic selection statements use inappropriate types such as qualified types or arrays. The rule checker reports violations.

#include <stdint.h>
#include <stdbool.h>

/*
 * Array type is not allowed in type selection
 */
typedef uint8_t a_byte_array[256];
#define is_a_byte_array(X) _Generic((X), a_byte_array : true, default : false) /*Noncompliant*/
void non_compliant_with_arrays() {
	a_byte_array some_bytes;
	(void) is_a_byte_array(some_bytes);
}


/*
 * Function type is not allowed in type selection
 */
typedef void a_function(void);
extern void f(void);

/*
 * Qualified types are non-compliant in type selection
 */
typedef const uint32_t const_int;
typedef volatile uint32_t volatile_int;
typedef const volatile uint32_t const_volatile_int;
typedef _Atomic uint32_t atomic_int;

#define is_const_type(X) _Generic((X), const_int : true, default: false)       /*Noncompliant*/
#define is_volatile_type(X) _Generic((X), volatile_int : true, default: false) /*Noncompliant*/
#define is_atomic_type(X) _Generic((X), atomic_int : true, default : false)    /*Noncompliant*/


void non_compliant_with_qualifiers() {
	const_int x = 7;
	(void) is_const_type(x);
	(void) is_volatile_type(x);
	(void) is_atomic_type(x);

}

Check Information

Group: Generic Selections
Category: Required
AGC Category: Required

Version History

Introduced in R2024a