1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2009 Free Software Foundation, Inc.
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.
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.
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/>. */
17 #ifndef LIBPSPP_CAST_H
18 #define LIBPSPP_CAST_H 1
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).
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 *);
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",
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);
59 // Provokes a warning because "int" is not compatible with "double":
60 CHECK_POINTER_HAS_TYPE (dp, int *);
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**);
67 #define CHECK_POINTER_HAS_TYPE(POINTER, TYPE) \
68 ((void) sizeof ((TYPE) (POINTER) == (POINTER)))
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
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)))
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), \
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)))
92 #endif /* libpspp/cast.h */