My school of thought would be to limit it to just #include, #if, #else, #end, and non-recursive single word only #define / #undef. Force everything to be 1 per single line, and call it a day.
Macros should always be the absolute last resort to doing anything. Stepping through code in gdb with some "creative" macro-based API is almost as bad as C++.
I've seen 'C' macros used to do template-ey things that probably reinforced the readability of the code ( once you get used to the fact that the macros were there at all ) .
More modern compilers allow using non-static "const" constructs to do much of the same, which is a great improvement.
You'll forgive me if my knowledge is a bit dated. I largely work on tools integration these days and don't do much in the way of framework development but aren't macros pretty much the defacto way of doing reflection/rtti. Actually, almost every mature framework I've worked with in the past used macros to markup class properties, register types, etc.
Macros should always be the absolute last resort to doing anything. Stepping through code in gdb with some "creative" macro-based API is almost as bad as C++.