Home > Blockchain >  Split function-like macro call between two source files
Split function-like macro call between two source files

Time:11-28

Is there anything in the C Standard preventing me of doing the following?

// main.c
#define DECORATE(x) ***x***
#include "call_macro.h"
this is the text I want decorated)
// call_macro.h
DECORATE(

When running it though gcc -E main.c, I expected to get

*** this is the text I want decorated***

Instead, it complained about macro_call.h:2: error: unterminated argument list invoking macro "DECORATE", but I can't actually find any prohibition of it in the standard.

Thoughts?

CodePudding user response:

5.1.1.2 Translation phases
(1.4) Preprocessing directives are executed, macro invocations are expanded, and _Pragma unary operator expressions are executed... A #include preprocessing directive causes the named header or source file to be processed from phase 1 through phase 4, recursively. All preprocessing directives are then deleted.

I believe this says that each included header is preprocessed separately, before being "merged" into the overall translation unit. It is at this point that an incomplete function-like macro invocation would be ill-formed:

6.10.3/4 ... There shall exist a ) preprocessing token that terminates the invocation.

CodePudding user response:

This ...

#define DECORATE(x) ***x***

... is a complete definition of function-like macro DECORATE (C17 6.10.3/10). Its scope is the remainder of the translation unit (there being no corresponding #undef; C17 6.10.3.5/1) including source and header files #included into that portion of the translation unit.

For it to be possible for the text of an invocation of that macro to start in an included file and complete in the main file, the model for #include would need to be similar to that for macro expansion: the whole text of the included file being inserted and then processed in the context of the surrounding preprocessing tokens. But that is not the model.

Paragraph 5.1.1.2/1 describes the logical phases for translating C source code. The relevant one here is phase 4 (emphasis added):

  1. Preprocessing directives are executed, macro invocations are expanded, and _Pragma unary operator expressions are executed. If a character sequence that matches the syntax of a universal character name is produced by token concatenation (6.10.3.3), the behavior is undefined. A #include preprocessing directive causes the named header or source file to be processed from phase 1 through phase 4, recursively. All preprocessing directives are then deleted.

That #includeing a file causes that file to be processed from phase 1 through phase 4 means, among other things, that any function-like macro invocation that starts in that file must be complete within that file. Preprocessing tokens following the #include directive are not relevant to the preprocessing of the included file.

And paragraph 6.10.3/10 says (in part):

Each subsequent instance of the function-like macro name followed by a ( as the next preprocessing token introduces the sequence of preprocessing tokens that is replaced by the replacement list in the definition (an invocation of the macro).

That does not leave room to interpret the

DECORATE(

in macro_call.h as anything other than the beginning of an invocation of DECORATE(), yet that cannot be processed because

The replaced sequence of preprocessing tokens is terminated by the matching ) preprocessing token

and in fact, paragraph 6.10.3/4 requires there to be such a token, but no such preprocessing token appears in the file.

  • Related