fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / docs / dev / c_functions.pod
blobcd609e0e933b582629ada09f3001508c8232c7a5
1 # Copyright (C) 2001-2006, Parrot Foundation.
2 # $Id$
4 =head1 NAME
6 docs/dev/c_functions.pod - C function decoration guidelines
8 =head1 Overview
10 Compilers have the ability to detect a wide class of potential errors in
11 code during the compilation phase, especially if certain metadata is
12 provided by the programmer to indicate details about specific operations.
13 This metadata is typically compiler-dependent, but using a system of
14 macros and our existing configuration system, we can instruct the
15 compiler to search for and prevent certain types of errors.
17 The net result is that errors (or potential errors) can be detected early
18 at compile-rime instead of later an runtime or during "make test".
20 Headerizer creates function declarations based on function
21 definitions. It scans the source files passed to it and extracts the
22 function declarations. Then it puts them into the appropriate .h file or,
23 in the case of static functions, back into the source file itself.
25 The headerizer also adds function attributes as specified by the
26 decorations on the source. It's important to properly-decorate functions
27 that are written, so that programs like headerizer can pass on important
28 metadata to the compiler.
30 Notice that not all of these decorations will have a real effect for all
31 compilers. In some cases, the various macros might be empty placeholders.
32 Also, where it says "compiler", it could also mean "lint or any
33 other static analysis tool like splint."
35 =head1 Function Parameter Decorators
37 =head2 What's a shim?
39 Think of "shim" as shorthand for "placeholder". It's 64% shorter.
41 GCC (and lint and splint and other analysis tools) likes to complain if
42 you pass an argument into a function and don't use it. If we know that we're
43 not going to use an argument, we can either remove the argument from
44 the function declaration, or mark it as unused.
46 Throwing the argument away is not always possible. Usually, it's because
47 the function is one that gets referred to by a function pointer, and
48 all functions of this group must have the same signature. Consider a
49 function with three args: Interp, Foo and Bar. Maybe a given function
50 doesn't use Foo, but we still have to accept Foo because all the other
51 functions like ours do. In this case we can use the C<UNUSED(Foo)> macro
52 in the body of the function to silence any compiler warnings. C<UNUSED>
53 lets the compiler know that we know the parameter isn't used, and that
54 we haven't just forgotten about it. C<UNUSED> is for cases where we don't
55 currently use a particular parameter, but we might in the future. If we
56 never will use it, mark it as a C<SHIM(Foo)> in the declaration. Here's an
57 example:
59   void MyFunction(PARROT_INTERP, SHIM(int Foo), /* Never using Foo */
60           int Bar)
61   {
62       UNUSED(Bar);  /* We aren't using Bar YET */
63           ...
64   }
66 If the interpreter structure in a function is a shim, there is a special
67 macro for that. 
69 =head2 Passing Interpreter Pointers
71 Most of the time, if you need an interpreter in your function,
72 define that argument as C<PARROT_INTERP>.  If your interpreter is
73 a shim, then use C<SHIM_INTERP>, not C<SHIM(PARROT_INTERP)>. 
75 =head2 What are input and output arguments?
77 Pointers are dangerous because they are so versatile. You can pass a pointer
78 to a function only to have that function modify the data that the pointer
79 is pointing to. In Parrot, we decorate all our pointer parameters with
80 keywords like C<ARGIN>, C<ARGOUT>, and C<ARGMOD> to specify whether the
81 pointer is an input only, an output only, or is modified.
83 Input pointers are pointers which are read, but the data they point to is
84 not changed. The data after the function call is the same as the data you
85 had before it. If you specify a parameter is an input parameter, and the
86 function tries to modify its contents anyway, you'll get a warning. Also,
87 if you pass in an uninitialized pointer, the compiler will throw a warning.
89 Output pointers are pointers that are passed into a function, its existing
90 contents are ignored, and new contents are created for it. It's called an
91 output because the data in the pointed-to structure are populated inside
92 the function and passed back out to the caller. If you have a pointer that
93 points to valid data and you pass it as an ARGOUT parameter, the compiler
94 will throw a warning. Unlike input arguments, you can typically pass an
95 uninitialized pointer as an ARGOUT parameter.
97 Modifiable, or "in-out" parameters are parameters that have both behaviors.
98 Some fields in it are read, some fields in it are changed.
100 Please note that these are only to be used on pointer types.  If you're
101 not absolutely sure that the argument is a pointer, don't use them.
102 (The "va_list" builtin type is sometimes a pointer, sometimes a struct,
103 depending on platform and compiler.)
105 Here's a simple example of a function that uses these modifiers:
107   void MyFunction(PARROT_INTERP, ARGIN(char *Foo),
108           ARGOUT(int *Bar), ARGMOD(float *Baz));
110 =head2 NOTNULL(x)
112 For function arguments and variables that must never have NULL
113 assigned to them, or passed into them.  For example, if we were
114 defining C<strlen()> in Parrot, we'd do it as
115 C<strlen(NOTNULL(const char *p))>. All the previous pointer decorations,
116 C<ARGIN>, C<ARGOUT> and C<ARGMOD> imply C<NOTNULL>. The compiler will
117 throw a warning if it detects a null value being passed to a C<NOTNULL>
118 parameter.
120 =head2 NULLOK(x)
122 For function arguments and variables where it's OK to pass in NULL.
123 For example, if we wrote C<free()> in Parrot, it would be
124 C<strlen(NULLOK(void *p))>. There are variants of C<ARGIN>, C<ARGOUT>,
125 and C<ARGMOD> that allow NULL values: C<ARGIN_NULLOK>, C<ARGOUT_NULLOK>,
126 and C<ARGMOD_NULLOK>. These have the same semantics as their
127 non-NULLOK counterparts, except the compiler will not throw errors if
128 a null value is passed.
130 =head1 Function Decorators
132 In addition to the C<SHIM>, C<ARGIN>, C<ARGOUT> and C<ARGMOD> parameters
133 and variants for parameters, there are a number of helpful modifiers that
134 can be applied directly to the function declaration itself.
136 =head2 PARROT_WARN_UNUSED_RESULT
138 Tells the compiler to warn if the function is called, but the result is
139 ignored. For instance, on a memory allocation function you would want to
140 keep track of the result so that you could free it later and not cause
141 a memory leak.
143 =head2 PARROT_IGNORABLE_RESULT
145 Tells the compiler that it's OK to ignore the function's return value.
147 =head2 PARROT_MALLOC
149 Functions marked with this are flagged as having received C<malloc>ed
150 memory. This lets the compiler do analysis on memory leaks.
152 =head2 PARROT_CONST_FUNCTION
154 The function is a deterministic one that will always return the
155 same value if given the same arguments, every time.  Examples include
156 functions like C<mod> or C<max>.  An anti-example is C<rand()> which
157 returns a different value every time. Some compilers can do optimizations
158 by replacing constant functions with lookup tables, if the results are
159 always going to be the same.
161 =head2 PARROT_PURE_FUNCTION
163 Less stringent than PARROT_CONST_FUNCTION, these functions only
164 operate on their arguments and the data they point to. These functions
165 have no other side effects to worry about, and clever compilers may find
166 ways to optimize these functions. Examples include C<strlen()> or
167 C<strchr()>.
169 =head2 PARROT_DOES_NOT_RETURN
171 For functions that can't return, like C<Parrot_exit()> or functions that
172 cause exceptions to be thrown. This helps the compiler's flow analysis
173 which can help detect unreachable code, or opportunities for optimization.
175 =head2 PARROT_CANNOT_RETURN_NULL
177 For functions that return a pointer, but the pointer is guaranteed to not
178 be NULL. The compiler can help to detect null pointer dereferences, and
179 this hint will simplify the process.
181 =head2 PARROT_CAN_RETURN_NULL
183 For functions that return a pointer that could be null. These return values
184 should be tested for null values before they are used or dereferenced.
186 =head2 PARROT_INLINE
188 For functions that could be inlined by the compiler for optimization. This
189 is more of a hint then a command, and many compilers might ignore it
190 entirely. Use this instead of the C<inline> keyword.
192 =head2 PARROT_EXPORT
194 For functions that are important API functions.
196 {{TODO: More detail is needed on this}}
198 =head1 Examples
200     PARROT_EXPORT
201     PARROT_WARN_UNUSED_RESULT
202     INTVAL
203     Parrot_str_find_index(PARROT_INTERP, NOTNULL(const STRING *s),
204             NOTNULL(const STRING *s2), INTVAL start)
207 C<Parrot_str_find_index> is part of the Parrot API, and returns an INTVAL. The
208 interpreter is used somewhere in the function. String C<s> and C<s2>
209 cannot be NULL. If the calling function ignores the return value,
210 it's an error, because you'd never want to call C<Parrot_str_find_index()>
211 without wanting to know its value.
213     PARROT_EXPORT
214     PARROT_PURE_FUNCTION
215     INTVAL
216     parrot_hash_size(SHIM_INTERP, NOTNULL(const Hash *hash))
217     {
218         return hash->entries;
219     }
221 This function is a pure function because it only looks at its parameters
222 or global memory. The interpreter doesn't get used, but needs to be
223 passed because all PARROT_EXPORT functions have interpreters passed, so is
224 flagged as a SHIM_INTERP.
226 We could put C<PARROT_WARN_UNUSED_RESULT> on this function, but since
227 all C<PARROT_PURE_FUNCTION>s and C<PARROT_CONST_FUNCTION>s get flagged
228 that way anyway, there's no need.