When ## concatenation produces a function-like macro name but the argument list (...) is not immediately adjacent in the replacement text (hidden behind a secondary macro parameter), simplecpp aborts expansion and emits the concatenated token bare.
Reproducer
#define PAR(a, ...) a __VA_ARGS__
#define PREFIX_SCALAR(T, N) T N
#define DISPATCH(kind, ...) PAR(PREFIX_ ## kind, (__VA_ARGS__))
DISPATCH(SCALAR, int, x)
Expected:
Actual:
1:
2:
3:
4: PREFIX_SCALAR ( int , x )
Root cause
expandHashHash() checks only B->next->op == '(' immediately after the ## result. In the PAR pattern, B->next is , (not (), so the function-like expansion is skipped.
Fix
A forward-scan fallback in the appendTokens context (expandResult==false) walks ahead on the same line, skipping , separators and resolving named parameter tokens via expandArg(), until ( is found.
PR attached: #655
When
##concatenation produces a function-like macro name but the argument list(...)is not immediately adjacent in the replacement text (hidden behind a secondary macro parameter), simplecpp aborts expansion and emits the concatenated token bare.Reproducer
Expected:
Actual:
Root cause
expandHashHash()checks onlyB->next->op == '('immediately after the##result. In the PAR pattern,B->nextis,(not(), so the function-like expansion is skipped.Fix
A forward-scan fallback in the
appendTokenscontext (expandResult==false) walks ahead on the same line, skipping,separators and resolving named parameter tokens viaexpandArg(), until(is found.PR attached: #655