[Bug c++/91159] New: Compilation error on explicitly defaulting default constructor of abstract class with virtual base class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91159 Bug ID: 91159 Summary: Compilation error on explicitly defaulting default constructor of abstract class with virtual base class Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: krzyk240 at gmail dot com Target Milestone: --- Consider the code below: ``` class Base { public: Base(int) {} virtual void foo() = 0; virtual ~Base() = default; }; class A : virtual public Base { public: A() = default; // Works with this line commented out }; class B : public A { public: B() : Base(0) {} void foo() override {} }; int main() { B b; } ``` It does not compile with GCC but compiles with Clang without problems. However, that is a minor issue. The core issue is that with the line `A() = default;` commented out, this code compiles fine on GCC. So, the question is: Should be there such difference between implicitly declared default constructor and explicitly defaulted default constructor? If such code is anyhow wrong, what should be the correct way to write it? As I understand, there is no point in making constructor of class A that initializes the class Base. That is because Base class is virtually inherited and class A is abstract. That means that A cannot be constructed directly and since the most derivative class has to directly call the virtual base class constructor, class A will never construct Base directly.
[Bug c++/70486] New: Constexpr array captured in lambda function (used via std::function)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70486 Bug ID: 70486 Summary: Constexpr array captured in lambda function (used via std::function) Product: gcc Version: 5.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: krzyk240 at gmail dot com Target Milestone: --- Created attachment 38150 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=38150&action=edit The *.i* file #include #include int main() { constexpr int t[2] = { 1, 2 }; std::function foo = [&] { for (int i = 0; i < 2; ++i) std::cout << t[i] << ' '; }; foo(); return 0; } $ g++-5.1 -std=c++11 -Wall -Wextra main.cpp -v -save-temps Using built-in specs. COLLECT_GCC=g++-5.1 COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-unknown-linux-gnu/5.1.0/lto-wrapper Target: x86_64-unknown-linux-gnu Configured with: ../gcc-5.1.0/configure --prefix=/usr/local --disable-multilib --without-mpc --without-mpfr --without-gmp --without-cloog --without-isl --enable-languages=c,c++ Thread model: posix gcc version 5.1.0 (GCC) COLLECT_GCC_OPTIONS='-std=c++11' '-Wall' '-Wextra' '-v' '-save-temps' '-shared-libgcc' '-mtune=generic' '-march=x86-64' /usr/local/libexec/gcc/x86_64-unknown-linux-gnu/5.1.0/cc1plus -E -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE main.cpp -mtune=generic -march=x86-64 -std=c++11 -Wall -Wextra -fpch-preprocess -o main.ii ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" ignoring nonexistent directory "/usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.1.0/../../../../x86_64-unknown-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.1.0/../../../../include/c++/5.1.0 /usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.1.0/../../../../include/c++/5.1.0/x86_64-unknown-linux-gnu /usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.1.0/../../../../include/c++/5.1.0/backward /usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.1.0/include /usr/local/include /usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.1.0/include-fixed /usr/include/x86_64-linux-gnu /usr/include End of search list. COLLECT_GCC_OPTIONS='-std=c++11' '-Wall' '-Wextra' '-v' '-save-temps' '-shared-libgcc' '-mtune=generic' '-march=x86-64' /usr/local/libexec/gcc/x86_64-unknown-linux-gnu/5.1.0/cc1plus -fpreprocessed main.ii -quiet -dumpbase main.cpp -mtune=generic -march=x86-64 -auxbase main -Wall -Wextra -std=c++11 -version -o main.s GNU C++11 (GCC) version 5.1.0 (x86_64-unknown-linux-gnu) compiled by GNU C version 5.1.0, GMP version 5.0.2, MPFR version 3.1.0-p3, MPC version 0.9 GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096 GNU C++11 (GCC) version 5.1.0 (x86_64-unknown-linux-gnu) compiled by GNU C version 5.1.0, GMP version 5.0.2, MPFR version 3.1.0-p3, MPC version 0.9 GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096 Compiler executable checksum: 03db94ff6398330bffd2a80db4ec6941 main.cpp: In lambda function: main.cpp:8:20: internal compiler error: in make_decl_rtl, at varasm.c:1313 std::cout << t[i] << ' '; ^ libbacktrace could not find executable to open Please submit a full bug report, with preprocessed source if appropriate. See <http://gcc.gnu.org/bugs.html> for instructions. $ uname -a Linux stacked-crooked 3.2.0-74-virtual #109-Ubuntu SMP Tue Dec 9 17:04:48 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
[Bug c++/70732] New: Operator new is unable to throw std::bad_alloc() when memory is exhausted in statically linked executable
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70732 Bug ID: 70732 Summary: Operator new is unable to throw std::bad_alloc() when memory is exhausted in statically linked executable Product: gcc Version: 5.3.0 Status: UNCONFIRMED Severity: major Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: krzyk240 at gmail dot com Target Milestone: --- Created attachment 38313 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=38313&action=edit *.ii file When there is no more memory available for the program and operator new is called, then it is unable to throw an exception - it unsuccessfully tries several times (a couple of thousands) to allocate memory for the exception. And finally, the exception is thrown. The problem is that memory for the exception is tried to be allocated too many times, but only if the program is statically linked. I have done some research and found that numerous allocation attempts come from function _Unwind_RaiseException(). To see unsuccessful allocation attempts, use command Strace. And one more thing I tested this program on GCC 4.6.4, 4.7.3, 4.8.5, 4.9.3, 5.3.0 and only on version 4.6.3 number of calls to brk(2) and mmap2() was normal (no more than 100). Here is code which is supossed to trigger the problem: #include void foo(int k) { const int size1 = 64; const int size2 = 256; volatile int t[size1]; // new[] should throw an exception as soon as memory is exhausted int volatile* p = new int[size2]; t[size1 - 1] = p[size2 - 1] = ++k; // prevent compiler from erasing t and p foo(++k); } int main() { // Set low memory limit struct rlimit limit; limit.rlim_cur = limit.rlim_max = 10 << 20; if (setrlimit(RLIMIT_AS, &limit)) return 1; if (setrlimit(RLIMIT_STACK, &limit)) return 2; foo(0); return 0; } /// Compilation command and output: $ g++-5 -v -save-temps -static re.cpp -o r -m32 -O2 Using built-in specs. COLLECT_GCC=g++-5 COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.3.0-3ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=gcc4-compatible --disable-libstdcxx-dual-abi --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 5.3.0 20151204 (Ubuntu 5.3.0-3ubuntu1~14.04) COLLECT_GCC_OPTIONS='-v' '-save-temps' '-static' '-o' 'r' '-m32' '-O2' '-mtune=generic' '-march=i686' /usr/lib/gcc/x86_64-linux-gnu/5/cc1plus -E -quiet -v -imultilib 32 -imultiarch i386-linux-gnu -D_GNU_SOURCE re.cpp -m32 -mtune=generic -march=i686 -O2 -fpch-preprocess -fstack-protector -Wformat -Wformat-security -o re.ii ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/5/../../../../include/i386-linux-gnu/c++/5" ignoring nonexistent directory "/usr/local/include/i386-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/5/../../../../x86_64-linux-gnu/include" ignoring nonexistent directory "/usr/include/i386-linux-gnu" #include "..." search starts here: #include <...> search starts here: /usr/include/c++/5 /usr/include/x86_64-linux-gnu/c++/5/32 /usr/include/c++/5/backward /usr/lib/gcc/x86_64-linux-gnu/5/include /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/5/include-fixed /usr/include End of search list. COLLECT_GCC_OPTIONS='-v' '-save-temps' '-static' '-o' 'r' '-m32' '-O2' '-mtune=generic' '-march=i686' /usr/lib/gcc/x86_64-linux-g
[Bug c++/70732] Operator new is unable to throw std::bad_alloc() when memory is exhausted in statically linked executable
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70732 --- Comment #2 from Krzysztof Małysa --- I read some code from unwind-dw2-fde.c and it makes sense. In the code above, stack unwinding happens in low memory conditions which causes unsuccessful memory allocations and because of deep recursion, there are so many of them. But maybe it is reasonable to make an optimization to not flood system with many, many unsuccessful syscalls (brk() and mmap2()). It's important to note that stack unwinding happens at the bottom of recursion (so it's unlikely that there will be more memory available - see https://github.com/gcc-mirror/gcc/blob/master/libgcc/unwind-dw2-fde.c#L957), also look at these syscalls which malloc makes: brk(0xcad8000) = 0xcab4000 mmap2(NULL, 1048576, ...) = -1 It tries to expand stack (which is not successful due to deep recursion that was made) and to map 1MB of memory, what is very much compared to what is needed, so it will almost always result in malloc() returning NULL. That is why it doesn't make much sense to call malloc() all the time if there is no memory available while we're freeing only small chunks of memory. All in all, I agree that there is no bug, but I think that it's a good opportunity to make an optimization here.
[Bug c++/100231] New: [C++17] Variable template specialization inside a class gives compilation error
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100231 Bug ID: 100231 Summary: [C++17] Variable template specialization inside a class gives compilation error Product: gcc Version: 10.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: krzyk240 at gmail dot com Target Milestone: --- On the following code: ``` template struct X {}; class Foo { template static constexpr inline bool bar = false; template static constexpr inline bool bar> = true; }; ``` GCC gives error: :8:34: error: explicit template argument list not allowed 8 | static constexpr inline bool bar> = true; | ^ But Clang, ICC and MSVC compile it correctly. Defining variable template bar outside of Foo class produces no compile errors. Compilation command: g++ example.cpp -std=c++17 Live example: https://godbolt.org/z/54hqYxe4P
[Bug c++/102577] New: Function frame size in relation to variables in conditional subscopes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102577 Bug ID: 102577 Summary: Function frame size in relation to variables in conditional subscopes Product: gcc Version: 11.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: krzyk240 at gmail dot com Target Milestone: --- Consider the following code: ``` int bar(unsigned short x, int* cache = nullptr) { if (!cache) { int cache[1 << (sizeof(x) * 8)] = {}; return bar(x, cache); } if (cache[x] != 0) { return cache[x]; } if (x == 0) { cache[x] = 1; } else { cache[x] = (bar(x - 1, cache) + bar(x / 2, cache)) % 17; } return cache[x]; } int bar2(unsigned short x, int* cache = nullptr) { if (!cache) { return [&] { int cache[1 << (sizeof(x) * 8)] = {}; return bar2(x, cache); }(); } if (cache[x] != 0) { return cache[x]; } if (x == 0) { cache[x] = 1; } else { cache[x] = (bar2(x - 1, cache) + bar2(x / 2, cache)) % 17; } return cache[x]; } #include #include int main() { printf("%i\n", bar(65535)); system("grep Vm /proc/$PPID/status"); } ``` The only difference between functions bar() and bar2() the first if -- in bar2() its contents are wrapped inside immediately invoked lambda. What is important, on the first call to bar() or bar2(), a big local array will be created on stack, and then in each recursive invocation, it will be not created. So this big local array is created ONCE if we analyze the control flow. The depth of the recursion is x, and I assume sizeof(unsigned short) == 2. So the program should use little memory (at most, a couple of MB). Unfortunately this program consumes much more memory than expected, VmRSS is around 270 MB, and VmStk is around 16 GB. Invoking it compiled with O2 (g++ abc.cc -O2 -o abc), produces: ``` 964369483 VmPeak: 16787136 kB VmSize: 16787100 kB VmLck: 0 kB VmPin: 0 kB VmHWM:269272 kB VmRSS:269272 kB VmData: 240 kB VmStk: 16781320 kB VmExe: 4 kB VmLib: 3188 kB VmPTE: 32892 kB VmSwap:0 kB ``` If we change invocation `bar(65535)` to `bar2(65535)` it produces: ``` 964369483 VmPeak: 9148 kB VmSize: 9112 kB VmLck: 0 kB VmPin: 0 kB VmHWM: 6092 kB VmRSS: 6092 kB VmData: 240 kB VmStk: 3332 kB VmExe: 4 kB VmLib: 3188 kB VmPTE:56 kB VmSwap:0 kB ``` Which are the expected numbers. It seems that GCC propagates allocation of stack memory for the local array to the function scope ignoring enclosing conditional scope. So that stack frame size of bar() is always greater than 65536 * 4b. Clang seems behave in the same way as GCC. I tried to find some information why it is done this way, but failed to find anything (I checked, cppreference, c++17 standard, stack overflow etc.). So here is my question: Is this behavior compliant with C++ standard, or is it a bug, or is it an optimization that rarely has an adverse impact? IMO, moving big stack memory allocations from conditional subscopes to function scope, especially if this function is recursive is not a good idea. This behavior was quite surprising for me when I discovered why similar program uses (wastes) so much memory.
[Bug c++/102577] Function frame size in relation to variables in conditional subscopes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102577 --- Comment #2 from Krzysztof Małysa --- Could you explain why this is correct? For example, quoting a relevant part of the C++ standard will do. As I said, I couldn't find WHY this is the expected behavior. I need to understand it.
[Bug c++/102577] Function frame size in relation to variables in conditional subscopes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102577 Krzysztof Małysa changed: What|Removed |Added Status|RESOLVED|UNCONFIRMED Resolution|INVALID |--- --- Comment #3 from Krzysztof Małysa --- I have received no explanation, maybe nobody saw my comment... I don't know what to do to receive explanation so let's try changing the status.