Traversing macro expansion chain

Hi everyone,

I working on a clang-tidy checker that deals with complex macros and needs to get some information related to them.

Take this code example: (IRL the names don't follow any pattern)
01 void do(int x) {}
03 #define MACRO_WITH_ARG_1(x) do(x)
04 #define MACRO_WITH_ARG_2(x) MACRO_WITH_ARG_1(x)
05 #define MACRO_WITH_ARG_3(x) MACRO_WITH_ARG_2(x)
06 #define MACRO_WITH_ARG_4(x) MACRO_WITH_ARG_3(x)
08 #define NUMBER_1 42
09 #define NUMBER_2 NUMBER_1
10 #define NUMBER_3 NUMBER_2
13 #define MACRO_2 MACRO_1
15 void func() {
16 MACRO_2;
17 }

What I have:
--final ExpansionLoc of `do(x)` --> line: 16
--SpellingLoc of `do(x)` --> line: 3
--final ExpansionLoc of `42` --> line: 16
--SpellingLoc of `42` --> line: 8

The length of the branches are unknown and independent, even 0 is possible.
The argument of MACRO_WITH_ARG_n doesn't necessarily consist only of NUMBER_n, e.g.: MACRO_WITH_ARG_4(NUMBER_3 + 1).

What I need:
--the name of the macro (if any) directly expanded into MACRO_1 as MACRO_WITH_ARG_n's argument --> NUMBER_3 in this case
--the name of the macro (if any) directly expanded into MACRO_1 from the MACRO_WITH_ARG_n branch --> MACRO_WITH_ARG_4 in this case
--in general a way to
-----step backward and forward on the expansion chain
-----detect the end of the chain
-----get the name of the macro definition Loc currently pointing into (not necessarily to the beginning)
-----decide whether LocA and LocB are in the same macro definition

What I tried:
--Using getImmediateMacroCallerLoc(): In theory it moves the Loc from the macro definition towards the final expansion location exactly by one expansion. It only goes one way but the results could be stored.
For me, the SpellingLoc iterated through the expansions but there were duplicates. This makes the identification of the segment of the expansion chain - where the expansions of `42` and `do(x)` go along - hard.
--Many combinations of SourceManager's getXxxxxxxxLoc()
--Lexer::getImmediateMacroName(): It gives the name of the macro where the spelling of the macro body (MACRO_WITH_ARG_1 in the example) is but didn't work with the argument.

I saw in the code of getImmediateMacroCallerLoc() that the arguments are handled differently than the bodies. Is this because they are expanded differently (I mean order, place, ...)?

Thanks in advance!

Szabolcs Sipos