This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
why C++ cannot alias an inline function, C can ?
- From: Jason Vas Dias <jason dot vas dot dias at gmail dot com>
- To: gcc at gcc dot gnu dot org
- Date: Sun, 1 Apr 2018 11:34:43 +0000
- Subject: 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