1 /* -*- coding: utf-8 -*-
2  * ----------------------------------------------------------------------
3  * Copyright © 2011, RedJack, LLC.
4  * All rights reserved.
5  *
6  * Please see the COPYING file in this distribution for license
7  * details.
8  * ----------------------------------------------------------------------
9  */
10 
11 #ifndef LIBCORK_CORE_ATTRIBUTES_H
12 #define LIBCORK_CORE_ATTRIBUTES_H
13 
14 #include <libcork/config.h>
15 
16 
17 /*
18  * Declare a “const” function.
19  *
20  * A const function is one whose return value depends only on its
21  * parameters.  This is slightly more strict than a “pure” function; a
22  * const function is not allowed to read from global variables, whereas
23  * a pure function is.
24  *
25  *   int square(int x) CORK_ATTR_CONST;
26  */
27 
28 #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES
29 #define CORK_ATTR_CONST  __attribute__((const))
30 #else
31 #define CORK_ATTR_CONST
32 #endif
33 
34 
35 /*
36  * Declare a “pure” function.
37  *
38  * A pure function is one whose return value depends only on its
39  * parameters, and global variables.
40  *
41  *   int square(int x) CORK_ATTR_PURE;
42  */
43 
44 #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES
45 #define CORK_ATTR_PURE  __attribute__((pure))
46 #else
47 #define CORK_ATTR_PURE
48 #endif
49 
50 
51 /*
52  * Declare that a function returns a newly allocated pointer.
53  *
54  * The compiler can use this information to generate more accurate
55  * aliasing information, since it can infer that the result of the
56  * function cannot alias any other existing pointer.
57  */
58 
59 #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES
60 #define CORK_ATTR_MALLOC  __attribute__((malloc))
61 #else
62 #define CORK_ATTR_MALLOC
63 #endif
64 
65 
66 /*
67  * Declare that a function shouldn't be inlined.
68  */
69 
70 #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES
71 #define CORK_ATTR_NOINLINE  __attribute__((noinline))
72 #else
73 #define CORK_ATTR_NOINLINE
74 #endif
75 
76 
77 /*
78  * Declare an entity that isn't used.
79  *
80  * This lets you keep -Wall activated in several cases where you're
81  * obligated to define something that you don't intend to use.
82  */
83 
84 #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES
85 #define CORK_ATTR_UNUSED  __attribute__((unused))
86 #else
87 #define CORK_ATTR_UNUSED
88 #endif
89 
90 
91 /*
92  * Declare a function that takes in printf-like parameters.
93  *
94  * When the compiler supports this attribute, it will check the format
95  * string, and the following arguments, to make sure that they match.
96  * format_index and args_index are 1-based.
97  */
98 
99 #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES
100 #define CORK_ATTR_PRINTF(format_index, args_index) \
101     __attribute__((format(printf, format_index, args_index)))
102 #else
103 #define CORK_ATTR_PRINTF(format_index, args_index)
104 #endif
105 
106 
107 /*
108  * Declare a var-arg function whose last parameter must be a NULL
109  * sentinel value.
110  *
111  * When the compiler supports this attribute, it will check the actual
112  * parameters whenever this function is called, and ensure that the last
113  * parameter is a @c NULL.
114  */
115 
116 #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES
117 #define CORK_ATTR_SENTINEL  __attribute__((sentinel))
118 #else
119 #define CORK_ATTR_SENTINEL
120 #endif
121 
122 
123 /*
124  * Declare that a boolean expression is likely to be true or false.
125  */
126 
127 #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES
128 #define CORK_LIKELY(expr)  __builtin_expect((expr), 1)
129 #define CORK_UNLIKELY(expr)  __builtin_expect((expr), 0)
130 #else
131 #define CORK_LIKELY(expr)  (expr)
132 #define CORK_UNLIKELY(expr)  (expr)
133 #endif
134 
135 /*
136  * Declare that a function is part of the current library's public API, or that
137  * it's internal to the current library.
138  */
139 
140 #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES && !defined(__CYGWIN__) && !defined(__MINGW32__)
141 #define CORK_EXPORT  __attribute__((visibility("default")))
142 #define CORK_IMPORT  __attribute__((visibility("default")))
143 #define CORK_LOCAL   __attribute__((visibility("hidden")))
144 #else
145 #define CORK_EXPORT
146 #define CORK_IMPORT
147 #define CORK_LOCAL
148 #endif
149 
150 
151 /*
152  * Declare a static function that should automatically be called at program
153  * startup.
154  */
155 
156 /* TODO: When we implement a full Windows port, [1] describes how best to
157  * implement an initialization function under Visual Studio.
158  *
159  * [1] http://stackoverflow.com/questions/1113409/attribute-constructor-equivalent-in-vc
160  */
161 
162 #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES
163 #define CORK_INITIALIZER(name) \
164 __attribute__((constructor)) \
165 static void \
166 name(void)
167 #else
168 #error "Don't know how to implement initialization functions of this platform"
169 #endif
170 
171 
172 #endif /* LIBCORK_CORE_ATTRIBUTES_H */
173