Does using `restrict` when initializing a new pointer actually do anything? - c

I have been reading about the restrict keyword and every example I've seen uses it when defining a function.
void foo (int *restrict bar, float *restrict baz);
I have been reading through articles on it and wondering if this would be something valid.
int main()
{
int *restrict bar = malloc(sizeof(int));
//... code using bar
return 0;
}
I tested it with gcc and I am not receiving any compiler warnings, but will it actually do anything? Will the compiler pick up that this pointer for it's life will not overlap and that it will not be shared by any other pointer or will it only work when used when defining a function?

The restricted 'bar' in main tell the compiler that the data will not be referenced via any other pointer. Depending on what main does, it might help with optimization of 'main'. If the only manipulation of bar is in function foo, there is no need to make it restrict.
As a side note, on Linux/gcc, the 'malloc' is tagged with __attribute__ ((__malloc__)), which tells the compiler that the returned value is restrict pointer, which will allow the compiler the perform the required optimization, if relevant. See: understanding malloc.h difference: __attribute_malloc__ https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
malloc
This tells the compiler that a function is malloc-like, i.e., that the pointer P
returned by the function cannot alias any other pointer valid when the function
returns, and moreover no pointers to valid objects occur in any storage addressed by P.
Using this attribute can improve optimization. Compiler predicts that
a function with the attribute returns non-null in most cases.
Functions like malloc and calloc have this property because they
return a pointer to uninitialized or zeroed-out storage. However,
functions like realloc do not have this property, as they can return a
pointer to storage containing pointers.

Related

Can a function use its own address in c11?

Is the following valid c11 code? I have checked the standard, and it seems unsupported, but I may be missing something. This example is a little contrived, but my actual situation involves like a thousand lines of code and wouldn't make much sense without all that context, and this example correctly isolates the principal I want to ask about. The point is that I use the function's own address by directly using its identifier.
typedef void(*ftype)(void*,void*);
void func(void* v, void* w)
{
if( func != (ftype)v ) ((ftype)v)( ((void**)w)[0], ((void**)w)[1]) );
}
So, the idea is to run the function pointed to by v for its side effects, with its input given by an array pointed to by w. However, it is desired to not run v if it happens to be a reference to the function 'func'.
EDIT: A comment answered the question: "A direct function call involves an implicit conversion ("decay") from the function name to a pointer to the function. Hence, every recursive function effectively takes its own address."
typedef void(*ftype)(void*,void*);
void func(void* v, void* w);
ftype myfunc = func; //here
Since we can take the address of functions that are 100% undefined in each translation unit, there's no reason that C should have a rule that disallows taking the address of a function that's partially defined. And when we check, there is indeed no such exception. Therefore, you can always take the address of a declared function, even inside the function.

restrict for return type and local variables

I have a good understanding of when to use restrict for function arguments. But all the articles I've found so far never mention other declarations (like function return values and local variables).
Here is one example:
extern int *alloc_foo(void);
extern int *alloc_bar(void);
int *foo = alloc_foo();
foo[i] = 42;
int *bar = alloc_bar();
f(foo[i]);
If alloc_foo() and alloc_bar() are guaranteed to return non-aliased addresses (like if there are wrappers for malloc), should I make them return restrict?
Should I make foo and bar restrict?
Returning restrict is not meaningful, just like returning const or volatile wouldn't be. This is because the return value of a function is purely a value expression ("rvalue"), not an expression denoting an object ("lvalue"). I don't know any way to encode the knowledge of non-aliasing in the function type without GCC attributes (whereby you could mark the function as being malloc-like) but the caller is free to store the result in a restrict-qualified pointer object and thereby give the compiler this knowledge.

Does `const T *restrict` guarantee the object pointed-to isn’t modified?

