netbsd & gcc 4.6 triple

I am building Clang 3.0.99 with gcc 4.6. The message below suggests
Triple.cpp is confused. The enumerated type "NetBSD" should be defined
in the enum in Triple.h on line 93. The message says that its value
is 199905, which appears to come from the preprocessor. That string is
used in places like config.guess.

It would be nice if "199905" appeared in a header somewhere, but no.
Any suggestions for how to track it down?

Error message follows. Thanks.

--jkl

llvm[1]: Compiling Triple.cpp for Release build
Triple.cpp: In static member function 'static const char*
llvm::Triple::getOSTypeName(llvm::Triple::OSType)':
Triple.cpp:99:10: warning: enumeration value 'NetBSD' not
  handled in switch [-Wswitch]
Triple.cpp:113:3: warning: case value '199905' not in
  enumerated type 'llvm::Triple::OSType' [-Wswitch]
Triple.cpp: In function 'llvm::Triple::OSType
  parseOS (llvm::StringRef)':
Triple.cpp:282:35: error: expected unqualified-id before
  numeric constant
Triple.cpp:292:1: warning: control reaches end of
  non-void function [-Wreturn-type]
rm: /usr/pkgsrc/wip/clang/work/llvm/lib/Support/Release/Triple.d.tmp:
  No such file or directory
