drgn/libdrgn/minmax.h
Omar Sandoval edf8845fcc libdrgn: get rid of compatible type requirement for {min,max}_iconst()
This has gotten in the way more than it has helped. I'll probably do the
same to min() and max() the next time they annoy me.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2023-08-16 14:12:11 -07:00

66 lines
1.7 KiB
C

// Copyright (c) Meta Platforms, Inc. and affiliates.
// SPDX-License-Identifier: LGPL-2.1-or-later
/**
* @file
*
* Minimum/maximum operations.
*
* See @ref MinMaxOperations.
*/
#ifndef DRGN_MINMAX_H
#define DRGN_MINMAX_H
#include "pp.h"
/**
* @ingroup Internals
*
* @defgroup MinMaxOperations Minimum/maximum operations
*
* Generic minimum/maximum operations.
*
* @{
*/
/** Get the minimum of two expressions with compatible types. */
#define min(x, y) cmp_once_impl(x, y, PP_UNIQUE(_x), PP_UNIQUE(_y), <)
/** Get the maximum of two expressions with compatible types. */
#define max(x, y) cmp_once_impl(x, y, PP_UNIQUE(_x), PP_UNIQUE(_y), >)
/** @cond */
#define cmp_once_impl(x, y, unique_x, unique_y, op) ({ \
__auto_type unique_x = (x); \
__auto_type unique_y = (y); \
/* Generate a warning if x and y do not have compatible types. */ \
(void)(&unique_x == &unique_y); \
unique_x op unique_y ? unique_x : unique_y; \
})
/** @endcond */
/**
* Get the minimum of two integer constant expressions, resulting in an integer
* constant expression.
*/
#define min_iconst(x, y) cmp_iconst_impl(x, y, <)
/**
* Get the maximum of two integer constant expressions, resulting in an integer
* constant expression.
*/
#define max_iconst(x, y) cmp_iconst_impl(x, y, >)
/** @cond */
#define cmp_iconst_impl(x, y, op) \
/* \
* Enforce that the arguments are integer constant expressions. The \
* size of a non-VLA array must be an integer constant expression, and \
* a compound literal cannot be a VLA. Evaluates to non-zero to fall \
* through to the comparison. \
*/ \
(sizeof((char [(x) * 0 + (y) * 0 + 1]){0}) && \
(x) op (y) ? (x) : (y))
/** @endcond */
/** @} */
#endif /* DRGN_MINMAX_H */