1*66c7723aSAndrew Jeffery /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ 2*66c7723aSAndrew Jeffery #ifndef PLDM_COMPILER_H 3*66c7723aSAndrew Jeffery #define PLDM_COMPILER_H 4*66c7723aSAndrew Jeffery 5*66c7723aSAndrew Jeffery // NOLINTBEGIN(bugprone-macro-parentheses) 6*66c7723aSAndrew Jeffery /** 7*66c7723aSAndrew Jeffery * Require that the given object is of the specified type. 8*66c7723aSAndrew Jeffery * 9*66c7723aSAndrew Jeffery * If the object is not of the required type then a diagnostic will be emitted. 10*66c7723aSAndrew Jeffery * 11*66c7723aSAndrew Jeffery * If you are reading this documentation due to hitting a compilation error 12*66c7723aSAndrew Jeffery * passing through the macro, then you have a type error in your code that must 13*66c7723aSAndrew Jeffery * be fixed. Despite the compiler output, the error is _not_ that some array 14*66c7723aSAndrew Jeffery * is negatively sized, the array is negatively sized _because_ you have a type 15*66c7723aSAndrew Jeffery * error. 16*66c7723aSAndrew Jeffery * 17*66c7723aSAndrew Jeffery * How this works: 18*66c7723aSAndrew Jeffery * 19*66c7723aSAndrew Jeffery * If the type of @p obj is not equivalent to the provided type @p type then 20*66c7723aSAndrew Jeffery * we force the compiler to evaluate sizeof on a negatively-sized array. The 21*66c7723aSAndrew Jeffery * C standard requires that the integer constant expression that specifies 22*66c7723aSAndrew Jeffery * the array length must be greater than zero. Failure to meet this constraint 23*66c7723aSAndrew Jeffery * generally terminates compilation of the translation unit as any other result 24*66c7723aSAndrew Jeffery * cannot be handled in a sensible way. The array size is derived to an integer 25*66c7723aSAndrew Jeffery * constant expression from a type eqivalence evaluated using _Generic() 26*66c7723aSAndrew Jeffery * allowing us to stay within the language standard. The default generic 27*66c7723aSAndrew Jeffery * association, representing a type mismatch, yields -1. 28*66c7723aSAndrew Jeffery * 29*66c7723aSAndrew Jeffery * pldm_require_obj_type() was introduced into the libpldm implementation to 30*66c7723aSAndrew Jeffery * enable use of the pldm_msgbuf_extract*() APIs for objects that may or may not 31*66c7723aSAndrew Jeffery * reside in a packed struct. See src/msgbuf.h for more details. 32*66c7723aSAndrew Jeffery * 33*66c7723aSAndrew Jeffery * @param obj The name of the object to evaluate 34*66c7723aSAndrew Jeffery * @param type The required type of @p obj 35*66c7723aSAndrew Jeffery * 36*66c7723aSAndrew Jeffery * @return The expression either yields 1, or compilation is terminated 37*66c7723aSAndrew Jeffery */ 38*66c7723aSAndrew Jeffery #define pldm_require_obj_type(obj, type) \ 39*66c7723aSAndrew Jeffery ((void)(sizeof( \ 40*66c7723aSAndrew Jeffery struct { char buf[_Generic((obj), type: 1, default: -1)]; }))) 41*66c7723aSAndrew Jeffery // NOLINTEND(bugprone-macro-parentheses) 42*66c7723aSAndrew Jeffery 43*66c7723aSAndrew Jeffery #endif 44