macrosextern

Is defining extern as a macro undefined behaviour?


I came across some code that defines some functions using a macro named SMTP_LINKAGE that expands to extern.

snippets of interest

#ifdef SMTP_TEST
# define SMTP_LINKAGE extern
# include "../test/seams.h"
#else 
# define SMTP_LINKAGE static                               
#endif

SMTP_LINKAGE  enum str_getdelim_retcode
smtp_str_getdelimfd(struct str_getdelimfd *const gdf){
  ..
}

The smtp_str_getdelimfd function's prototype is defined in another file as

int
smtp_str_getdelimfd(struct str_getdelimfd *const gdf);

note the return value is int

If the macro is removed and the extern keyword is used directly the compiler complains of the defintion mismatch.

If however the SMTP_LINKAGE macro is used as shown, no such error occurs.

What causes this behaviour? Is it specified somewhere ?

I can not find any information on this topic.

Errors for the various possibilities

with enum no previous prototype for 'smtp_str_getdelimfd' [-Werror=missing-prototypes]

with static static declaration of 'smtp_str_getdelimfd' follows non-static declaration

with SMTP_LINKAGE ok

EDIT ! turns out I had suppresed a warning on earlier tests and without doing so the compiler catches the return type mismatch when using SMTP_LINKAGE

with SMTP_LINKAGE conflicting types for 'smtp_str_getdelimfd' due to enum/integer mismatch; have 'enum str_getdelim_retcode(struct str_getdelimfd * const)' [-Wenum-int-mismatch]

So no issues defining a macro as extern.


Solution

  • Macros quite literally are used as text substitution, so just as if you typed it manually, if this would work, there should be no issue with defining a macro for it. By this logic, if it doesn't work when defining as extern but works as this macro, it suggest the macro is not setting it to extern, rather to static.

    This could potentially be due to the test failing due to unforeseen linking issues.