Consider the following code:
void doesnt_modify(const int *);
int foo(int *n) {
*n = 42;
doesnt_modify(n);
return *n;
}
where the definition of doesnt_modify isn’t visible for the compiler. Thus, it must assume, that doesnt_modify changes the object n points to and must read *n before the return (the last line cannot be replaced by return 42;).
Assume, doesnt_modify doesn’t modify *n. I thought about the following to allow the optimization:
int foo_r(int *n) {
*n = 42;
{ /* New scope is important, I think. */
const int *restrict n_restr = n;
doesnt_modify(n_restr);
return *n_restr;
}
}
This has the drawback that the caller of doesnt_modify has to tell the compiler *n isn’t modified, rather than that the function itself could tell the compiler via its prototype. Simply restrict-qualifying the parameter to doesnt_modify in the declaration doesn’t suffice, cf. “Is top-level volatile or restrict significant [...]?”.
When compiling with gcc -std=c99 -O3 -S (or Clang with the same options), all functions are compiled to equivalent assembly, all re-reading the 42 from *n.
Would a compiler be allowed to do this optimization (replace the last line by return 42;) for foo_r? If not, is there a (portable, if possible) way to tell the compiler doesnt_modify doesn’t modify what its argument points to? Is there a way compilers do understand and make use of?
Does any function have UB (provided doesnt_modify doesn’t modify its argument’s pointee)?
Why I think, restrict could help here (From C11 (n1570) 6.7.3.1 “Formal definition of restrict”, p4 [emph. mine]):
[In this case, B is the inner block of foo_r, P is n_restr, T is const int, and X is the object denoted by *n, I think.]
During each execution of B, let L be any lvalue that has &L based on P. If L is used to access the value of the object X that it designates, and X is also modified (by any means), then the following requirements apply: T shall not be const-qualified. […]
$ clang --version
Ubuntu clang version 3.5.0-4ubuntu2 (tags/RELEASE_350/final) (based on LLVM 3.5.0)
Target: x86_64-pc-linux-gnu
Gcc version is 4.9.2, on an x86 32bit target.
Version 1 seems clearly specified by the formal definition of restrict (C11 6.7.3.1). For the following code:
const int *restrict P = n;
doesnt_modify(P);
return *P;
the symbols used in 6.7.3.1 are:
B - that block of code
P - the variable P
T - the type of *P which is const int
X - the (non-const) int being pointed to by P
L - the lvalue *P is what we're interested in
6.7.3.1/4 (partial):
During each execution of B, let L be any lvalue that has &L based on P. If L is used to access the value of the object X that it designates, and X is also modified (by any means), then the following requirements apply: T shall not be const-qualified
[...]
If these requirements are not met, then the behavior is undefined.
Note that T is const-qualified. Therefore, if X is modified in any way during this block (which includes during the call to a function in that block), the behaviour is undefined.
Therefore the compiler can optimize as if doesnt_modify did not modify X.
Version 2 is a bit more difficult for the compiler. 6.7.6.3/15 says that top-level qualifiers are not considered in prototype compatibility -- although they aren't ignored completely.
So although the prototype says:
void doesnt_modify2(const int *restrict p);
it could still be that the body of the function is declared as void doesnt_modify2(const int *p) and therefore might modify *p.
My conclusion is that if and only if the compiler can see the definition for doesnt_modify2 and confirm that p is declared restrict in the definition's parameter list then it would be able to perform the optimization.
Generally, restrict means that the pointer is not aliased (i.e. only it or a pointer derived from it can be used to access the pointed-to object).
With const, this means that the pointed-to object cannot be modified by well-formed code.
There is, however, nothing to stop the programmer breaking the rules using an explicit type conversion to remove the constness. Then the compiler (having been beaten into submission by the programmer) will permit an attempt to modify the pointed-to object without any complaint. This, strictly speaking, results in undefined behaviour so any result imaginable is then permitted including - possibly - modifying the pointed-to object.
If not, is there a (portable, if possible) way to tell the compiler doesnt_modify doesn’t modify what its argument points to?
No such way.
Compiler optimizers have difficulty optimizing when pointer and reference function parameters are involved. Because the implementation of that function can cast away constness compilers assume that T const* is as bad as T*.
Hence, in your example, after the call doesnt_modify(n) it must reload *n from memory.
See 2013 Keynote: Chandler Carruth: Optimizing the Emergent Structures of C++. It applies to C as well.
Adding restrict keyword here does not change the above.
Simultaneous use of a restrict qualifier on a pointer-type parameter and a const qualifier on its target type would invite a compiler to assume that no region of storage which is accessed during the lifetime of the pointer object via the pointer contained therein or any pointer derived from it, will be modified via any means during that pointer's lifetime. It generally says nothing whatsoever about regions of storage which are not accessed using the pointer in question.
The only situations where const restrict would have implications for an entire object would be those where pointer is declared using array syntax with a static bound. In that situation, behavior would only be defined in cases where the entire array object could be read (without invoking UB). Since reading any part of the array object which changes during function execution would invoke UB, code would be allowed to assume that no portion of the array can be changed in any fashion whatsoever.
Unfortunately, while a compiler that knew that a function's actual definition starts with:
void foo(int const thing[restrict static 1]);
would be entitled to assume that no part of *thing would be changed during the function's execution, even if the object might be one the function could otherwise access via pointer not derived from thing, the fact that a function's prototype includes such qualifiers would not compel its definition to do likewise.

