[Bug c++/93969] New: Static data member cannot be initialized in place, if it is of a nested class type with a default argument in its constructor.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93969 Bug ID: 93969 Summary: Static data member cannot be initialized in place, if it is of a nested class type with a default argument in its constructor. Product: gcc Version: 9.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: igusarov at mail dot ru Target Milestone: --- Dear gcc developers, x86_64-gcc-9.2 available online at godbolt.org, refuses to compile a sample program which I believe is well-formed: struct Outer { struct Inner { Inner(int arg = 23); }; static inline Inner x{};// (1) }; If invoked with a sole "-std=c++17" command-line option, the compilation fails at line marked (1) and the following error is reported: error: call to 'Outer::Inner::Inner(int)' uses the default argument for parameter 1, which is not yet defined The sample program looks well-formed to me because of the following reasoning: (clause numbers are per N4659 C++17 draft at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf ) 1) Class Outer::Inner is fully defined at its closing brace (12.2/p6) and therefore is already a complete-type before Outer::x data member is declared; 2) The declaration of static inline data member Outer::x comes with a brace-initializer (12.2/p8) which means that it is also the definition (12.2.3.2/p3), also initializing-declaration and defining declaration (11.6/p21); 3) Outer::x is direct-list-initialized (11.6/p16, 11.6/p17); the initializer list is empty; 4) Class Outer::Inner has a user-defined constructor Outer::Inner::Inner(int). That constructor is the default constructor because every formal parameter has a corresponding default argument (15.1/p4); 5) Combination of points 3) and 4) means that Outer::x should be default-initialized (11.6.4/p3.4, 11.6/p8.1); 6) Default initialization of Outer::x should be performed by calling its matching constructor with an empty argument list (11.6/p7.1); 7) Each time the constructor is called with no arguments, default argument should be evaluated for the corresponding parameter (11.3.6/p9); 8) Default argument to that constructor is an integral constant expression which is already defined. So it seems that evaluation of the said default argument should cause no problem. P.S. clang-9.0.0 also reports a similar error.
[Bug target/90622] New: Suboptimal code generated for __builtin_avr_insert_bits
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90622 Bug ID: 90622 Summary: Suboptimal code generated for __builtin_avr_insert_bits Product: gcc Version: 5.4.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: igusarov at mail dot ru Target Milestone: --- Please consider the following function: uint8_t copy_bit_5_to_bit_2(uint8_t dst, uint8_t src) { return __builtin_avr_insert_bits(0xF5FF, src, dst); } That particular map value (magic hex constant) is supposed to copy the 5-th bit from argument 'src' to the 2-nd bit of argument 'dst' while leaving all other bits of src unmodified. In other words, given that bit representation of src is [s7 s6 s5 s4 s3 s2 s1 s0], and bit representation of dst is [d7 d6 d5 d4 d3 d2 d1 d0], it should return [d7 d6 d5 d4 d3 s5 d1 d0]. The code generated for such function is perfect: bst r22,5# Take the 5-th bit of r22 bld r24,2# Put it as the 2-nd bit in r24 Similar code is generated for copying any n-th bit to any m-th bit, provided that n and m are different. Thus far everything is great. However, the code generated for copying n-th bit to n-th bit is surprisingly suboptimal. A similar function uint8_t copy_bit_2_to_bit_2(uint8_t dst, uint8_t src) { return __builtin_avr_insert_bits(0xF2FF, src, dst); } gives: eor r22,r24 andi r22,lo8(4) eor r24,r22 which takes an extra word of program memory and an extra CPU cycle at runtime. I wonder what's wrong with using the same bst/bld idiom which is successfully used for n-to-m copy? I would expect that the following code is much better: bst r22,2 bld r24,2 It would be great if the compiler can generate it.
[Bug target/90616] New: Suboptimal code generated for accessing an aligned array.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90616 Bug ID: 90616 Summary: Suboptimal code generated for accessing an aligned array. Product: gcc Version: 5.4.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: igusarov at mail dot ru Target Milestone: --- Consider the following code: #include uint8_t globalArray[68] __attribute__((aligned(256))); uint8_t foo(uint8_t index) { return globalArray[index]; } avr-gcc-5.4.0 generates the following code for the body of foo(): movr30,r24# r24 is where 'index' argument is stored ldir31,0 subi r30,lo8(-(globalArray)) sbci r31,hi8(-(globalArray)) ld r24,Z which is suboptimal because the lower byte of the address of globalArray is always 0 due to the extended alignment enforced on that object. Would it be possible to generate a better code for such specific indexing? For example, the following snippet takes full advantage of the overalignment: movr30,r24 ldir31,hi8(globalArray) ld r24,Z
[Bug c++/90291] [8/9/10 Regression] Inline namespace erroneously extends another namespace
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90291 --- Comment #12 from Igor A. Goussarov --- Thank you for taking interest and for the efforts, Nathan!
[Bug c++/90291] [8/9/10 Regression] Inline namespace erroneously extends another namespace
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90291 --- Comment #10 from Igor A. Goussarov --- Having reflected on my feelings about the described scenario, I came up with a slightly different wording for my complaints about the behaviour of gcc-8.x: The fact that using an inline namespace at one point in source may alter the interpretation of an unrelated, unaware and otherwise well-defined code at some other point further down the same translation unit looks unsafe. That's dangerous interference right there. Given the following source text: namespace B { namespace A { void foo() {} } } I would expect the compiler to generate B::A::foo() no matter what header files may have been included prior to these lines. BTW, is that core working group forum public? Maybe I'm missing some important reasoning why the behaviour exhibited by gcc 8.x is actually desired? P.S. I'm having days off now; most likely, I'll not be able to reply before May 9.
[Bug c++/90291] [8/9/10 Regression] Inline namespace erroneously extends another namespace
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90291 --- Comment #8 from Igor A. Goussarov --- P.S. It seems that different compilers have different ideas about inline namespaces. If godbolt.org can be trusted, clang-8.0 and msvc 2017 do not merge namespaces in described scenario.
[Bug c++/90291] [8/9/10 Regression] Inline namespace erroneously extends another namespace
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90291 --- Comment #7 from Igor A. Goussarov --- The intent is to have a lot of services, each defined in its dedicated namespace. The hierarchy of those namespaces can grow to arbitrary depth: component component::service_a component::group_b::service_c component::group_b::service_d component::third_party::domain::service_e Each service may have header-only public part and private part. Private part must be placed in namespace `detail` under the namespace of its corresponding service. So we have: component::detail component::service_a::detail component::group_b::service_c::detail component::group_b::service_d::detail component::third_party::domain::service_e::detail Now, if some team decided to put their service in an inline namespace (say, if their service is common enough), the identity of detail namespaces is ruined because they start merging with each other, subject to the order of header files inclusion. And that leads to ODR violation and weird linker errors...
[Bug c++/90291] [8/9/10 Regression] Inline namespace erroneously extends another namespace
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90291 --- Comment #6 from Igor A. Goussarov --- Yes, this is a slightly modified excerpt from real code. Perhaps a less abridged example would make more sense: // Code in logger.h namespace component { inline namespace utility { namespace detail // (1) { // Private implementation details void LogImpl(); } // Facade inline void LogEvent() { detail::LogImpl(); } } } // Code in service.h namespace component { namespace detail// (2) { // Private implementation details void ServiceImpl(); } // Facade inline void DoService() { detail::ServiceImpl(); } } // Code in service_impl.cpp #include "service.h" namespace component { namespace detail { // This defines `component::detail::ServiceImpl()`. void ServiceImpl() { } } } // Code in other_source.cpp #include "logger.h" #include "service.h" // When both headers are included, namespace (2) is // merged with namespace (1), which results in // inline function `component::DoService()` calling // `component::utility::detail::ServiceImpl()` // which obviously isn't defined. // Not to say that ODR for component::DoService() // is violated.
[Bug c++/90291] New: [7/8 Regression] Inline namespace erroneously extends another namespace
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90291 Bug ID: 90291 Summary: [7/8 Regression] Inline namespace erroneously extends another namespace Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: igusarov at mail dot ru Target Milestone: --- Compilation of the following code with gcc 7.x and 8.x produces different results: inline namespace A { inline namesapce B // (1) { void foo() {} } } inline namespace B // (2) { inline namesapce A { void foo() {} } } If compiled with "gcc-7.4 -std=c++11 -c", the object file contains functions A::B::foo() B::A::foo() which I believe is correct. However, if the same source is compiled with "gcc-8.3 -std=c++11 -c", the object file contains functions A::B::foo() A::B::A::foo() which I believe is wrong. It looks like gcc 8.x assumes that the namespace at line (2) doesn't start a new top-level namespace, but extends the namespace defined at line (1).
[Bug rtl-optimization/68086] Expression explicitly defined outside the loop is moved inside the loop by the optimizer
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68086 --- Comment #1 from Igor A. Goussarov --- Created attachment 36579 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=36579=edit Performance test for the problem
[Bug rtl-optimization/68086] New: Expression explicitly defined outside the loop is moved inside the loop by the optimizer
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68086 Bug ID: 68086 Summary: Expression explicitly defined outside the loop is moved inside the loop by the optimizer Product: gcc Version: 5.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: rtl-optimization Assignee: unassigned at gcc dot gnu.org Reporter: igusarov at mail dot ru Target Milestone: --- Created attachment 36578 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=36578=edit Single function to reproduce the results Compileable C source in "ex324_core.c" does not include any header files. It consists of a single function whose performance is spoiled by the optimizer. Please read explanatory comments in that file. "ex324.c" is a compileable test program build around the same core function. It merely measures the amount of CPU clock ticks taken by that core function. It includes system headers for printf and mmap, and is provided just for convenience of testing. The problem was first discovered in x86_64 gcc 5.2.0 compiler. Brief regression research showed that 4.8.3 has this problem too. 4.7.4 seems to be good. Problem in a nutshell. Let's start with this loop: // Case 1 for (i = 0; i < size; ++i) accumulator += data[i]; and rewrite it in this equivalent form: // Case 2 int* rebased = data + size; for (i = -size; i; ++i) accumulator += rebased[i]; It looks like the forward propagation pass decides not to allocate a register for variable 'rebased', but rather compute its value every time it is used in the loop. This results in assembly output which, if written in terms of C, would look like this: for (i = -size; i; ++i) accumulator += *(data + (size + i)); Extra operation inside the loop only slows the program down. This happens at any optimization level above -O0. Command line: x86_64-unknown-freebsd9.0_5.2.0-gcc -O2 -S ex324_core.c Compiler: x86_64-unknown-freebsd9.0_5.2.0-gcc -v Using built-in specs. COLLECT_GCC=x86_64-unknown-freebsd9.0_5.2.0-gcc COLLECT_LTO_WRAPPER=/usr/toolchain/x86_64-unknown-freebsd9.0_5.2.0/libexec/gcc/x86_64-unknown-freebsd9.0/5.2.0/lto-wrapper Target: x86_64-unknown-freebsd9.0 Configured with: /mnt/hdd/usr/home/toolbuilder/build_scripts/x86_64-unknown-freebsd9.0_5.2.0/build_scripts/../tools_build/x86_64-unknown-freebsd9.0_5.2.0/gcc-5.2.0/configure --target=x86_64-unknown-freebsd9.0 --prefix=/usr/toolchain/x86_64-unknown-freebsd9.0_5.2.0 --with-local-prefix=/usr/local --with-sysroot=/usr/toolchain/x86_64-unknown-freebsd9.0_5.2.0/sysroot --program-prefix=x86_64-unknown-freebsd9.0_5.2.0- --with-gnu-as --with-gnu-ld --with-as=/usr/toolchain/x86_64-unknown-freebsd9.0_5.2.0/bin/x86_64-unknown-freebsd9.0_5.2.0-as --with-ld=/usr/toolchain/x86_64-unknown-freebsd9.0_5.2.0/bin/x86_64-unknown-freebsd9.0_5.2.0-ld --with-nm=/usr/toolchain/x86_64-unknown-freebsd9.0_5.2.0/bin/x86_64-unknown-freebsd9.0_5.2.0-nm --with-objdump=/usr/toolchain/x86_64-unknown-freebsd9.0_5.2.0/bin/x86_64-unknown-freebsd9.0_5.2.0-objdump --with-gmp=/mnt/hdd/usr/home/toolbuilder/build_scripts/x86_64-unknown-freebsd9.0_5.2.0/build_scripts/../tools_build/x86_64-unknown-freebsd9.0_5.2.0/gmp-root --with-mpfr=/mnt/hdd/usr/home/toolbuilder/build_scripts/x86_64-unknown-freebsd9.0_5.2.0/build_scripts/../tools_build/x86_64-unknown-freebsd9.0_5.2.0/mpfr-root --with-mpc=/mnt/hdd/usr/home/toolbuilder/build_scripts/x86_64-unknown-freebsd9.0_5.2.0/build_scripts/../tools_build/x86_64-unknown-freebsd9.0_5.2.0/mpc-root --disable-__cxa_atexit --enable-languages=c,c++ --disable-multilib --disable-nls --enable-shared=libstdc++ --enable-static --enable-threads Thread model: posix gcc version 5.2.0 (GCC) Operating system: amd64 FreeBSD 9.0-RELEASE CPU: Intel(R) Core(TM) i7-2700K CPU @ 3.50GHz (3500.10-MHz K8-class CPU) Origin = "GenuineIntel" Id = 0x206a7 Family = 6 Model = 2a Stepping = 7 Features=0xbfebfbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CLFLUSH,DTS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE> Features2=0x179ae3bf<SSE3,PCLMULQDQ,DTES64,MON,DS_CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,POPCNT,TSCDLT,AESNI,XSAVE,AVX> AMD Features=0x28100800<SYSCALL,NX,RDTSCP,LM> AMD Features2=0x1
[Bug c++/42692] New: Invalid member lookup when member template class is involved
The bug is: if a class definition has a nested template class, then whenever a code refers to a name in the nested class, gcc searches it not in the nested template class, but it the outer class. The bug results in gcc accepting a source text that should not be compiled, and incorrectly compiling a valid source text. Complete compilable example is included at the end of this report. I was able to reproduce this behaviour back to gcc 4.2.1, 3.3.2 and 2.95.3. Explanation. Please consider the following class definition: struct root { template typename Y struct chain { }; }; As you see, the structure root::chainany_type has no members. However, gcc accepts and compiles type declarations like typedef root::chaintype_1::chaintype_2::chaintype_3 my_type; , where my_type becomes root::chaintype_3, asif each chain template were looked up in the root class. You can use the following example to reproduce the bug. The example is compilable, which is wrong. //--- struct root { template typename Y struct chain { }; }; struct o1; struct o2; struct o3; typedef root::chaino1 p1; typedef root::chaino2::chaino1 p2; /* - should be error */ typedef root::chaino3::chaino2::chaino1 p3; /* - should be error */ int main() { p1 x1; p2 x2; p3 x3; x1 = x2 = x3; /* gcc thinks that they are of the same type! */ return 0; } -- Summary: Invalid member lookup when member template class is involved Product: gcc Version: 4.4.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: igusarov at mail dot ru GCC build triplet: amd64-unknown-freebsd7.1 GCC host triplet: amd64-unknown-freebsd7.1 GCC target triplet: amd64-unknown-freebsd7.1 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42692
[Bug c++/33909] New: Error reported on a legal source: invalid use of non-lvalue array when array name is used in initializer
Compiling the following code with g++ result in error. Command line to reproduce the error is arm-linux-gnueabi-g++ -c test.cpp, where test.cpp is the file comprising the following lines: struct T { const void* ptr; }; const struct T my_arr[] = { { 0 }, { my_arr+1 }// Error at this line }; Error is: invalid use of non-lvalue array This error is reported only when compiling as C++ code. Compilation with gcc or with -xc is successful. I think that the code above perfectly meet C++ standard because: 1. According to 3.3.1p1, the point of declaration of my_arr is immediately before =. Thus, the name my_arr is properly introduced and can be used in the initializer. 2. Expression my_arr+1 should be treated as: Array-to-pointer conversion (4.2p1), additive operator + (5.7p1). Resulting pointer does not exceed array boundaries, so the expression is well-formed and it has legal result. 3. Whether my_arr is an lvalue or an rvalue expression is not important, because array-to-pointer conversion is defined for lvalue and rvalue arrays (4.2p1). Which makes error message irrelevant, because such use is valid. 4. However, I believe that expression my_arr is an lvalue expression because it refers to an object (3.10p2). The fact that the object is const (i.e. non-modifiable) doesn't make it non-lvalue. Output of arm-linux-gnueabi-g++ -v is: Using built-in specs. Target: arm-none-linux-gnueabi Configured with: /home/toolbuilder/tools_build/build.arm-linux-gnueabi/gcc-4.1.1/configure --target=arm-none-linux-gnueabi --prefix=/usr/toolchain/arm-linux-gnueabi/gcc-4.1.1 --with-local-prefix=/usr/toolchain/arm-linux-gnueabi/gcc-4.1.1/local --with-sysroot=/usr/toolchain/arm-linux-gnueabi/sysroot-arm11-linux-2.6.17.8-glibc-2.4 --enable-languages=c,c++ --enable-c99 --program-transform-name=s/.*/arm-linux-gnueabi--4.1.1/ --enable-shared --enable-__cxa_atexit --disable-libunwind-exceptions --enable-threads=posix --enable-symvers=gnu --enable-long-long --disable-cpp --with-gnu-as --with-gnu-ld --with-as=/usr/toolchain/arm-linux-gnueabi/bin/arm-linux-gnueabi-as --with-ld=/usr/toolchain/arm-linux-gnueabi/bin/arm-linux-gnueabi-ld --with-nm=/usr/toolchain/arm-linux-gnueabi/bin/arm-linux-gnueabi-nm --with-objdump=/usr/toolchain/arm-linux-gnueabi/bin/arm-linux-gnueabi-objdump --disable-nls --disable-multilib Thread model: posix gcc version 4.1.1 -- Summary: Error reported on a legal source: invalid use of non- lvalue array when array name is used in initializer Product: gcc Version: 4.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: igusarov at mail dot ru GCC build triplet: i386-unknown-freebsd5.4 GCC host triplet: i386-unknown-freebsd5.4 GCC target triplet: arm-none-linux-gnueabi http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33909