Julio Guerra
Julio Guerra

Reputation: 5661

Expand a macro in a macro

Given the following macros giving access to compiler attributes in a function-call way, like spec(section(".mysection")) void foo(void);:

#define spec(_H_) spec_##_H_
#define spec_section(_S_) attribute ((section (_S_)))

I now would like to use these definitions in other macros, like spec(namespace(unmanaged)) int x;:

#define spec_namespace(_H_) spec_namespace_##_H_
#define spec_namespace_unmanaged spec(section(".unmanaged"))

But this does not expand at all, the only way to make it work is writting the expanded spec() macro myself:

#define spec_namespace_unmanaged spec_section(".unmanaged")

Any idea of what is going on? gcc -E on spec(namespace(unmanaged)) results inspec(namespace(unmanaged)).

Upvotes: 4

Views: 7463

Answers (2)

Dmitry Grigoryev
Dmitry Grigoryev

Reputation: 3203

To put it simply, the preprocessor will only expand a nested macro on the left side (in another macro's arguments) if neither the stringification operator # nor the concatenation operator ## are applied to it on the right side (in the macro definition).

The idiomatic way to force a nested macro expansion is to use a helper macro:

#define macro_helper(x) macro(x) // gets x expanded

Consider the following example which gets the nested __LINE__ macro expanded:

#include <iostream>

#define MACRO1(L)   "Line " #L         // MACRO1(__LINE__) -> "Line " "__LINE__")
#define MACRO2       MACRO1(__LINE__)  // MACRO2 -> MACRO1(__LINE__)

#define MACRO3(L)   "Line " #L         // MACRO3(13) -> "Line " "13")
#define MACRO4(L)   MACRO3(L)          // MACRO4(__LINE__) -> MACRO3(13)
#define MACRO5      MACRO4(__LINE__)   // MACRO5 -> MACRO4(__LINE__)

int main()
{
    std::cout << MACRO2 << std::endl;  // Output: "Line __LINE__"
    std::cout << MACRO5 << std::endl;  // Output: "Line 13"
}

Upvotes: 2

Grzegorz Szpetkowski
Grzegorz Szpetkowski

Reputation: 37914

Citing C99 draft 6.10.3.4 Rescanning and further replacement §2 (emphasis mine):

If the name of the macro being replaced is found during this scan of the replacement list (not including the rest of the source file’s preprocessing tokens), it is not replaced. Furthermore, if any nested replacements encounter the name of the macro being replaced, it is not replaced. These nonreplaced macro name preprocessing tokens are no longer available for further replacement even if they are later(re)examined in contexts in which that macro name preprocessing token would otherwise have been replaced.

From folowing macro-definitions:

#define spec(_H_) spec_##_H_
#define spec_namespace(_H_) spec_namespace_##_H_
#define spec_namespace_unmanaged spec(section(".unmanaged"))

It's clear that spec macro is evaluated twice, so no futher replacement is done, let's take it step-by-step:

spec(namespace(unmanaged)) int x; → spec_namespace(unmanaged) int x;
spec_namespace(unmanaged) int x;  → spec_namespace_unmanaged int x;
spec_namespace_unmanaged int x;   → spec(section(".unmanaged")) int x;

What you can do about it is to modify your last macro-defintion into following form:

#define spec_namespace_unmanaged attribute ((namespace (".unmanaged")))

or maybe simplify it as:

#define spec(_H_) spec_##_H_
#define spec_section(_S_) attribute ((section (_S_)))
#define spec_namespace(_N_) attribute ((namespace (_N_)))

with:

spec(namespace(".unmanaged")) int x;

Upvotes: 4

Related Questions