Question
I try to find static (compile time) asserts, to ensure (as good as possible) things below. As I use them in an auto code generation context (see “Background” below) they do not have to be neat, the only have to break compilation, at best with zero overhead. Elegant variants are welcomed though.
The following things shall be checked:
A Type Identity
typedef T T1;
typedef T T2;
typedef X T3;
T1 a;
T2 b;
T3 c;
SA_M1(T1,T2); /* compilation */
SA_M1(T1,T3); /* compilation error */
SA_M2(a,b); /* compilation */
SA_M2(a,c); /* compilation error */
where X
and T
are C Types (including structured, aggregated, object pointer, not so important function pointer). Note again, that a set of partly successful solutions also helps.
Some solutions that I assume will partly work:
- comparing the sizes
- checking if the type is a pointer as claimed by trying to dereference it.
- for unsigned integers: Compare a casted slightly to big value with the expected wrap around value.
- for floats, compare double precision exact representable value with the casted one (hoping the best for platform specific rounding operations)
B A Variable has global Scope
My solution here is at the momement simply to generate a static function, that tries to get a reference to the global variable Assume that X
is a global variable:
static void SA_IsGlobal_X() {(void) (&X == NULL); /* Dummy Operation */}
C A Function has the correct number of parameters
I have no idea yet.
D If the prototype of a functions is as it is expected
I have no idea yet.
E If a function or macro parameters are compile time constants (
This question is discussed here for macros:
Macro for use in expression while enforcing its arguments to be compile time constants
For functions, an wrapper macro could do.
Z Other things you might like to check considering the “background” part below
Preferred are answers that can be done with C89, have zero costs in runtime, stack and (with most compilers) code size. As the checks will be auto generated, readability is not so important, but I like to place the checks in static functions, whenever possible.
Background:
I want to provide C functions as well as an interface generator to allow them to smoothly being integrated in different C frameworks (with C++ on the horizon). The user of the interface generator then only specifies where the inputs come from, and which of the outputs shall go where. Options are at least:
- RAW (as it is implemented - and should be used)
- from the interface functions parameter, which is of a type said to be the same as my input/output (and perhaps is a field of a structure or an array element)
- from a getter/setter function
- from a global variable
- using a compile time constant
I will:
- ask for a very detailed interface specification (including specification errors)
- use parsers to check typedefs and declarations (including tool bugs and my tool usage errors)
But this happens at generation time. Besides everything else: if the user change either the environment or takes a new major version of my function (this can be solved by macros checking versions), without running the interface generator again, I would like to have a last defense line at compile time.
The resulting code of the generations might near worst case be something like:
#include "IFMyFunc.h" /* contains all user headers for the target framework(s) */
#include "MyFunc.h"
RetType IFMYFunc(const T1 a, const struct T2 * const s, T3 * const c)
{
/* CHECK INTERFACE */
CheckIFMyFunc();
/* get d over a worst case parametrized getter function */
const MyD_type d = getD(s->dInfo);
/* do horrible call by value and reference stuff, f and g are global vars */
c.c1 = MyFunc(a,s->b,c.c1,d,f,&(c->c2), &e,&g);
set(e);
/* return something by return value */
return e;
}
(I am pretty sure I will restrict the combos though).
static void CheckIFMyFunc(void)
{
/* many many compile time checks of types and specifications */
}
or I will provide a piece of code (local block) to be directly infused - which is horrible architecture, but might be necessary if we can't abandon some of the frame work fast enough, supported by some legacy scripts.