How to do preprocessor/macro refactorings?

Hi,

Suppose I want to do a refactoring that collapses all #if SYMBOL
preprocessor blocks, how would I hook that into clang?

Example:

// somewhere, perhaps in a header file, or coming from compile_commands.json
#define HAVE_LIBEDIT 1
#define USE_NEW_CODE 1
#define USE_BOOST 1

// ... lots of other code

    // preamble code
#if USE_NEW_CODE
    // do the new shiny thing here!
#else
    // do the crusty old thing here!
#endif
    // prologue code
#if USE_NEW_CODE || FORCE_NEW_CODE
    // do the new shiny thing here!
#endif

Apply refactoring "Flatten USE_NEW_CODE preprocessor condition"
yields:

// somewhere, perhaps in a header file, or coming from compile_commands.json
#define HAVE_LIBEDIT 1
#define USE_BOOST 1

// ... lots of other code

    // preamble code
    // do the new shiny thing here!
    // prologue code
#if FORCE_NEW_CODE
    // do the new shiny thing here!
#endif

(Note: I'm not expecting the refactoring tool to modify
compile_commands.json as that is outside the scope of the source code
and within the scope of your build system. Your build system can keep
defining USE_NEW_CODE to 1 without harm.)

This is just one example of a refactoring on source code involving
interaction with preprocessor. Other more mundane examples are:

- renaming macro arguments
- renaming macros
- recognize multi-statement macro bodies and wrapping them in
  do { ... } while (false)

Thoughts?

By the time I get down to AST nodes, how much of a breadcrumb trail
has the processor left behind for me to recognize such constructs things?

Presumably I have to look at things beyond what an AST node matcher
could do.