Got a clear answer about the handling of if defined.

Expanding macros within if defined is non-compliant if cpphs is trying to be a C99 preprocessor:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
6.10.1/1 Conditional Inclusion pg 148 indicates that the token after defined or within defined ( ) is an identifier, not a macro to be expanded.

I'm not sure what's involved in fixing this behavior in cpphs, but I'm happy to test fixes.

On Sun, Jan 10, 2016 at 3:53 PM Alain O'Dea <alain.odea@gmail.com> wrote:
I've isolated the issue to the handling of if defined on multi-argument macros.

I took a crack at interpreting the cpphs source for this and I think it may be a bug in the conversion of defined expressions here in Language.Preprocessor.CppIfdef here:

    convert "defined" [arg] =
      case lookupST arg st of
        Nothing | all isDigit arg    -> return arg 
        Nothing                      -> return "0"
        Just (a@AntiDefined{})       -> return "0"
        Just (a@SymbolReplacement{}) -> return "1"
        Just (a@MacroExpansion{})    -> return "1"

It looks like it will macro expand the contents of a defined expression which isn't what GCC does.  I don't know if GCC is wrong or if using parameterized macros within 

if defined works on single-argument macros.

working1.hs:

    {-# LANGUAGE CPP #-}
    
    #define EXAMPLE_MACRO(arg) (\
                                   arg)
    
    #if defined(EXAMPLE_MACRO)
    #endif

preprocess it (it works!):

    $ cpphs --cpp working1.hs -o $tempfile
    $

ifdef works on multiple-argument macros.

working2.hs:

    {-# LANGUAGE CPP #-}
    
    #define EXAMPLE_MACRO(arg1,arg2) (\
                                   arg1 > arg2)
    
    #ifdef EXAMPLE_MACRO
    #endif

preprocess it (it works!):

    $ cpphs --cpp working2.hs -o $tempfile
    $

if defined fails on multi-argument macros.

broken2.hs:

    {-# LANGUAGE CPP #-}
    
    #define EXAMPLE_MACRO(arg1,arg2) (\
                                   arg1 > arg2)
    
    #if defined(EXAMPLE_MACRO)
    #endif

preprocess it (it fails!):

    $ cpphs --cpp broken2.hs -o $tempfile
    cpphs: macro EXAMPLE_MACRO expected 2 arguments, but was given 0
    $

I've posted a StackOverflow question to see if any of them know if this is undefined behavior:
http://stackoverflow.com/questions/34709769/is-cpphs-wrong-or-is-the-behavior-of-macros-with-arguments-in-if-defined-express

If it is undefined behavior we should stop relying on it in GHC sources.  Either way the behavior is inconsistent with GCC which complicates things.

Best,
Alain

On Sun, Jan 10, 2016 at 2:04 PM Alain O'Dea <alain.odea@gmail.com> wrote:
Hi Malcolm:

cpphs is under consideration as a replacement for GCC's C preprocessor in the GHC toolchain:

GHC 7.10.3's build fails when cpphs is used as the C preprocessor (--with-hs-cpp=cpphs --with-hs-cpp-flags="--cpp").

It runs into this error when preprocessing libraries/base/GHC/Natural.hs:

cpphs: macro MIN_VERSION_integer_gmp expected 3 arguments, but was given 0

I've reproduced this issue on Ubuntu 14.04 x86-64 and SmartOS 15.3.0 x86-64.

Interestingly the error seems to arise only when preprocessing Natural.hs while the autogenerated cabal-macros.h is present.  Removing that include from the cpphs flags leads to a clean preprocessing run.

I have more details of this investigation here:

Is this a bug?

Best,
Alain