Bug 1211357 - compile error when using clang.
Summary: compile error when using clang.
Keywords:
Status: CLOSED UPSTREAM
Alias: None
Product: Fedora
Classification: Fedora
Component: elfutils
Version: rawhide
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
Assignee: Mark Wielaard
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2015-04-13 18:01 UTC by yunlian
Modified: 2015-09-04 19:21 UTC (History)
9 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2015-04-17 12:07:08 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description yunlian 2015-04-13 18:01:06 UTC
When I use clang to build elfutils, I got
/build/falco/tmp/portage/dev-libs/elfutils-0.161/work/elfutils-0.161/libelf/elf_begin.c:1054:3: error: function definition is not allowed here
  {
  ^
/build/falco/tmp/portage/dev-libs/elfutils-0.161/work/elfutils-0.161/libelf/elf_begin.c:1086:11: warning: implicit declaration of function 'lock_dup_elf' is invalid in C99 [-Wimplicit-function-declaration]
        retval = lock_dup_elf ();
                 ^
/build/falco/tmp/portage/dev-libs/elfutils-0.161/work/elfutils-0.161/libelf/elf_begin.c:1086:9: warning: incompatible integer to pointer conversion assigning to 'Elf *' (aka 'struct Elf *') from 'int' [-Wint-conversion]
        retval = lock_dup_elf ();
               ^ ~~~~~~~~~~~~~~~
/build/falco/tmp/portage/dev-libs/elfutils-0.161/work/elfutils-0.161/libelf/elf_begin.c:1107:13: warning: incompatible integer to pointer conversion assigning to 'Elf *' (aka 'struct Elf *') from 'int' [-Wint-conversion]
            retval = lock_dup_elf ();
                   ^ ~~~~~~~~~~~~~~~
3 warnings and 1 error generated.
Makefile:934: recipe for target 'elf_begin.os' failed
make[2]: *** [elf_begin.os] Error 1
make[2]: *** Waiting for unfinished jobs....
/build/falco/tmp/portage/dev-libs/elfutils-0.161/work/elfutils-0.161/libelf/elf_getarsym.c:205:15: error: fields must have a constant size: 'variable length array in structure' extension will never be supported
            uint32_t u32[n];
                     ^
/build/falco/tmp/portage/dev-libs/elfutils-0.161/work/elfutils-0.161/libelf/elf_getarsym.c:206:15: error: fields must have a constant size: 'variable length array in structure' extension will never be supported
            uint64_t u64[n];
                     ^
2 errors generated.
Makefile:934: recipe for target 'elf_getarsym.os' failed
make[2]: *** [elf_getarsym.os] Error 1
In file included from /build/falco/tmp/portage/dev-libs/elfutils-0.161/work/elfutils-0.161/libelf/elf64_updatefile.c:30:
/build/falco/tmp/portage/dev-libs/elfutils-0.161/work/elfutils-0.161/libelf/elf32_updatefile.c:297:4: error: function definition is not allowed here
          {
          ^
/build/falco/tmp/portage/dev-libs/elfutils-0.161/work/elfutils-0.161/libelf/elf32_updatefile.c:331:7: warning: implicit declaration of function 'fill_mmap' is invalid in C99 [-Wimplicit-function-declaration]
                    fill_mmap (dl->data.d.d_off);
                    ^
/build/falco/tmp/portage/dev-libs/elfutils-0.161/work/elfutils-0.161/libelf/elf32_updatefile.c:297:4: error: function definition is not allowed here
          {
          ^
/build/falco/tmp/portage/dev-libs/elfutils-0.161/work/elfutils-0.161/libelf/elf32_updatefile.c:331:7: warning: implicit declaration of function 'fill_mmap' is invalid in C99 [-Wimplicit-function-declaration]
                    fill_mmap (dl->data.d.d_off);
                    ^
1 warning and 1 error generated.
Makefile:934: recipe for target 'elf64_updatefile.os' failed
make[2]: *** [elf64_updatefile.os] Error 1
1 warning and 1 error generated.
Makefile:934: recipe for target 'elf32_updatefile.os' failed
make[2]: *** [elf32_updatefile.os] Error 1
make[2]: Leaving directory '/build/falco/tmp/portage/dev-libs/elfutils-0.161/work/elfutils-0.161-.amd64/libelf'
Makefile:464: recipe for target 'all-recursive' failed
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory '/build/falco/tmp/portage/dev-libs/elfutils-0.161/work/elfutils-0.161-.amd64'
Makefile:379: recipe for target 'all' failed
make: *** [all] Error 2

Comment 1 Jakub Jelinek 2015-04-13 18:12:57 UTC
Use a compiler that supports the GNU extensions used by the package then.  elfutils uses GNU nested functions as well as variable length structures, that clang folks didn't bother to implement.

Comment 2 Petr Machata 2015-04-13 21:50:58 UTC
You mean flexible array members?  That's C99, not even GNU extension.  I'm somewhat surprised they are not supported.

Other than that, I don't think it's unreasonable to ask that elfutils sticks to standard language.  But if there are other (standard) features that we use anyway that clang doesn't support, why bother.

Comment 3 Mark Wielaard 2015-04-14 08:36:57 UTC
Yeah, that is nasty. Apparently clang claims to support -std=gnu99, which we explicitly check with a configure check, but doesn't actually implement all language extensions, producing these cryptic error messages.

I proposed a patch upstream to some extra added explicit checks for some of the language extensions I know the code is using (Mixed Declarations and Code https://gcc.gnu.org/onlinedocs/gcc/Mixed-Declarations.html Nested Functions https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html Arrays of Variable Length https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html) to hopefully catch versions of clang which don't support them early.
https://lists.fedorahosted.org/pipermail/elfutils-devel/2015-April/004723.html

Could you see if that catches the issue for you? As soon as clang implements those extensions I think the configure check should pass and everything should build fine.

BTW. I wouldn't mind alternatives that make the code also compile with clang versions that don't implement all these extensions. As long as the code isn't too ugly and the whole code base builds and the testsuite still PASSes. But apparently that is hard because nobody managed to come up with such a patch (some patches were posted in the past, but they all were incomplete and the resulting binaries just didn't work correctly).

Comment 4 Mark Wielaard 2015-04-17 12:07:08 UTC
commit aba6d762ed1f3a9c318ebee20cd08bcd069a3f75
Author: Mark Wielaard <mjw>
Date:   Tue Apr 14 10:18:37 2015 +0200

    configure: Add explicit checks for all GNU99 extensions used.
    
    Some compilers (clang) claim to support -std=gnu99 but don't actually
    implement all extensions we use in the code. Producing really hard to
    parse errors. Add explicit checks for some of the other language
    extensions we use, Nested Functions and Arrays of Variable Length,
    to the configure check to catch such issues early.
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1211357
    
    Signed-off-by: Mark Wielaard <mjw>

Comment 5 Chih-Hung Hsieh 2015-09-03 17:42:40 UTC
I have a patch to compile elfutls with clang/llvm and it passed all elfutils uni
t tests. My tests were on x86 host. My goal is to make elfutils run on Android w
ith clang compiler.

I have not contribute to elfutils before.
Could someone help or show me how to make this patch into elfutils?

The patch contains mainly three kinds of changes:

(1) Add simple type casts or declarations because clang gives more warnings than
 gcc. This should not change output code.

(2) Change some on-stack variable length arrays to fixed length with dynamic all
oca or malloc. I saw a few changes like this already made into the last two vers
ions of elfutls. I used similar patterns to get all compiled with clang.

(3) Nested functions are conditionally changed to clang "Blocks" (closures).
Please see spec at http://clang.llvm.org/docs/BlockLanguageSpec.html.
This should not change output code from gcc.
The change pattern is simple enough to verify and merge like this:

+#include "nested_func.h"   /* get macros __BLOCK and NESTED_FUNC */

 { // body of the enclosing function
-  int nbkpts = 0;
+  __BLOCK int nbkpts = 0;

-  int add_bkpt (Dwarf_Addr pc)
+  NESTED_FUNC(int, add_bkpt, (Dwarf_Addr), (Dwarf_Addr pc))
     {
       // body of the nested function, can update nbkpts
-    }
+    };

Comment 6 Jan Kratochvil 2015-09-03 17:46:23 UTC
Patches should be sent to the mailing list elfutils-devel-at-lists.fedorahosted.org.

Comment 7 Mark Wielaard 2015-09-03 17:55:30 UTC
(In reply to Chih-Hung Hsieh from comment #5)
> I have a patch to compile elfutls with clang/llvm and it passed all elfutils
> unit tests.

Very nice.

> My tests were on x86 host. My goal is to make elfutils run on
> Android w
> ith clang compiler.
> 
> I have not contribute to elfutils before.
> Could someone help or show me how to make this patch into elfutils?

Please see: https://git.fedorahosted.org/cgit/elfutils.git/plain/CONTRIBUTING
 
> The patch contains mainly three kinds of changes:

It is probably best to split the patch up in at least 3 parts in that case.
Then they can be reviewed and tested independently.

> (1) Add simple type casts or declarations because clang gives more warnings
> than
>  gcc. This should not change output code.

That should be fine. Ideally we add any warning flags needed for gcc to give similar warnings so such issues don't creep back in.
 
> (2) Change some on-stack variable length arrays to fixed length with dynamic
> all
> oca or malloc. I saw a few changes like this already made into the last two
> vers
> ions of elfutls. I used similar patterns to get all compiled with clang.

Some of those on-stack variable length arrays could cause unbounded stack usage. So it is often good to fix them.

> (3) Nested functions are conditionally changed to clang "Blocks" (closures).
> Please see spec at http://clang.llvm.org/docs/BlockLanguageSpec.html.
> This should not change output code from gcc.
> The change pattern is simple enough to verify and merge like this:
> 
> +#include "nested_func.h"   /* get macros __BLOCK and NESTED_FUNC */
> 
>  { // body of the enclosing function
> -  int nbkpts = 0;
> +  __BLOCK int nbkpts = 0;
> 
> -  int add_bkpt (Dwarf_Addr pc)
> +  NESTED_FUNC(int, add_bkpt, (Dwarf_Addr), (Dwarf_Addr pc))
>      {
>        // body of the nested function, can update nbkpts
> -    }
> +    };

I must say that I don't think this improves readability of the code.
But please do post on the list and we can discuss if there is a way to make it look a bit nicer.

Comment 8 Chih-Hung Hsieh 2015-09-04 19:21:05 UTC
Thanks for the suggestions.
I have started sending patches to the list.
The first few will be simpler changes and only the last one will change the config files to enable clang compiler.


Note You need to log in before you can comment on or make changes to this bug.