* [Bug c++/97771] gcc/g++ failed to generate proper .init_array entries for local scope function, should create "axG", .init_array comdat
2020-11-10 4:55 [Bug c++/97771] New: gcc/g++ failed to generate proper .init_array entries for local scope function, should create "axG", .init_array comdat erstrauss at gmail dot com
@ 2020-11-10 8:16 ` rguenth at gcc dot gnu.org
2020-11-10 13:27 ` erstrauss at gmail dot com
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: rguenth at gcc dot gnu.org @ 2020-11-10 8:16 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97771
Richard Biener <rguenth at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Keywords| |wrong-code
--- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> ---
I think the GCC "portable" way of doing this is to attach the constructor
attribute to Local::init.
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/97771] gcc/g++ failed to generate proper .init_array entries for local scope function, should create "axG", .init_array comdat
2020-11-10 4:55 [Bug c++/97771] New: gcc/g++ failed to generate proper .init_array entries for local scope function, should create "axG", .init_array comdat erstrauss at gmail dot com
2020-11-10 8:16 ` [Bug c++/97771] " rguenth at gcc dot gnu.org
@ 2020-11-10 13:27 ` erstrauss at gmail dot com
2020-11-10 14:31 ` jakub at gcc dot gnu.org
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: erstrauss at gmail dot com @ 2020-11-10 13:27 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97771
--- Comment #2 from Erez Strauss <erstrauss at gmail dot com> ---
Thanks, I tried, it fails with:
$ g++ -O2 -std=c++20 init_array5c.cpp -o init_array5c
init_array5c.cpp: In function ‘void localFunc(const char*)’:
init_array5c.cpp:17:55: warning: ‘constructor’ attribute ignored [-Wattributes]
17 | static void init() __attribute__((constructor))
| ^
===========================
$ ./init_array5c
main() started
post-main-start: X1 init_array5c.cpp 37 &count: 0x4041d4 count: 1 void
localFunc(const char*) [with const
std::experimental::fundamentals_v2::source_location& X = s]
post-main-start: X2 init_array5c.cpp 38 &count: 0x4041dc count: 1 void
localFunc(const char*) [with const
std::experimental::fundamentals_v2::source_location& X = s]
===========================
clang++ accepts correctly the attribute:
$ clang++ -O2 -std=c++20 init_array5c.cpp -o init_array5c
===========================
$ ./init_array5c
pre-main-start init from localFunc: init_array5c.cpp 37 &count: 0x4041d8 count:
1 okFunc1 / static void localFunc(const char *)::Local::init()
pre-main-start init from localFunc: init_array5c.cpp 38 &count: 0x4041dc count:
1 okFunc2 / static void localFunc(const char *)::Local::init()
main() started
post-main-start: X1 init_array5c.cpp 37 &count: 0x4041d8 count: 2 void
localFunc(const char *) [X = s]
post-main-start: X2 init_array5c.cpp 38 &count: 0x4041dc count: 2 void
localFunc(const char *) [X = s]
===========================
$ cat init_array5c.cpp
#include <experimental/source_location>
#include <iostream>
using namespace std::experimental;
template<const source_location& X>
void localFunc(const char* name)
{
static int count{0};
volatile ::std::ios_base::Init dummy{};
std::cout << "post-main-start: " << name << " " << X.file_name() << " " <<
X.line()
<< " &count: " << (void*)&count << " count: " << (++count) << " "
<< __PRETTY_FUNCTION__ << std::endl;
struct Local
{
static void init() __attribute__((constructor))
{
volatile ::std::ios_base::Init dummy{};
std::cout << "pre-main-start init from localFunc: " <<
X.file_name() << " "
<< X.line() << " &count: " << (void*)&count
<< " count: " << (++count) << " " << X.function_name() <<
" / " << __PRETTY_FUNCTION__
<< std::endl;
}
};
//static void* volatile initp __attribute__((__used__,
section(".init_array"))){(void*)&Local::init};
}
#define LOCAL_FUNC(NAME) \
do \
{ \
constexpr static auto s = source_location::current(); \
localFunc<s>((const char*)&(NAME)[0]); \
} while (0)
void okFunc1() { LOCAL_FUNC("X1"); }
inline void okFunc2() { LOCAL_FUNC("X2"); }
int main()
{
std::cout << "main() started" << std::endl;
okFunc1();
okFunc2();
return 0;
}
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/97771] gcc/g++ failed to generate proper .init_array entries for local scope function, should create "axG", .init_array comdat
2020-11-10 4:55 [Bug c++/97771] New: gcc/g++ failed to generate proper .init_array entries for local scope function, should create "axG", .init_array comdat erstrauss at gmail dot com
2020-11-10 8:16 ` [Bug c++/97771] " rguenth at gcc dot gnu.org
2020-11-10 13:27 ` erstrauss at gmail dot com
@ 2020-11-10 14:31 ` jakub at gcc dot gnu.org
2020-11-10 14:43 ` jakub at gcc dot gnu.org
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-11-10 14:31 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97771
Jakub Jelinek <jakub at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |jakub at gcc dot gnu.org
--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
What you are doing is certainly wrong. .init_array section needs to be
@init_array,
there is no way to create initialized variables in anything but @progbits.
The section attribute doesn't have any list of magic sections that should be
treated differently from anything else.
constructor attribute indeed is only allowed on file-scope functions.
Why don't you use inline asm?
I'd suggest
__asm (".section .init_array, \"aw\",%%init_array; .balign %P0;
.%P0byte %P1; .previous" : : "i" (sizeof (void *)), "g" ((void
*)&Local::init));
instead of your initp declaration.
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/97771] gcc/g++ failed to generate proper .init_array entries for local scope function, should create "axG", .init_array comdat
2020-11-10 4:55 [Bug c++/97771] New: gcc/g++ failed to generate proper .init_array entries for local scope function, should create "axG", .init_array comdat erstrauss at gmail dot com
` (2 preceding siblings ...)
2020-11-10 14:31 ` jakub at gcc dot gnu.org
@ 2020-11-10 14:43 ` jakub at gcc dot gnu.org
2020-11-11 2:29 ` erstrauss at gmail dot com
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-11-10 14:43 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97771
Jakub Jelinek <jakub at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |jason at gcc dot gnu.org
--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
That is about the assembler warning (which isn't fatal though); for the uses in
inline functions or templates anothing thing is that the comdat sections from
comdat take priority over the section attribute.
Now, when assembler doesn't support comdat groups, there is really no way
around it, section attribute has to be ignored and one needs to use
.gnu.linkonce.* etc. sections, because otherwise it wouldn't act as comdat.
With comdat groups, we could use the section name from the section attribute
and just put it into the comdat group, but don't do that.
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/97771] gcc/g++ failed to generate proper .init_array entries for local scope function, should create "axG", .init_array comdat
2020-11-10 4:55 [Bug c++/97771] New: gcc/g++ failed to generate proper .init_array entries for local scope function, should create "axG", .init_array comdat erstrauss at gmail dot com
` (3 preceding siblings ...)
2020-11-10 14:43 ` jakub at gcc dot gnu.org
@ 2020-11-11 2:29 ` erstrauss at gmail dot com
2021-08-17 7:47 ` pinskia at gcc dot gnu.org
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: erstrauss at gmail dot com @ 2020-11-11 2:29 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97771
--- Comment #5 from Erez Strauss <erstrauss at gmail dot com> ---
Yes, thanks, the asm() works - but if it can be expressed in C++, why add the
dependency on assembly?
1. attribute constructor - fails to compile
2. placing the address into the .init_array fails to generate the proper code.
3. assembly is required for gcc, but not for clang.
I minimized the program by avoiding any include files, having three different
macros for the different options.
I would expect that gcc will handle correctly the first two options, as other
compilers do.
See https://godbolt.org/z/Mr1794 - for the three compilers: gcc clang icc
========================================
$ cat init_array_minimized.cpp
extern "C" int write(int, const char *, long);
extern "C" unsigned long strlen(const char *);
extern "C" int snprintf(char *, unsigned long, const char *, ...);
#define SIMPLE_LOCAL_FUNC_INIT_ARRAY()
\
do
\
{
\
struct Local
\
{
\
static void init()
\
{
\
char buffer[256];
\
snprintf(buffer, sizeof(buffer), "%p: %s:%d: %s\n",
(void*)&init, __FILE__, __LINE__, \
__PRETTY_FUNCTION__);
\
write(1, buffer, strlen(buffer));
\
}
\
};
\
static void *volatile initp __attribute__((__used__,
section(".init_array"))){(void *)&Local::init}; \
} while (0)
#define SIMPLE_LOCAL_FUNC_CONSTRUCTOR()
\
do
\
{
\
struct Local
\
{
\
static void init() __attribute__((constructor))
\
{
\
char buffer[256];
\
snprintf(buffer, sizeof(buffer), "%p: %s:%d: %s\n",
(void*)&init, __FILE__, __LINE__, \
__PRETTY_FUNCTION__);
\
write(1, buffer, strlen(buffer));
\
}
\
};
\
} while (0)
#define SIMPLE_LOCAL_FUNC_INIT_ASM()
\
do
\
{
\
struct Local
\
{
\
static void init()
\
{
\
char buffer[256];
\
snprintf(buffer, sizeof(buffer), "%p: %s:%d: %s\n",
(void*)&init, __FILE__, __LINE__, \
__PRETTY_FUNCTION__);
\
write(1, buffer, strlen(buffer));
\
}
\
};
\
__asm (".section .init_array, \"aw\",%%init_array; .balign %P0; .%P0byte %P1;
.previous" : : "i" (sizeof (void *)), "g" ((void*)&Local::init)); \
} while (0)
//#define LOCAL_INIT_FUNC() SIMPLE_LOCAL_FUNC_INIT_ARRAY()
//#define LOCAL_INIT_FUNC() SIMPLE_LOCAL_FUNC_CONSTRUCTOR()
#define LOCAL_INIT_FUNC() SIMPLE_LOCAL_FUNC_INIT_ASM()
void funcA() {
LOCAL_INIT_FUNC();
LOCAL_INIT_FUNC();
}
inline void funcB() { LOCAL_INIT_FUNC(); }
template<int> void funcT(int) { LOCAL_INIT_FUNC(); }
int main()
{
write(1, "main\n", 5);
funcA();
funcB();
funcT<0>(0);
funcT<1>(0);
return 0;
}
==================================
$ g++ -std=c++20 -O2 -fverbose-asm --save-temps -o init_array_minimized
init_array_minimized.cpp
$ ./init_array_minimized
0x4011e0: init_array_minimized.cpp:63: static void funcA()::Local::init()
0x401180: init_array_minimized.cpp:64: static void funcA()::Local::init()
0x401250: init_array_minimized.cpp:67: static void funcB()::Local::init()
0x4012b0: init_array_minimized.cpp:69: static void funcT(int)::Local::init()
[with int <anonymous> = 0]
0x401310: init_array_minimized.cpp:69: static void funcT(int)::Local::init()
[with int <anonymous> = 1]
main
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/97771] gcc/g++ failed to generate proper .init_array entries for local scope function, should create "axG", .init_array comdat
2020-11-10 4:55 [Bug c++/97771] New: gcc/g++ failed to generate proper .init_array entries for local scope function, should create "axG", .init_array comdat erstrauss at gmail dot com
` (4 preceding siblings ...)
2020-11-11 2:29 ` erstrauss at gmail dot com
@ 2021-08-17 7:47 ` pinskia at gcc dot gnu.org
2021-08-29 2:45 ` erstrauss at gmail dot com
2021-08-29 3:12 ` pinskia at gcc dot gnu.org
7 siblings, 0 replies; 9+ messages in thread
From: pinskia at gcc dot gnu.org @ 2021-08-17 7:47 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97771
Andrew Pinski <pinskia at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|UNCONFIRMED |RESOLVED
Resolution|--- |DUPLICATE
--- Comment #6 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Dup of bug 88061. Though I suspect both PR 88061 and PR 70435 are invalid.
*** This bug has been marked as a duplicate of bug 88061 ***
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/97771] gcc/g++ failed to generate proper .init_array entries for local scope function, should create "axG", .init_array comdat
2020-11-10 4:55 [Bug c++/97771] New: gcc/g++ failed to generate proper .init_array entries for local scope function, should create "axG", .init_array comdat erstrauss at gmail dot com
` (5 preceding siblings ...)
2021-08-17 7:47 ` pinskia at gcc dot gnu.org
@ 2021-08-29 2:45 ` erstrauss at gmail dot com
2021-08-29 3:12 ` pinskia at gcc dot gnu.org
7 siblings, 0 replies; 9+ messages in thread
From: erstrauss at gmail dot com @ 2021-08-29 2:45 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97771
--- Comment #7 from Erez Strauss <erstrauss at gmail dot com> ---
Hi Andrew,
Here is a very simple test program, under clang++ its output is 3, as expected.
Its output is 2 in case of g++ 11.2.1 20210728 (Red Hat 11.2.1-1)
#include <iostream>
static int X;
typedef void (*funcP)();
static funcP g_init_func [[gnu::used, gnu::section(".init_array")]] {
[]()->void{++X;} };
void funcA() {
static funcP init_func [[gnu::used, gnu::section(".init_array")]] {
[]()->void{++X;} };
}
template<typename T>
void funcB() {
static funcP init_func [[gnu::used, gnu::section(".init_array")]] {
[]()->void{++X;} };
}
void testT() {
funcB<int>();
}
int main()
{
std::cout << X << std::endl;
testT();
return 0;
}
Please test the above to generate 3 as output with g++.
Thanks,
Erez
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/97771] gcc/g++ failed to generate proper .init_array entries for local scope function, should create "axG", .init_array comdat
2020-11-10 4:55 [Bug c++/97771] New: gcc/g++ failed to generate proper .init_array entries for local scope function, should create "axG", .init_array comdat erstrauss at gmail dot com
` (6 preceding siblings ...)
2021-08-29 2:45 ` erstrauss at gmail dot com
@ 2021-08-29 3:12 ` pinskia at gcc dot gnu.org
7 siblings, 0 replies; 9+ messages in thread
From: pinskia at gcc dot gnu.org @ 2021-08-29 3:12 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97771
--- Comment #8 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
(In reply to Erez Strauss from comment #7)
> Hi Andrew,
>
> Here is a very simple test program, under clang++ its output is 3, as
> expected.
Right I already mentioned this is a dup of still opened bug 88061 . The
problem is clang might be emitting really really broken assembly and only can
be resolved at link time.
Take:
template<typename T>
void funcB() {
static funcP init_func [[gnu::used, gnu::section(".init_array")]] {
[]()->void{++X;} };
}
----- CUT -----
funcB<int>::init_func has to be the same between TUs and that means emiting it
in the comdat section. In fact the use of X here might actually cause this
code to be full on invalid anyways.
^ permalink raw reply [flat|nested] 9+ messages in thread