1e33857c1e3afa0a879512378df55694ca3900bc
[pspp] / src / libpspp / cast.h
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2009 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifndef LIBPSPP_CAST_H
18 #define LIBPSPP_CAST_H 1
19
20 #include <stddef.h>
21
22 /* Expands to a void expression that checks that POINTER is an
23    expression whose type is a qualified or unqualified version of
24    a type compatible with TYPE (a pointer type) and, if not,
25    causes a compiler warning to be issued (on typical compilers).
26
27    Examples:
28
29    int *ip;
30    const int *cip;
31    const int **cipp;
32    int ***ippp;
33    double *dp;
34
35    // None of these causes a warning:
36    CHECK_POINTER_HAS_TYPE (ip, int *);
37    CHECK_POINTER_HAS_TYPE (ip, const int *);
38    CHECK_POINTER_HAS_TYPE (cip, int *);
39    CHECK_POINTER_HAS_TYPE (cip, const int *);
40    CHECK_POINTER_HAS_TYPE (dp, double *);
41    CHECK_POINTER_HAS_TYPE (dp, const double *);
42    CHECK_POINTER_HAS_TYPE (cipp, const int **);
43    CHECK_POINTER_HAS_TYPE (cipp, const int *const *);
44    CHECK_POINTER_HAS_TYPE (ippp, int ***);
45    CHECK_POINTER_HAS_TYPE (ippp, int **const *);
46
47    // None of these causes a warning either, although it is unusual to
48    // const-qualify a pointer like this (it's like declaring a "const int",
49    // for example).
50    CHECK_POINTER_HAS_TYPE (ip, int *const);
51    CHECK_POINTER_HAS_TYPE (ip, const int *const);
52    CHECK_POINTER_HAS_TYPE (cip, int *const);
53    CHECK_POINTER_HAS_TYPE (cip, const int *const);
54    CHECK_POINTER_HAS_TYPE (cipp, const int **const);
55    CHECK_POINTER_HAS_TYPE (cipp, const int *const *const);
56    CHECK_POINTER_HAS_TYPE (ippp, int ***const);
57    CHECK_POINTER_HAS_TYPE (ippp, int **const *const);
58
59    // Provokes a warning because "int" is not compatible with "double":
60    CHECK_POINTER_HAS_TYPE (dp, int *);
61
62    // Provoke warnings because C's type compatibility rules only allow
63    // adding a "const" qualifier to the outermost pointer:
64    CHECK_POINTER_HAS_TYPE (ippp, const int ***);
65    CHECK_POINTER_HAS_TYPE (ippp, int *const**);
66 */
67 #define CHECK_POINTER_HAS_TYPE(POINTER, TYPE)           \
68         ((void) sizeof ((TYPE) (POINTER) == (POINTER)))
69
70 /* Given expressions A and B, both of which have pointer type,
71    expands to a void expression that causes a compiler warning if
72    A and B are not pointers to qualified or unqualified versions
73    of compatible types.
74
75    Examples similar to those given for CHECK_POINTER_HAS_TYPE,
76    above, can easily be devised. */
77 #define CHECK_POINTER_COMPATIBILITY(A, B) ((void) sizeof ((A) == (B)))
78
79 /* Equivalent to casting POINTER to TYPE, but also issues a
80    warning if the cast changes anything other than an outermost
81    "const" or "volatile" qualifier. */
82 #define CONST_CAST(TYPE, POINTER)                       \
83         (CHECK_POINTER_HAS_TYPE (POINTER, TYPE),        \
84          (TYPE) (POINTER))
85
86 /* Given POINTER, a pointer to the given MEMBER within structure
87    STRUCT, returns the address of the STRUCT. */
88 #define UP_CAST(POINTER, STRUCT, MEMBER)                                \
89         (CHECK_POINTER_COMPATIBILITY (&((STRUCT *) 0)->MEMBER, POINTER), \
90          (STRUCT *) ((char *) (POINTER) - offsetof (STRUCT, MEMBER)))
91
92 #endif /* libpspp/cast.h */