cpphs: can't be used to build GHC 7.10.3. Bug?

Hi Malcolm: cpphs is under consideration as a replacement for GCC's C preprocessor in the GHC toolchain: https://ghc.haskell.org/trac/ghc/wiki/Proposal/NativeCpp 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: https://gist.github.com/AlainODea/bd5b3e0e6f7c4227f009 Is this a bug? Best, Alain

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-behavio...
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
Hi Malcolm:
cpphs is under consideration as a replacement for GCC's C preprocessor in the GHC toolchain: https://ghc.haskell.org/trac/ghc/wiki/Proposal/NativeCpp
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: https://gist.github.com/AlainODea/bd5b3e0e6f7c4227f009
Is this a bug?
Best, Alain

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
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-behavio...
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
wrote: Hi Malcolm:
cpphs is under consideration as a replacement for GCC's C preprocessor in the GHC toolchain: https://ghc.haskell.org/trac/ghc/wiki/Proposal/NativeCpp
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: https://gist.github.com/AlainODea/bd5b3e0e6f7c4227f009
Is this a bug?
Best, Alain

Thanks for the bug report, and for the detailed analysis. I will try to look at and fix this soon. Regards, Malcolm On 10 Jan 2016, at 20:09, Alain O'Dea wrote:
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
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-behavio...
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
wrote: Hi Malcolm: cpphs is under consideration as a replacement for GCC's C preprocessor in the GHC toolchain: https://ghc.haskell.org/trac/ghc/wiki/Proposal/NativeCpp
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: https://gist.github.com/AlainODea/bd5b3e0e6f7c4227f009
Is this a bug?
Best, Alain

No worries. Thank you Malcolm. If there's anything else I can gather to
facilitate the fix let me know.
On Sun, Jan 10, 2016 at 5:40 PM Malcolm Wallace
Thanks for the bug report, and for the detailed analysis. I will try to look at and fix this soon.
Regards, Malcolm
On 10 Jan 2016, at 20:09, Alain O'Dea wrote:
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
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-behavio...
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
Hi Malcolm:
cpphs is under consideration as a replacement for GCC's C preprocessor in the GHC toolchain: https://ghc.haskell.org/trac/ghc/wiki/Proposal/NativeCpp
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
wrote: that include from the cpphs flags leads to a clean preprocessing run.
I have more details of this investigation here: https://gist.github.com/AlainODea/bd5b3e0e6f7c4227f009
Is this a bug?
Best, Alain
participants (2)
-
Alain O'Dea
-
Malcolm Wallace