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