◐ Shell
clean mode source ↗

expandHashHash(): function-like macro not expanded when '(' is not adjacent (PAR-style indirection)

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