feos feos - 1 year ago 213
C Question

Invalid storage class for a function in a macro in GCC

I have this legacy macro

#define ASYNC_FUNCTION(x) \
void x(void) { \
static void internal ## x (ASYNCIOCB *); \
ASYNCIOCB *aiocb = AcquireAsyncIOCB(); \
CallAsyncNativeFunction_md(aiocb, internal ## x); \
} \
static void internal ## x (ASYNCIOCB *aiocb)


followed by this one

#define ASYNC_FUNCTION_START(x) ASYNC_FUNCTION(x) {
#define ASYNC_FUNCTION_END ASYNC_resumeThread(); }


And their use looks like this:

ASYNC_FUNCTION_START(Occasional_function_name)
{
//actual stuff
}
ASYNC_FUNCTION_END


It compiles fine with cl, but gcc gives

invalid storage class for function ‘internalOccasional_function_name’
static void internal##x (ASYNCIOCB *);
^


I tried to expand them all just to see what it becomes and found nothing broken. I also searched for unclosed curved brackets in the file, and found other macros like this

#define Foo_Bar1() { \
extern int foo; \
int bar = foo; \
if (condition) { \
Bar_Foo(); \
} \

#define Foo_Bar2() \
if (condibar != footion1){ \
AbortAsyncIOCB(aiocb); \
return; \
} \
if (condition) { \
Bar_Foo(); \
} \
}


No other headers are included, so other than that last macro looking weird, I couldn't find any obvious errors. I'm using cygwin and I'm fairly clueless.

Answer Source

You can't declare a static function inside of another one. You need to put the declaration outside of void(x):

#define ASYNC_FUNCTION(x)                                               \
static void internal ## x (ASYNCIOCB *);                                \
void x(void) {                                                          \
    ASYNCIOCB *aiocb = AcquireAsyncIOCB();                              \
    CallAsyncNativeFunction_md(aiocb, internal ## x);                   \
}                                                                       \
static void internal ## x (ASYNCIOCB *aiocb)

Then, if you run the source through just the preprocessor via gcc -E, you'll get something like this (extra spacing added):

static void internalOccasional_function_name (ASYNCIOCB *);
void Occasional_function_name(void)
{
    ASYNCIOCB *aiocb = AcquireAsyncIOCB();
    CallAsyncNativeFunction_md(aiocb, internalOccasional_function_name);
}
static void internalOccasional_function_name (ASYNCIOCB *aiocb) 
{
    {
        int a=1;
    }
    ASYNC_resumeThread();
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download