Front page | perl.perl5.porters |
Postings from May 2010
Compiling with clang
Thread Next
From:
hv
Date:
May 6, 2010 09:32
Subject:
Compiling with clang
Message ID:
201005061610.o46GAgXv006446@zen.crypt.org
I tried compiling bleadperl with clang (<http://clang.llvm.org>), which
has nicely picky, verbose error messages.
I fetch clang direct from svn. clang --version initially gave
'clang version 2.0 (trunk 102861)', and later (after (5) below) as
'clang version 2.0 (trunk 103176)'. gccversion comes out as
'GNU cc 4.2.1 Compatible Clang Compiler'.
I configured perl with "./Configure -de -Dcc=/opt/clang-latest/bin/clang
-Dprefix=/opt/blead-clang -Doptimize='-g -O3' -Dusedevel -Uversiononly"
and built with 'make all'.
1. clang does support the flag '-fstack-protector', but the resulting
object doesn't compile: see <http://llvm.org/bugs/show_bug.cgi?id=5094>.
I hacked Configure to avoid specifying this flag. I assume this will be
fixed in clang soon enough, so I haven't tried to make a corable patch.
2. The build fails early complaining about the use of HEK_KEY() within
macros such as GvNAME(), which provides a char[1] where char * is
expected:
gv.c:685:7: error: passing 'char [1]' to parameter of incompatible type 'char const *'
This seems like a reasonable complaint, and I believe that we always intend
to get a char * whenever we call HEK_KEY(). The patch to hv.h below avoids
that; this is the only fatal error caused by perl source when compiling.
3. The warnings in core fall into a small number of classes. I'm not sure how
far we want to go to shut these up:
3a. expression result unused (118 times)
35 SvUPGRADE(); 44 SvGROW(); 16 SvPV_force_*() variants; 6 CHECKOP();
4 SvNV(); 4 SvIV(); 2 my_snprintf(); 2 SvREFCNT_inc(); 2 LINKLIST();
2 GvAVn(); 1 ReREFCNT_inc().
While I think there is some value to be gained to be clean of this warning,
I do not think it outweighs the maintenance cost of getting and staying
clean. I suggest rather that we specify '-Wno-unused-value' by default when
the compiler is clang.
I include a patch to cflags.SH to achieve that for core; I hope some more
shell- and portability-aware porter will cast an eye over that. I'm not
sure how to fix this for extensions.
3b. result of comparison against a string literal is unspecified (36 times)
These are precisely the 36 calls to LEAVE_with_name(). I'm not at all sure
the way we do {ENTER,LEAVE}_with_name is portable, but I'm not sure what
to do about it.
3c. comparison of 0 <= unsigned expression is always true (6 times)
These are inside the FIT_ARENA() macro, and can be ignored: in the case
where the LHS would be zero, the relevant expression cannot be reached.
See <http://llvm.org/bugs/show_bug.cgi?id=7071>.
3d. comparison of integers of different signs (4 times)
We should fix these:
dump.c:279:21: warning: comparison of integers of different signs: 'U8 const' (aka 'unsigned char const') and 'char const' [-Wsign-compare]
dump.c:279:34: warning: comparison of integers of different signs: 'U8 const' (aka 'unsigned char const') and 'char const' [-Wsign-compare]
dump.c:284:22: warning: comparison of integers of different signs: 'U8 const' (aka 'unsigned char const') and 'char const' [-Wsign-compare]
Patch to dump.c below.
perlio.c:5325:21: warning: comparison of integers of different signs: 'size_t' (aka 'unsigned int') and 'int' [-Wsign-compare]
const int val = my_vsnprintf(s, n > 0 ? n : 0, fmt, ap);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from perlio.c:59:
./perl.h:1641:133: note: instantiated from:
# define my_vsnprintf(buffer, len, ...) ({ int __len__ = vsnprintf(buffer, len, __VA_ARGS__); if ((len) > 0 && (Size_t)__len__ >= (len)) Perl_croak_nocontext("panic: vsnprintf buffer overflow"); __len__; })
~~~~~~~~~~~~~~~ ^ ~~~~~
I think this just needs a cast on the (len), in both variants of the macro,
as per the patch to perl.h below.
4. clang then crashed compiling ext/Dynaloader/Dynaloader.c, so I tried
a 'make minitest'.
This had a lot of failures for "can't find <module>", mostly File::Spec
and File::Spec::Functions, but also examples of IO::File, Cwd and POSIX.
Is that supposed to happen, or are core tests supposed to be avoiding
such modules? The documentation of minitest is somewhat sparse, and I
don't know if it is bitrotted or working as intended.
5. The crashing code (see <http://llvm.org/bugs/show_bug.cgi?id=7054>)
resolves to:
#define _FILE_OFFSET_BITS 64
#define _GNU_SOURCE
#include <sys/stat.h>
The clang developers have fixed this not to crash, and eventually I
realised I need gcc's fixed include files to avoid the problem.
So I added another Configure option:
-Accflags=-I/opt/gcc-4.5.0/lib/gcc/i686-pc-linux-gnu/4.5.0/include-fixed
This allowed a complete build, and:
All tests successful.
u=6.99 s=1.40 cu=643.38 cs=50.41 scripts=1701 tests=349409
zen% ./perl -Ilib -V
Summary of my perl5 (revision 5 version 13 subversion 0 patch v5.13.0-167-g89abef2) configuration:
Snapshot of: 89abef211f482f5f37aeb9b02c71c4452feb5c34
Platform:
osname=linux, osvers=2.6.24.7-3, archname=i686-linux
uname='linux zen.crypt.org 2.6.24.7-3 #1 smp sat jan 30 13:21:44 gmt 2010 i686 i686 i386 gnulinux '
config_args='-de -Dcc=/opt/clang-latest/bin/clang -Dprefix=/opt/blead-clang -Doptimize=-g -O3 -Accflags=-I/opt/gcc-4.5.0/lib/gcc/i686-pc-linux-gnu/4.5.0/include-fixed -Dusedevel -Uversiononly'
hint=recommended, useposix=true, d_sigaction=define
useithreads=undef, usemultiplicity=undef
useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
use64bitint=undef, use64bitall=undef, uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler:
cc='/opt/clang-latest/bin/clang', ccflags ='-I/opt/gcc-4.5.0/lib/gcc/i686-pc-linux-gnu/4.5.0/include-fixed -DDEBUGGING -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
optimize='-g -O3',
cppflags='-I/opt/gcc-4.5.0/lib/gcc/i686-pc-linux-gnu/4.5.0/include-fixed -DDEBUGGING -fno-strict-aliasing -pipe -I/usr/local/include'
ccversion='', gccversion='4.2.1 Compatible Clang Compiler', gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
alignbytes=4, prototype=define
Linker and Libraries:
ld='/opt/clang-latest/bin/clang', ldflags =' -L/usr/local/lib'
libpth=/usr/local/lib /lib /usr/lib
libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc
perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
libc=/lib/libc-2.5.so, so=so, useshrplib=false, libperl=libperl.a
gnulibc_version='2.5'
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
cccdlflags='-fPIC', lddlflags='-shared -g -O3 -L/usr/local/lib'
Characteristics of this binary (from libperl):
Compile-time options: DEBUGGING PERL_DONT_CREATE_GVSV PERL_MALLOC_WRAP
PERL_USE_DEVEL USE_LARGE_FILES USE_PERLIO
USE_PERL_ATOF
Built under linux
Compiled at May 6 2010 14:50:53
@INC:
lib
/opt/blead-clang/lib/perl5/site_perl/5.13.0/i686-linux
/opt/blead-clang/lib/perl5/site_perl/5.13.0
/opt/blead-clang/lib/perl5/5.13.0/i686-linux
/opt/blead-clang/lib/perl5/5.13.0
.
zen%
6. In extensions, there are a further 97 warnings.
6a. expression result unused (79 times)
As before, except I'm not sure how to get -Wno-unused-value into the
flags for extensions to suppress these.
6b. passing <X> to parameter of type <Y> converts between pointers to <Z>
types with different sign (6 times)
These should probably be fixed. I haven't looked at them yet:
MD5.xs:709:20: warning: passing 'unsigned char *' to parameter of type 'char const *' converts between pointers to integer types with different sign [-Wpointer-sign]
encengine.c:136:54: warning: passing 'U8 *' to parameter of type 'char const *' converts between pointers to integer types with different sign [-Wpointer-sign]
encengine.c:136:54: warning: passing 'U8 const *' to parameter of type 'char const *' converts between pointers to integer types with different sign [-Wpointer-sign]
Storable.xs:5709:13: warning: passing 'unsigned char [259]' to parameter of type 'char const *' converts between pointers to integer types with different sign [-Wpointer-sign]
Storable.xs:5720:17: warning: passing 'unsigned char [259]' to parameter of type 'char const *' converts between pointers to integer types with different sign [-Wpointer-sign]
Storable.xs:5825:51: warning: passing 'unsigned char [259]' to parameter of type 'char const *' converts between pointers to integer types with different sign [-Wpointer-sign]
6c. using the result of an assignment as a condition without parentheses (7
times)
These are all in ext/Hash-Util-FieldHash/FieldHash.xs. It would vaguely be
nice to be able to catch new occurrences of this. Not sure if that's win
enough to justify the mild effort of fixing the existing ones. Can be
suppressed, I think, with -Wno-parentheses.
6d. null passed to a callee which requires a non-null argument (3 times)
This is the same issue as 3c above: there is a null test before the code
complained about, so it can't be reached.
6e. passing 'char const *' to parameter of type 'char *' discards qualifiers
(1 time)
This is because ext/SDBM_File/sdbm/sdbm.h declares a proto for memcmp()
rather than getting it from my headers:
extern int memcmp proto((char*, char*, int));
I'm not sure if there's any good reason for it not to declare that as
extern int memcmp proto((const char*, const char*, int));
instead.
6f. 'Perl_ptr_table_clear' is deprecated (1 time)
APItest.c:1171:2: warning: 'Perl_ptr_table_clear' is deprecated [-Wdeprecated-declarations]
ptr_table_clear(table);
^
In file included from APItest.xs:3:
In file included from ../../perl.h:954:
../../embed.h:1189:26: note: instantiated from:
#define ptr_table_clear Perl_ptr_table_clear
I have no idea what that one means, or whether it needs fixing.
Hugo
--- hv.h.old 2010-02-20 14:39:09.000000000 +0000
+++ hv.h 2010-05-05 14:31:38.000000000 +0100
@@ -343,7 +343,7 @@
#define HEK_BASESIZE STRUCT_OFFSET(HEK, hek_key[0])
#define HEK_HASH(hek) (hek)->hek_hash
#define HEK_LEN(hek) (hek)->hek_len
-#define HEK_KEY(hek) (hek)->hek_key
+#define HEK_KEY(hek) ((char *)(hek)->hek_key)
#define HEK_FLAGS(hek) (*((unsigned char *)(HEK_KEY(hek))+HEK_LEN(hek)+1))
#define HVhek_UTF8 0x01 /* Key is utf8 encoded. */
--- cflags.SH.old 2009-11-19 16:51:33.000000000 +0000
+++ cflags.SH 2010-05-06 12:06:30.000000000 +0100
@@ -355,6 +355,13 @@
;;
esac
+ case "$cc" in
+ *clang*)
+ # Clang <http://clang.llvm.org/> gives too many warnings without this.
+ warn="$warn -Wno-unused-value"
+ ;;
+ esac
+
: Can we perhaps use $ansi2knr here
echo "$cc -c -DPERL_CORE $ccflags $stdflags $optimize $warn $extra"
--- dump.c.old 2010-04-23 15:49:09.000000000 +0100
+++ dump.c 2010-05-06 11:06:04.000000000 +0100
@@ -241,8 +241,8 @@
const STRLEN count, const STRLEN max,
STRLEN * const escaped, const U32 flags )
{
- const char esc = (flags & PERL_PV_ESCAPE_RE) ? '%' : '\\';
- const char dq = (flags & PERL_PV_ESCAPE_QUOTE) ? '"' : esc;
+ const U8 esc = (flags & PERL_PV_ESCAPE_RE) ? '%' : '\\';
+ const U8 dq = (flags & PERL_PV_ESCAPE_QUOTE) ? '"' : esc;
char octbuf[PV_ESCAPE_OCTBUFSIZE] = "%123456789ABCDF";
STRLEN wrote = 0; /* chars written so far */
STRLEN chsize = 0; /* size of data to be written */
--- perl.h.old 2010-05-01 17:01:11.000000000 +0100
+++ perl.h 2010-05-06 11:47:43.000000000 +0100
@@ -1626,7 +1626,7 @@
#if defined(HAS_SNPRINTF) && defined(HAS_C99_VARIADIC_MACROS) && !(defined(DEBUGGING) && !defined(PERL_USE_GCC_BRACE_GROUPS)) && !defined(PERL_GCC_PEDANTIC)
# ifdef PERL_USE_GCC_BRACE_GROUPS
-# define my_snprintf(buffer, len, ...) ({ int __len__ = snprintf(buffer, len, __VA_ARGS__); if ((len) > 0 && (Size_t)__len__ >= (len)) Perl_croak_nocontext("panic: snprintf buffer overflow"); __len__; })
+# define my_snprintf(buffer, len, ...) ({ int __len__ = snprintf(buffer, len, __VA_ARGS__); if ((len) > 0 && (Size_t)__len__ >= (Size_t)(len)) Perl_croak_nocontext("panic: snprintf buffer overflow"); __len__; })
# define PERL_MY_SNPRINTF_GUARDED
# else
# define my_snprintf(buffer, len, ...) snprintf(buffer, len, __VA_ARGS__)
@@ -1638,7 +1638,7 @@
#if defined(HAS_VSNPRINTF) && defined(HAS_C99_VARIADIC_MACROS) && !(defined(DEBUGGING) && !defined(PERL_USE_GCC_BRACE_GROUPS)) && !defined(PERL_GCC_PEDANTIC)
# ifdef PERL_USE_GCC_BRACE_GROUPS
-# define my_vsnprintf(buffer, len, ...) ({ int __len__ = vsnprintf(buffer, len, __VA_ARGS__); if ((len) > 0 && (Size_t)__len__ >= (len)) Perl_croak_nocontext("panic: vsnprintf buffer overflow"); __len__; })
+# define my_vsnprintf(buffer, len, ...) ({ int __len__ = vsnprintf(buffer, len, __VA_ARGS__); if ((len) > 0 && (Size_t)__len__ >= (Size_t)(len)) Perl_croak_nocontext("panic: vsnprintf buffer overflow"); __len__; })
# define PERL_MY_VSNPRINTF_GUARDED
# else
# define my_vsnprintf(buffer, len, ...) vsnprintf(buffer, len, __VA_ARGS__)
Thread Next
-
Compiling with clang
by hv