C cast void pointer to function pointer

I am trying to create some macros that I can use to create my own unit testing library. My header file looks like this:
#ifndef _TEST_H_
#define _TEST_H_
#include <stdio.h>
#include "hehe_stack.h"
static hehe_stack* tests;
typedef int (*testfunc)();
#define test_init() tests = hehe_stack_init();
#define test_register(test) hehe_stack_push(tests, test);
#define test_info() fprintf(stdout, "running %s :: %s \n", __FILE__, __func__);
#define test_run() testfunc = (int (*)()) hehe_stack_pop(tests); testfunc(); return 0;
#endif
In each test .c file I want to push a number of function pointers into the tests stack and then pop each function pointer out of the stack and call it. My stack pop method returns a void pointer, and the function pointer that I am pushing onto it returns an int and takes no parameters. Is my syntax incorrect? I feel like I should be able to do this.
The C99 standard does not allow to convert between pointers to data (in the standard, “objects or incomplete types” e.g. char* or void*) and pointers to functions.
6.3.2.3:8 A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall
compare equal to the original pointer. If a converted pointer is used
to call a function whose type is not compatible with the pointed-to
type, the behavior is undefined.
One reason is that pointers to objects and pointers to functions do not have to be the same size. On an example architecture, the former can be 64-bit and the latter 32-bit.
You can cast from a pointer to a certain function type to a pointer to another function type, and this is the technique I recommend you use if you need to store function pointers in a data structure. Any function type will do. This means you cannot reuse a data structure intended for data pointers. You need to duplicate the data structure and change it to hold function pointers.
Do not forget to cast back to the proper function pointer type before calling, otherwise this is undefined behavior.
NOTE that, as pointed out by Andrew Mellinger, some compilers allow the conversion in each direction. C11's annex “J.5 Common extensions” lists:
J.5.7 Function pointer casts
1 A pointer to an object or to void may be cast to a pointer to a function, allowing data to be invoked as a function (6.5.4).
2 A pointer to a function may be cast to a pointer to an object or to void, allowing a function to be inspected or modified (for example, by a debugger) (6.5.4).
Some POSIX interfaces, such as dlsym(), also in effect mandate these conversions to be valid in the POSIX system's C compiler.
You can do it, but you're not supposed to do it by accident, so the syntax is made especially awkward. One does not cast the function pointer, but a pointer to a function pointer, then assigns that.
#define test_run() *((void**)&testfunc) = hehe_stack_pop(tests); testfunc(); return 0;
This turns &testfunc into a pointer to a void*, then dereferences it and assigns the value of another void* to it, which is legal.
The suggested code never compiles as you are not supposed to dereference a void * pointer (how could you? There is no type information about the particular pointer.)
The way cmotley suggests in his comment is the correct way to do this although I would recommend a little improvement for the sake of readability:
typedef int (*tTestFuncSignature)(void)
#define test_run() tTestFuncSignature testfunc = hehe_stack_pop(tests); testfunc();
or even to avoid hidden name clashes using this macro:
#define test_run() ((tTestFuncSignature)hehe_stack_pop(tests))();
Either way you have to make sure (e.g. by contract) you only got valid pointers in your stack or have to test the pointer first before invoking the function.
Edit: Corrected code formatting

How do I quiet the C compiler about a function pointer takes any number of arguments?

