This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

why C++ cannot alias an inline function, C can ?


Good day -

I'm trying to understand why this code compiles fine
in  'gcc   -std=gnu11' mode, but not in
     'g++  -std=g++11' mode
(so far tried with gcc/g++ 5.4.0 , 7.3.1 on x86_64 linux) :

'
     static inline __attribute__((always_inline))
     void foo(void){}

     static inline __attribute__((always_inline,alias("foo")))
     void bar(void);

     static
     void f(void) { foo(); }
     // must have a usage to generate any code
 '

In C mode , no problems - I can invoke foo() or bar() to
reference the same inline, and it is always inlined .

In C++ however, it does not compile :

  $ g++ -g -std=gnu++11 -x c++ -c t.c
t.c:5:8: error: 'void bar()' aliased to undefined symbol 'foo'
   void bar(void);
        ^

Even though, if I compile the object with the declaration
of bar() commented out , I can see C++ is not mangling
the name "foo" :

$ objdump -g t.o

t.o:     file format elf64-x86-64

Contents of the .debug_info section:

  Compilation Unit @ offset 0x0:
   Length:        0x4d (32-bit)
   Version:       4
   Abbrev Offset: 0x0
   Pointer Size:  8
 <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <c>   DW_AT_producer    : (indirect string, offset: 0x0): GNU
C++11 5.4.0 -mtune=haswell -march=x86-64 -g -std=gnu++11
    <10>   DW_AT_language    : 4	(C++)
    <11>   DW_AT_name        : t.c
    <15>   DW_AT_comp_dir    : (indirect string, offset: 0x43): /tmp
    <19>   DW_AT_low_pc      : 0x0
    <21>   DW_AT_high_pc     : 0x7
    <29>   DW_AT_stmt_list   : 0x0
 <1><2d>: Abbrev Number: 2 (DW_TAG_subprogram)
    <2e>   DW_AT_name        : foo
    <32>   DW_AT_decl_file   : 1
    <33>   DW_AT_decl_line   : 2
    <34>   DW_AT_inline      : 3	(declared as inline and inlined)
 <1><35>: Abbrev Number: 3 (DW_TAG_subprogram)
    <36>   DW_AT_external    : 1
    <36>   DW_AT_name        : f
    <38>   DW_AT_decl_file   : 1
    <39>   DW_AT_decl_line   : 10
    <3a>   DW_AT_linkage_name: (indirect string, offset: 0x3d): _Z1fv
    <3e>   DW_AT_low_pc      : 0x0
    <46>   DW_AT_high_pc     : 0x7
    <4e>   DW_AT_frame_base  : 1 byte block: 9c 	(DW_OP_call_frame_cfa)
    <50>   DW_AT_GNU_all_call_sites: 1
 <1><50>: Abbrev Number: 0

So there is a symbol "foo" declared, even though it is only a debug symbol .

Why does C++ not let me alias it ?  There appears to be no mangled name
for it .

And even worse, the obvious workaround does not work:

'
    static inline __attribute__((always_inline))
    void foo(void) {}

//  static inline __attribute__((always_inline, alias("foo")))
//  void bar(void);

    static inline __attribute__((always_inline))
    void (&bar)(void) = foo;

   void f(void)
   { bar();
   }
'
Fails to compile with:

t.c:8:19: error: 'bar' declared as an 'inline' variable
   void (&bar)(void) = foo;


So one has to do just
    static
    void (&bar) ( void ) = foo;

So now foo() has lost its inline-ness:

$ nm -C t.o
0000000000000007 T f()
0000000000000000 r bar
0000000000000000 t foo()

ie. the compiler did not warn that foo
has been made into an ordinary symbol:

'
    $ cat t.c
    static inline __attribute__((always_inline))
    void foo(void) {}
    static
    void (&bar)(void) = foo;
    void f(void){ bar();}
    $ g++ -std=gnu++11 -x c++ -Wall -Wextra -c t.c
    $
 '
I think g++ should have warned that it is not treating
an always inline function as inline here !

This problem is causing me grief in more real-world scenarios -
any advice on how to create an alias that is inline-able in C++
would be much appreciated.

Thanks & Best Regards,
Jason


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]