gmake[1]: ***
[/usr/pkgsrc/wip/clang/work/llvm/lib/Support/Release/Triple.o] Error 1
gmake[1]: Leaving directory
`/usr/pkgsrc/wip/clang/work/llvm/lib/Support' gmake: *** [all] Error 1
*** Error code 2

I am building Clang 3.0.99 with gcc 4.6. The message below suggests
Triple.cpp is confused. The enumerated type "NetBSD" should be
defined in the enum in Triple.h on line 93. The message says that
its value is 199905, which appears to come from the preprocessor.
That string is used in places like config.guess.

The preprocessed code confirms the problem:

const char *Triple::getOSTypeName(OSType Kind) {
  switch (Kind) {
  case UnknownOS: return "unknown";

  case AuroraUX: return "auroraux";
  case Cygwin: return "cygwin";
  case Darwin: return "darwin";
  case DragonFly: return "dragonfly";
  case FreeBSD: return "freebsd";
  case IOS: return "ios";
  case KFreeBSD: return "kfreebsd";
  case Linux: return "linux";
  case Lv2: return "lv2";
  case MacOSX: return "macosx";
  case MinGW32: return "mingw32";
  case 199905: return "netbsd";
  case OpenBSD: return "openbsd";
  case Solaris: return "solaris";
  case Win32: return "win32";
  case Haiku: return "haiku";
  case Minix: return "minix";
  case RTEMS: return "rtems";
  case NativeClient: return "nacl";
  case CNK: return "cnk";
  }

  __builtin_unreachable();
}

One other point of information: the value 199905 is fixed in the NetBSD
headers, which include a cautionary note to use "__NetBSD_Version__"
instead of "NetBSD".

--jkl

The real question is where sys/param.h is pulled in.

Joerg

> I am building Clang 3.0.99 with gcc 4.6. The message below suggests
> Triple.cpp is confused. The enumerated type "NetBSD" should be
> defined in the enum in Triple.h on line 93. The message says that
> its value is 199905, which appears to come from the preprocessor.

The real question is where sys/param.h is pulled in.

I'm always delighted to answer real questions! It's being checked in
configure.ac, probably because it's used in some header files, see
below.

But why? If someone could answer that, perhaps we can craft portable
conditional compilation. :slight_smile:

AFAIK sys/param.h is non-standard. opengroup.org mentions it only once
that I see, calling it "traditional":
http://pubs.opengroup.org/onlinepubs/009604599/basedefs/sys/stat.h.html.

clang finds two unwanted preprocessor definitions
in /usr/include/sys/param.h, both defined unconditionally:

  NetBSD
  FSCALE

$ grep -nE '(#define.NetBSD)|FSCALE' /usr/include/sys/param.h
83:#define NetBSD 199905 /* NetBSD version (year &
month). */
373:#define FSCALE (1<<FSHIFT)

Out of sheer orneriness I got it to compile. I sprinkled #undef in
about 6 files, some generated.

Autoconf references:

$ grep sys/param.h *conf* autoconf/*
config.log:| #include <sys/param.h>
config.log:configure:15117: checking sys/param.h usability
config.log:configure:15175: checking sys/param.h presence
config.log:configure:15250: checking for sys/param.h
configure: # See if sys/param.h defines the BYTE_ORDER macro.
configure:#include <sys/param.h>
configure:#include <sys/param.h>
configure:for ac_header in sys/mman.h sys/param.h sys/resource.h
sys/time.h sys/uio.h configure:/* Assume that all systems that can run
configure have sys/param.h. */ configure:# include <sys/param.h>
configure.lineno: # See if sys/param.h defines the BYTE_ORDER macro.
configure.lineno:#include <sys/param.h>
configure.lineno:#include <sys/param.h>
configure.lineno:for ac_header in sys/mman.h sys/param.h sys/resource.h
sys/time.h sys/uio.h configure.lineno:/* Assume that all systems that
can run configure have sys/param.h. */ configure.lineno:# include
<sys/param.h> autoconf/config.guess:#include <sys/param.h>
autoconf/config.guess:# include <sys/param.h>
autoconf/configure.ac:AC_CHECK_HEADERS([sys/mman.h sys/param.h
sys/resource.h sys/time.h sys/uio.h])

References in header files:

$ find work/ -name *.h -exec grep sys/param.h {} + \
  > grep -E '#[[:space:]]*include'
work/llvm/lib/Support/Unix/Unix.h:#include <sys/param.h>
work/.buildlink/gcc46/include/c+
+/x86_64-unknown-netbsd5.0.2/bits/ctype_base.h:#include <sys/param.h>
work/.buildlink/gcc46/lib/gcc/x86_64-unknown-netbsd5.0.2/4.6.3/plugin/include/system.h:#
include <sys/param.h>

--jkl

But you didn't :slight_smile: If you look at the pre-processed code for Triple.cpp,
what is the include path leading to sys/param.h?

Joerg

The attached file was created with

$ cat preprocess.sh
cpp -H \
    -I/usr/pkgsrc/wip/clang/work/llvm/include \
    -I/usr/pkgsrc/wip/clang/work/llvm/lib/Support \
    -DNDEBUG \
    -D_GNU_SOURCE \
    -D__STDC_CONSTANT_MACROS \
    -D__STDC_FORMAT_MACROS \
    -D__STDC_LIMIT_MACROS \
    -I/usr/include \
    -I/usr/pkg/gcc46/include \
    -I/usr/pkg/gcc46/lib/gcc/x86_64-unknown-netbsd5.0.2/4.6.3/include \
    -I/usr/include \
    -I/usr/pkg/gcc46/include \
    -I/usr/pkg/gcc46/lib/gcc/x86_64-unknown-netbsd5.0.2/4.6.3/include \
    Triple.cpp

$ ./preprocess.sh 2>&1 | grep -E '^(# [0-9]+ ")|^\.'

The story starts with llvm/include/llvm/ADT/SmallVector.h. That draws
in many gcc46/include files, one of which is gcc46/include/c+
+//x86_64-unknown-netbsd5.0.2/bits/ctype_base.h, which says:

     26 // ISO C++ 14882: 22.1 Locales
     27 //
     28
     29 // Information as gleaned from /usr/include/ctype.h on NetBSD.
     30 // Full details can be found from the CVS files at:
     31 // anoncvs@anoncvs.netbsd.org:/cvsroot/basesrc/include/ctype.h
     32 // See www.netbsd.org for details of access.
     33
     34 #include <sys/param.h>

That's new btw. The attached diff shows ctype_base.h from base didn't
include sys/params.h.

I hope that answers your specific question. Should we talk to gcc
about it?

It's not enough, though, IMO. configure.ac also looks for
sys/params.h and configure references "NetBSD" where it should use
__NetBSD_Version__ unless, improbably, it seeks to be compatible with
NetBSD 1.4. It's worth considering changing the clang
symbols to be slightly different from NetBSD and FSCALE.

Interested to hear your thoughts. I fetched
http://llvm.org/svn/llvm-project/llvm/trunk this morning. I'll try
building that and, if I bump into the same problem -- if I get that far
-- I'll try patching ctype_base.h.

Regards,

--jkl

Triple.includes (77.9 KB)

ctype_base.h-diff (3.61 KB)

[Second reply, better information.]

I was able to build clang trunk as of today with gcc 4.6 by modifying
one gcc header file. I don't say it's a great solution, but it does
narrow down the problem.

In ctype_base.h, after

  #include <sys/param.h>

I added

  #if DNU_SYS_PARAMS_H
  # ifdef NetBSD
  # undef NetBSD
  # endif
  # ifdef FSCALE
  # undef FSCALE
  # endif
  #endif

(I know, the ifdefs aren't needed.)

For simplicity, I added this guard to Clang's header file:

$ svn diff
Index: include/llvm/ADT/SmallVector.h