I have a function pointer inside a struct that gets dynamically set at runtime to the address of another function in various places in my code. It is defined in my header file like this:
void *(*run)();
During compile time, I get the following warning about this:
warning: function declaration isn't a prototype
This warning is benign, because the pointer is used in many places in my code to call the function it points to, and everything works just fine. However, I would really like to silence the warning.
If I change it to this:
void *(*run)(void);
I get compile errors whever I use it, because the various functions that make use of the pointer have different numbers of arguments, and saying void inside the parenthesies tells the compiler it accepts no arguments.
I can't use a va_list or anything fancy like that, as this is simply a pointer to another function, and I use a single pointer for them all because it keeps the code clean and simple.
I can silence the warning with adding this to my compiler flags:
-Wno-strict-prototypes
But I'd rather not have to disable compiler warnings with flags if I can avoid it.
So my question is: How do I notate this function pointer in the code in such a way that the compiler is satisfied with the fact that it accepts any number of any kind of arguments?
The code works perfectly. I just want the warning to go away.
Store the pointer as a void * and cast to the appropriate function pointer type when necessary? Keep in mind that it isn't necessarily safe to call one type of function pointer as if it were another type, so the warning you're starting out with isn't entirely invalid.
You can cast a function pointer like so:
void *genericPointer = ...;
void (*fp)(int, int) = genericPointer;
fp(123, 456);
Note that:
There's no explicit casting necessary here, as void * can always be cast to any pointer type.
The initial "void" before (*fp) is the return type of the function pointer.
You are trying to do things clean - i.e. involve the compiler in checks, but the design you invented simply cannot be clean by its principle. You cannot involve compiler in prototype checks this way, because you always must know, which parameters to pass at this particular case in runtime. Compiler cannot check this and if you make a mistake, segmentation fault is on the way.
But if I remember well, something like this was maybe used also in linux kernel (?). The solution is to have a general pointer (like the one you have) and each time you call a particular function you just typecast it to the pointer to function with the particular arguments. You may need to typecast it to void * first to silence the compiler again :-)
In C, when you call a function without a prototype visible, default argument promotions are applied to all of the arguments that you pass to the function. This means that the types that you actually pass do not necessarily match the types received by the function.
E.g.
void (*g)();
void f()
{
float x = 0.5;
g(x); // double passed
}
This means that you need to know that the function that you are actually calling has a compatible signature to that implied by the arguments that you are passing after promotion.
Given that you need to know this in any case you must know the function signature of the actual function being called at the call site which is using the function pointer. With this knowledge it is usually simpler and cleaner to use a function pointer with the correct prototype and you can avoid default argument promotion entirely.
Note that as you are defining your functions with prototypes, when you assigned a pointer to your function to a function pointer without a prototype you effective converted, say, a void(*)(int, int) to a void(*)() so it is completely correct and desirable to perform the reverse conversion before calling the function. gcc allows both these conversions without emitting any warnings.
E.g.
void PerformCall( void(*p)() )
{
if (some_condition)
{
// due to extra knowledge I now know p takes two int arguments
// so use a function pointer with the correct prototype.
void(*prototyped_p)(int, int) = p;
prototyped_p( 3, 4 );
}
}
Try typedefing the function pointer declaration and then have the caller explicityly cast it:
typedef void *(*run)();
//when calling...
void my_foo() {}
run r = (run)my_foo;
If the different function signatures are known, use a union. Otherwise, use a pointer of type void (*)(void) (actually, any function pointer type would do) to hold the generic pointer and convert to the proper type when setting the value and calling the code.
Example using a union:
union run_fn
{
void *(*as_unary)(int);
void *(*as_binary)(int, int);
};
struct foo
{
union run_fn run;
};
void *bar(int, int);
struct foo foo;
foo.run.as_binary = bar;
void *baz = foo.run.as_binary(42, -1);
Example using explicit casts:
struct foo
{
void (*run)(void);
};
void *bar(int, int);
struct foo foo;
foo.run = (void *(*)(int, int))bar;
void *baz = ((void *(*)(int, int))foo.run)(42, -1);
Don't use a void * to hold function pointers - such a conversion is unspecified by the ISO C standard and may be unavailable on certain architectures.
Ignoring the warning and using your code as-is is actually also a possibility, but keep in mind that any function argument will be subject to the default argument promotions and it's your responsibility that the promoted arguments properly match the declared parameters.

Resources