[Bug c++/115639] New: Large variations in compilation times involving static_assert
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115639 Bug ID: 115639 Summary: Large variations in compilation times involving static_assert Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- I often want to be sure that an expression is evaluated at compile time, while also checking that it produces the expected value. With a `constexpr` function called `big_calc`, expected to return zero, I might either use: static_assert(0==big_calc());// (1) ...or: constexpr int ret = big_calc(); // (2) static_assert(0==ret); Surprisingly, the first of these (1) takes around 76% longer than the second (2) to compile. constexpr int big_calc() { long i = 1, count = 0, n = (1<<22); for (; i < n; i++) count = count + i; bool b = count == (i * (i - 1)) / 2; return 0; } This is true even when `big_calc` involves more calculations. I am using Ubuntu 24.04 with an Intel i9-13900K, and g++ (GCC) 15.0.0 20240623 (experimental). With `n` of `big_calc` set at `(1<<22)` (as above) average compilation times are 6.5 secs. for approach (1); and 3.7 secs. for approach (2). With `n` of `big_calc` set at `(1<<24)` average compilation times are 28.3 secs. for approach (1); and 16.2 secs. for approach (2). time /opt/gcc-latest/bin/g++ -std=c++20 performance-bug-double-constant-eval.cpp -fconstexpr-ops-limit=$((2**31-1)) -fconstexpr-loop-limit=$((2**31-1)) Other approaches to invoke `big_calc` (e.g. SFINAE/Concepts class/function templates) are also slow; and have the performance profile of method (1). Perhaps the constant expression is being evaluated twice. It does look odd that the `big_calc` function returns zero. This was reduced from a larger problem. Curiously, if `big_calc` instead returns a boolean (i.e. `b`), and the `0==` part of each constant expression is removed, the issue disappears. This is reminiscent of a recently resolved Clang issue (https://github.com/llvm/llvm-project/issues/92924), though with 2 notable differences: firstly, with GCC the problem only arises when the `big_calc` function is actually invoked; and secondly, the `-Wno-invalid-constexpr` flag makes no difference to the performance with GCC.
[Bug c++/111272] [13/14 Regression] Truncated error messages with -std=c++23 and -std=c++26
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111272 --- Comment #8 from Paul Keir --- I wonder if a small part of this bug still remains. The code below should #include , but as it doesn't, we get an error message. The message now gives all the right information but, with -std=c++23 and -std=c++26, a part of the text is still truncated. Instead of "declared here" we get "is not usable as a 'constexpr' function because:". Perhaps it should also say "declared here" with -std=c++23 and -std=c++26. At https://godbolt.org/z/6c9hME7hh the code is: // #include constexpr bool init_list() { int total{}; for (int x : {1, 2, 3}) total += x; return total == 6; } static_assert(init_list(), ""); The error message is: : In function 'constexpr bool init_list()': :6:24: error: deducing from brace-enclosed initializer list requires '#include ' +++ |+#include 1 | // #include .. 6 | for (int x : {1, 2, 3}) |^ : At global scope: :11:24: error: non-constant condition for static assertion 11 | static_assert(init_list(), ""); | ~^~ :11:24: error: 'constexpr bool init_list()' called in a constant expression :3:16: note: 'constexpr bool init_list()' is not usable as a 'constexpr' function because: 3 | constexpr bool init_list() |^ Compiler returned: 1
[Bug c++/113306] New: constexpr cast from void* fails with typeid result target
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113306 Bug ID: 113306 Summary: constexpr cast from void* fails with typeid result target Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- The C++26 code below fails to compile with GCC trunk; with Clang it passes. The error message indicates that the constexpr evaluator uses `const __fundamental_type_info_pseudo_2` as the type of `typeid(int)`. (See https://godbolt.org/z/1Mr9ao9hr.) #include #include constexpr bool test1() { const void* cvp = (int); return static_cast(cvp) != nullptr; } int main(int argc, char *argv[]) { static_assert(test1()); assert(test1()); return 0; } The error message is below. bug3.cpp:13:22: in ‘constexpr’ expansion of ‘test1()’ bug3.cpp:8:10: error: cast from ‘const void*’ is not allowed in a constant expression because pointed-to type ‘const __fundamental_type_info_pseudo_2’ is not similar to ‘const std::type_info’ 8 | return static_cast(cvp) != nullptr; | ^~~ bug3.cpp:6:32: note: pointed-to object declared here 6 | const void* cvp = (int);
[Bug libstdc++/113294] New: constexpr error from accessing inactive union member in basic_string after move assignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113294 Bug ID: 113294 Summary: constexpr error from accessing inactive union member in basic_string after move assignment Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- The C++20 program below fails to compile. A call to `basic_string::clear()` in the move assignment operator leads to an access of inactive union member `_M_local_buf`. #include constexpr bool string_test1() { { std::string str1; // = "1"; // also a problem when small (less than 16) std::string str2 = "1234567890123456"; // 16 chars str1 = std::move(str2); } return true; } static_assert(string_test1()); Changing `__str._M_data(__str._M_local_buf);` to `__str._M_data(__str._M_use_local_data());` in basic_string.h seems to fix it, though I've not had time to test it fully. With this solution, the function below also remains functional: constexpr bool string_test2() { { std::string str = "1234567890123456"; // 16 chars str = std::string{"1234567890123456"}; // rvalue assignment } return true; }
[Bug c++/111272] [13/14 Regression] Truncated error messages with -std=c++23 and -std=c++26
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111272 --- Comment #4 from Paul Keir --- I believe P2448R2 would only allow the code, without the static_assert. Explicitly calling `test()`, `Jam::Jam()` and then `Jam::ft()` here would mean evaluating a non-constexpr function (i.e. `ft`). ft is *constexpr-suitable*, but still needs the `constexpr` specifier when it is constant evaluated.
[Bug c++/111379] New: comparison between unequal pointers to void should be illegal during constant evaluation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111379 Bug ID: 111379 Summary: comparison between unequal pointers to void should be illegal during constant evaluation Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- [DR 2526](https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2526) clarifies that in C++23 comparison between unequal pointers to void has unspecified result. As unspecified behaviour cannot be executed in a constant expression, the code below should not compile. In fact without DR 2526, the comparison would have undefined behaviour, which also cannot be executed in a constant expression. constexpr bool compare_void_pointers() { int a[2]; void* vp1 = [0], * vp2 = [1]; return vp1 < vp2; } static_assert(compare_void_pointers());
[Bug c++/111272] [13/14 Regression] Truncated error messages with -std=c++23 and -std=c++26
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111272 --- Comment #2 from Paul Keir --- Thanks. The `-Winvalid-constexpr` mentioned there is a helpful workaround.
[Bug c++/111272] New: Truncated error messages with -std=c++23 and -std=c++26
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111272 Bug ID: 111272 Summary: Truncated error messages with -std=c++23 and -std=c++26 Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- The C++14 code below requires the `constexpr` specifier on the `ft` member function. Compiling this with `-std=c++14`, `-std=c++17` or `-std=c++20` will provide a helpful error message which identifies the need to add the `constexpr` specifier to `ft`. However, if `-std=c++23`, or `-std=c++26` are used, no message indicating the need for `constexpr` on `ft` is displayed; and the message itself is truncated: ending only in "...not usable as a 'constexpr' function because:". struct Jam { // constexpr // n.b. int ft() { return 42; } constexpr Jam() { ft(); } }; constexpr bool test() { Jam j; return true; } static_assert(test(), ""); The full truncated error message is: $ /opt/gcc-latest/bin/g++ -std=c++26 -c truncated-constexpr-error-gcc.cpp truncated-constexpr-error-gcc.cpp:16:19: error: non-constant condition for static assertion 16 | static_assert(test(), ""); | ^~ truncated-constexpr-error-gcc.cpp:16:19: in ‘constexpr’ expansion of ‘test()’ truncated-constexpr-error-gcc.cpp:12:7: error: ‘constexpr Jam::Jam()’ called in a constant expression 12 | Jam j; | ^ truncated-constexpr-error-gcc.cpp:7:3: note: ‘constexpr Jam::Jam()’ is not usable as a ‘constexpr’ function because: 7 | Jam() { ft(); } | ^~~
[Bug c++/70248] constexpr initialization with unspecified equality expression accepted
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70248 Paul Keir changed: What|Removed |Added CC||pkeir at outlook dot com --- Comment #10 from Paul Keir --- Here is another example which GCC accepts, but Clang correctly rejects: constexpr bool test() { int arr[2]{}; void *p1 = [0]; void *p2 = [1]; return p1 < p2; } constexpr bool b = test();
[Bug c++/110714] constexpr lifetime error: base class this pointer
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110714 --- Comment #3 from Paul Keir --- Actually, there's no need here to delete through the base pointer; so this is perhaps simpler: struct Base { constexpr Base* get_this() { return this; } int x; }; struct Derived : public Base {}; constexpr bool test() { Derived* pf = new Derived; delete static_cast(pf->get_this()); return true; } constexpr bool b = test();
[Bug c++/110714] constexpr lifetime error: base class this pointer
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110714 --- Comment #2 from Paul Keir --- I know. `delete pf` also works. The issue seems to be with the use of the this pointer within the member function. This is just the MRE - I've come across this issue twice now in our code base.
[Bug c++/110714] New: constexpr lifetime error: base class this pointer
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110714 Bug ID: 110714 Summary: constexpr lifetime error: base class this pointer Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- Compiling the C++20 MRE code below fails: struct Base { constexpr virtual ~Base() {} constexpr Base* get_this() { return this; } int x; }; struct Derived : public Base {}; constexpr bool test() { Derived* pf = new Derived; delete pf->get_this(); return true; } constexpr bool b = test(); ...with the following error message: 2$ /opt/gcc-latest/bin/g++ -std=c++20 -c ce_base_alloc2.cpp ce_base_alloc2.cpp:17:24: in ‘constexpr’ expansion of ‘test()’ ce_base_alloc2.cpp:13:23: in ‘constexpr’ expansion of ‘pf->Derived::.Base::get_this()->Base::~Base()’ ce_base_alloc2.cpp:8:8: error: deallocation of storage that was not previously allocated 8 | struct Derived : public Base {}; |^~~ I have tried with GCC trunk (14.0.0) and also version 12.2.0. I suspect that the this pointer in the base class is not tracking the constexpr dynamic allocation. Clang and MSVC both compile successfully. Clang requires the virtual destructor.
[Bug c++/106107] New: dynamic_cast fail within constant expression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106107 Bug ID: 106107 Summary: dynamic_cast fail within constant expression Product: gcc Version: 13.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- Created attachment 53210 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=53210=edit The code described in the bug report. The dynamic_cast, evaluated within the static_assert, in the code below, fails (GCC trunk); while the runtime assert passes. Both pass with Clang and MSVC. I have in place a workaround for the lack of an implicit destructor in Derived due to bug 93413 - I am not sure if this is independent of that 93413. #include struct Base { virtual constexpr ~Base() {} }; struct Derived : public Base { #if !defined(__clang__) // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93413 constexpr virtual ~Derived() {}; #endif }; constexpr bool test() { Base* bp = new Derived; Derived* dp = dynamic_cast(bp); bool b = dp != nullptr; delete bp; return b; } int main(int argc, char *argv[]) { static_assert(test()); assert(test()); return 0; }
[Bug c++/102406] New: ICE on array declaration sized by a struct member
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102406 Bug ID: 102406 Summary: ICE on array declaration sized by a struct member Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- Created attachment 51483 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=51483=edit The code described in the bug report. Compiling the code below (also attached) produces an internal compiler error. struct Foo { unsigned x_; }; int main(int argc, char *argv[]) { const Foo a{3}; float f[2][a.x_]{}; return 0; } The full error is below: internal compiler error: in make_decl_rtl, at varasm.c:1446 6 | float f[2][a.x_]{}; | ^ 0x86bd48 make_decl_rtl(tree_node*) ../../gcc/varasm.c:1446 0xda0967 expand_expr_real_1(tree_node*, rtx_def*, machine_mode, expand_modifier, rtx_def**, bool) ../../gcc/expr.c:10457 0xdb274b expand_constructor ../../gcc/expr.c:8491 0xda015a expand_expr_real_1(tree_node*, rtx_def*, machine_mode, expand_modifier, rtx_def**, bool) ../../gcc/expr.c:10749 0xdac0ec store_expr(tree_node*, rtx_def*, int, bool, bool) ../../gcc/expr.c:5994 0xdb1ab7 store_field ../../gcc/expr.c:7491 0xdae17d expand_assignment(tree_node*, tree_node*, bool) ../../gcc/expr.c:5589 0xc76a37 expand_gimple_stmt_1 ../../gcc/cfgexpand.c:3945 0xc76a37 expand_gimple_stmt ../../gcc/cfgexpand.c:4043 0xc7cf03 expand_gimple_basic_block ../../gcc/cfgexpand.c:6085 0xc7ecb7 execute ../../gcc/cfgexpand.c:6811
[Bug c++/100138] New: ICE with constructor constrained (C++20 Concepts) by parameter pack length
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100138 Bug ID: 100138 Summary: ICE with constructor constrained (C++20 Concepts) by parameter pack length Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- Created attachment 50624 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=50624=edit The C++ file producing the ICE Compiling the code below with `-c -std=c++20` produces an ICE. template struct Foo { template Foo(Ts... xs) requires(sizeof...(xs)==N) {} }; void bar() { Foo x{64}; } As a workaround, using Ts rather than xs within the requires clause avoids the ICE. The error message is below: constrained_ctor.hpp: In substitution of ‘template Foo(Ts ...)-> Foo requires sizeof ... ((Foo::__ct ::xs ...)) == N [with int N = 1; Ts = {int}]’: constrained_ctor.hpp:10:11: required from here constrained_ctor.hpp:5:26: internal compiler error: Segmentation fault 5 | Foo(Ts... xs) requires(sizeof...(xs)==N) {} | ^ 0x10d0e8f crash_signal ../../gcc/toplev.c:327 0x950d49 hash_table, tree_node*> >::hash_entry, false, xcallocator>::find_slot_with_hash(tree_node* const&, unsigned int, insert_option) ../../gcc/hash-table.h:963 0xac055d hash_map, tree_node*> >::put(tree_node* const&, tree_node* const&) ../../gcc/hash-map.h:166 0xac055d register_local_specialization(tree_node*, tree_node*) ../../gcc/cp/pt.c:2004 0xad21e1 gen_elem_of_pack_expansion_instantiation ../../gcc/cp/pt.c:12496 0xad21e1 tsubst_pack_expansion(tree_node*, tree_node*, int, tree_node*) ../../gcc/cp/pt.c:13173 0xac63be tsubst_copy ../../gcc/cp/pt.c:16925 0xac7ca4 tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*, bool, bool) ../../gcc/cp/pt.c:20896 0xac7ad3 tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*, bool, bool) ../../gcc/cp/pt.c:19856 0xad3128 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) ../../gcc/cp/pt.c:19144 0x95a455 satisfy_atom ../../gcc/cp/constraint.cc:2984 0x95a455 satisfy_constraint_r ../../gcc/cp/constraint.cc:3047 0x95a779 satisfy_normalized_constraints ../../gcc/cp/constraint.cc:3069 0x957d7e satisfy_declaration_constraints ../../gcc/cp/constraint.cc:3277 0x957d7e constraint_satisfaction_value ../../gcc/cp/constraint.cc:3297 0x95a810 constraints_satisfied_p(tree_node*, tree_node*) ../../gcc/cp/constraint.cc:3334 0xaf98a5 fn_type_unification(tree_node*, tree_node*, tree_node*, tree_node* const*, unsigned int, tree_node*, unification_kind_t, int, conversion**, bool, bool) ../../gcc/cp/pt.c:21632 0x9053fd add_template_candidate_real ../../gcc/cp/call.c:3456 0x905eda add_template_candidate ../../gcc/cp/call.c:3541 0x905eda add_candidates ../../gcc/cp/call.c:6031 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <https://gcc.gnu.org/bugs/> for instructions.
[Bug c++/96614] New: constexpr deletion failure through pointer to base with virtual base class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96614 Bug ID: 96614 Summary: constexpr deletion failure through pointer to base with virtual base class Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- Created attachment 49062 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=49062=edit A C++ file containing the code described. The C++20 code below (also attached) fails to compile with GCC trunk. struct FooBase { constexpr virtual ~FooBase() {} }; struct Foo : public FooBase {}; constexpr bool test() { FooBase* pb = new Foo; delete pb; return true; } int main(int argc, char *argv[]) { static_assert(test()); test(); // no problem return 0; } The error is invoked by the `static_assert` expression, and relates to the call to `delete pb`. It states: virtual constexpr Foo::~Foo()’ used before its definition
[Bug c++/95514] constexpr dynamic memory allocation compile error with inheritance and the this pointer
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95514 Paul Keir changed: What|Removed |Added Status|UNCONFIRMED |RESOLVED Resolution|--- |INVALID --- Comment #2 from Paul Keir --- Here is a reduced test case which removes prior use of static_cast and a pointer reference parameter. struct FooBase { constexpr FooBase* get_this() { return this; } int x; }; struct Foo : FooBase {}; constexpr bool test() { Foo* pf = new Foo; delete pf->get_this(); return true; } constexpr bool b = test(); --- Comment #3 from Paul Keir --- The code invokes undefined behaviour; as it tries to delete the object through pointer to base.
[Bug c++/96510] New: Unexpected constexpr deallocation error after implicit conversion
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96510 Bug ID: 96510 Summary: Unexpected constexpr deallocation error after implicit conversion Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- Created attachment 49012 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=49012=edit A C++ file containing the code described. In the C++20 code below (also attached), the Foo class allocates and deallocates to an int pointer member in the constructor and destructor respectively. Comparing a Foo object to an integer (via `operator==`) makes use of another member function `compare` which expects a `Foo&`; and so a `Foo` object is implicitly created. Somehow, within a `constexpr` context (e.g. the `static_assert` below), the `constexpr` memory is not being freed, and an error message is issued (error: ‘do_stuff()’ is not a constant expression because allocated storage has not been deallocated). struct Foo { constexpr Foo(int i) { p = new int(i); } constexpr ~Foo() { delete p; } constexpr bool compare(const Foo&) const { return true; } constexpr bool operator==(int y) const { return compare(y); } int *p; }; constexpr bool do_stuff() { Foo f(0); bool b = f == 42; return b; } int main(int argc, char *argv[]) { static_assert(do_stuff()); return do_stuff() ? 0 : -1; }
[Bug c++/96414] Second char relation test incorrect with constexpr dynamic allocation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96414 --- Comment #1 from Paul Keir --- constexpr int lt_fun(const char& c1, const char& c2) { return c1 < c2; } constexpr bool doit() { char *pc = new char; const char* s = "a"; *pc = 'b'; lt_fun(*s, *pc); // a < b *pc = 'a'; bool lt = lt_fun(*s, *pc); // a < a delete pc; return !lt; } int main(int argc, char *argv[]) { static_assert(doit()); return doit() ? 0 : -1; }
[Bug c++/96414] New: Second char relation test incorrect with constexpr dynamic allocation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96414 Bug ID: 96414 Summary: Second char relation test incorrect with constexpr dynamic allocation Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- Created attachment 48981 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48981=edit The file containing the code described. The attached C++20 code behaves differently at compile-time than at runtime, but shouldn't. As with `__gnu_cxx::char_traits::lt`, the function `lt_fun` applies built-in `operator<` to two character references, and returns the result as an `int`. However, with the character pointer `pc` pointing to memory allocated dynamically, the second call returns true (1) indicating that 'a' < 'a' is true. This is demonstrated by a failing static assert. Commenting out the static assert produces an executable which correctly reports that 'a' < 'a' is false; by returning a 0.
[Bug c++/95977] No deallocation of temporary in return-statement during constant evaluation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95977 Paul Keir changed: What|Removed |Added CC||pkeir at outlook dot com --- Comment #2 from Paul Keir --- I've also encountered this bug. I changed your code to: struct X { int* x{new int{42}}; constexpr ~X() { delete x; } }; int main(int argc, char *argv[]) { static_assert(42 == *X{}.x); return 0; } ...and now an extra note appears at compilation: note: ‘’ was not declared ‘constexpr’ 15 | static_assert(42 == *X{}.x); | ^ This made me think of the implicitly-defined default constructor for X, which should be `constexpr`. But perhaps attribution of this `constexpr` qualifier is failing due to the memory not having been freed at the point where the equality is evaluated? This is certainly unintuitive, but I do note that the error disappears when `static_assert(doit())` is used instead, with the following definition: constexpr bool doit() { int i = *X{}.x; return i==42; } ...but while that perhaps make sense, I encountered two other changes to the version above which surprisingly also remove the error: 1) Adding an explicitly defaulted constructor for X; 2) Using `X()` rather than `X{}` in the static assert.
[Bug c++/68342] Unexpected expansion pattern contains no argument packs error
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68342 Paul Keir changed: What|Removed |Added Resolution|--- |WORKSFORME Status|UNCONFIRMED |RESOLVED --- Comment #1 from Paul Keir --- The code no longer produces an error on gcc (Ubuntu 9.3.0-10ubuntu2) 9.3.0 and gcc (GCC) 11.0.0 20200531 (experimental). clang version 10.0.0-4ubuntu1 is also fine with it.
[Bug c++/95514] constexpr dynamic memory allocation compile error with inheritance and the this pointer
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95514 --- Comment #1 from Paul Keir --- The code above should also include: int main(int argc, char *argv[]) { static_assert(test1()); // test1(); // no problem return 0; }
[Bug c++/95514] New: constexpr dynamic memory allocation compile error with inheritance and the this pointer
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95514 Bug ID: 95514 Summary: constexpr dynamic memory allocation compile error with inheritance and the this pointer Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- Created attachment 48671 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48671=edit The code described in the bug report. I believe the C++20 code below should compile, but using `g++ -std=c++2a` instead produces an error; indicating that there was deallocation of storage that was not previously allocated. If the call to the `point_to_me` method is replaced with the assignment on the previous line, there is no error. Functionally the two forms seem the same to me. Removing inheritance from the situation removes the error, which makes me suspect the `static_cast`, but the this pointer usage also catches my eye. Using an `std::allocator` instead of the `new` expression changes nothing (included in the attached file as test2). struct FooBase { constexpr void point_to_me(FooBase*& p) { p = this; } FooBase* m_p = nullptr; }; struct Foo : FooBase {}; constexpr bool test1() { FooBase fb; Foo* pf = new Foo; // fb.m_p = pf; // this works pf->point_to_me(fb.m_p); // this doesn't delete static_cast(fb.m_p); return true; }
[Bug c++/93867] New: ICE using class type NTTPs and class template argument deduction
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93867 Bug ID: 93867 Summary: ICE using class type NTTPs and class template argument deduction Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- Created attachment 47881 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=47881=edit The code described in the bug report. The attached C++20 code makes use of class type NTTPs, and also class template argument deduction. It is based on code from P0732r2. With the -std=c++2a switch the code produces an ICE on GCC snapshot gcc-10-20200216. The error message is below: nttp_ice.cpp: In function ‘int main(int, const char**)’: nttp_ice.cpp:27:16: internal compiler error: in alias_ctad_tweaks, at cp/pt.c:28327 27 | foo<"hello">(); |^ 0x67b060 alias_ctad_tweaks ../../gcc/cp/pt.c:28327 0x67b060 deduction_guides_for ../../gcc/cp/pt.c:28499 0x9fc488 do_class_deduction ../../gcc/cp/pt.c:28604 0x9fc488 do_auto_deduction(tree_node*, tree_node*, tree_node*, int, auto_deduction_context, tree_node*, int) ../../gcc/cp/pt.c:28733 0x9fe129 convert_template_argument ../../gcc/cp/pt.c:8306 0x9fff7b coerce_template_parms ../../gcc/cp/pt.c:8810 0xa32fac fn_type_unification(tree_node*, tree_node*, tree_node*, tree_node* const*, unsigned int, tree_node*, unification_kind_t, int, conversion**, bool, bool) ../../gcc/cp/pt.c:20919 0x8951ed add_template_candidate_real ../../gcc/cp/call.c:3396 0x895c04 add_template_candidate ../../gcc/cp/call.c:3481 0x895c04 add_candidates ../../gcc/cp/call.c:5830 0x8960c7 add_candidates ../../gcc/cp/call.c:4478 0x8960c7 perform_overload_resolution ../../gcc/cp/call.c:4486 0x89bdb5 build_new_function_call(tree_node*, vec**, int) ../../gcc/cp/call.c:4560 0xa4ec54 finish_call_expr(tree_node*, vec**, bool, bool, int) ../../gcc/cp/semantics.c:2671 0x9c848d cp_parser_postfix_expression ../../gcc/cp/parser.c:7427 0x9ab24a cp_parser_binary_expression ../../gcc/cp/parser.c:9519 0x9acd0c cp_parser_assignment_expression ../../gcc/cp/parser.c:9824 0x9ad032 cp_parser_expression ../../gcc/cp/parser.c:9992 0x9aff26 cp_parser_expression_statement ../../gcc/cp/parser.c:11642 0x9bb083 cp_parser_statement ../../gcc/cp/parser.c:11438
[Bug c++/92530] New: Absent error on static_assert expression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92530 Bug ID: 92530 Summary: Absent error on static_assert expression Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- Created attachment 47272 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=47272=edit The code described in the bug report. The static_assert expression in the C++11 code below is not an integral constant expression. GCC trunk compiles this, while Clang reports the error correctly. To quote Clang's Richard Smith: "The evaluation semantics of the expression 'x' (because it's of reference type) involve locating the object that the reference binds to, which can't be done in this case because we don't know the value of the function parameter 'x'. So the evaluation of the static_assert condition is non-constant, which is invalid." The language rule that's violated is here: http://eel.is/c++draft/expr.const#4.12 template constexpr bool bar(T &) { return true; } template constexpr bool foo(T ) { static_assert(bar(x),""); return bar(x); } int main(int argc, char *argv[]) { int i; constexpr bool y = foo(i); return 0; }
[Bug c++/88762] New: C++17 Deduction guide and operator expression produces missing template argument error
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88762 Bug ID: 88762 Summary: C++17 Deduction guide and operator expression produces missing template argument error Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- Created attachment 45383 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=45383=edit C++ file which produces the error. I believe the code below/attached should compile with: g++ -c -std=c++17 gcc-deduction-expr.cpp The code is already reduced, but I also tried changing the operator for a method; and only using operator+ once; but the error disappears in both cases. The code compiles with Clang. Here is the error: error: missing template arguments after ‘Foo’ (Foo{x} + Foo{y}) + Foo{z}; ^~~ The code: template struct Foo { Foo operator+(Foo &) { return f; } T }; template Foo(T) -> Foo; void zod() { int x,y,z; (Foo{x} + Foo{y}) + Foo{z}; }
[Bug c++/83003] Using the detection idiom and void_t causes an error
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83003 Paul Keir changed: What|Removed |Added CC||pkeir at outlook dot com --- Comment #1 from Paul Keir --- Created attachment 42615 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=42615=edit The code described in the bug
[Bug c++/59498] [DR 1430][4.9/5/6/7 Regression] Pack expansion error in template alias
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59498 --- Comment #13 from Paul Keir --- Yup, I just came up with exactly the same solution. Thanks.
[Bug c++/59498] [DR 1430][4.9/5/6/7 Regression] Pack expansion error in template alias
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59498 Paul Keir changed: What|Removed |Added CC||pkeir at outlook dot com --- Comment #11 from Paul Keir --- Did you find a way to implement quote when given an alias?
[Bug c++/71737] ICE following 2x pack expansion in non-pack with template alias
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71737 --- Comment #1 from Paul Keir --- Created attachment 38820 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=38820=edit Minimal testcase.
[Bug c++/71737] New: ICE following 2x pack expansion in non-pack with template alias
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71737 Bug ID: 71737 Summary: ICE following 2x pack expansion in non-pack with template alias Product: gcc Version: 7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- The code below (and attached) produces an ICE with gcc (GCC) 7.0.0 20160608 (experimental) when compiled using g++ with "-c -std=c++11". template class TT> struct quote { template using apply = TT; }; template using to_int_t = int; using t = quote<quote::apply>::apply;
[Bug c++/68342] New: Unexpected expansion pattern contains no argument packs error
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68342 Bug ID: 68342 Summary: Unexpected expansion pattern contains no argument packs error Product: gcc Version: 6.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- Created attachment 36704 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=36704=edit The code which produces the unexpected error The C++11 code below unexpectedly fails to compile on 64-bit Ubuntu 15.04 using g++ (GCC) 6.0.0 20151110 (experimental) with the following message: nullary.cpp:12:27: error: expansion pattern ‘g(xs#0)’ contains no argument packs using r_t = decltype(mt(g(x),g(xs)...)) It compiles with Clang 3.8.0. struct vec { int x; }; template int g(T y) { return y.x; } template int mt(Ts ...xs){ return 0; } template void quack(T x, Ts ...xs) { using r_t = decltype(mt(g(x),g(xs)...)); auto f = []() { return r_t{}; }; } int main(int argc, char *argv[]) { quack(vec{0},vec{0},vec{0}); return 0; }
[Bug c++/68278] New: internal compiler error with C++14 polymorphic lambda and type alias
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68278 Bug ID: 68278 Summary: internal compiler error with C++14 polymorphic lambda and type alias Product: gcc Version: 5.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Target Milestone: --- Created attachment 36682 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=36682=edit C++14 file which produces the internal compiler error The C++14 code below produces an internal compiler error in tsubst_decl, at cp/pt.c:10836 when compiled using: g++ -std=c++14 poly_type_lambda_bug.cpp with GCC 5.2.0. I'm using Ubuntu 15.04 (vivid). It compilers and runs with clang version 3.8.0 (trunk 252425). int main(int argc, char *argv[]) { auto f = []() { return 1; }; auto q = [=](auto g) { using type = decltype(g(f())); }; q([](int x){ return x; }); return 0; }
[Bug c++/68278] internal compiler error with C++14 polymorphic lambda and type alias
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68278 --- Comment #2 from Paul Keir --- Agreed. I've just tested on 6.0.0 20151110 and there is no ICE.
[Bug c++/59991] New: Recursive lambda capture in C++1y constexpr function template causes internal compiler error
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59991 Bug ID: 59991 Summary: Recursive lambda capture in C++1y constexpr function template causes internal compiler error Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pkeir at outlook dot com Created attachment 31987 -- http://gcc.gnu.org/bugzilla/attachment.cgi?id=31987action=edit The test case which produces the internal compiler error The code below uses the C++1y feature of allowing declarations in constexpr functions, but r should not be included in the lambda's capture list. There is also an issue with excessive recursive template instantiation. In any case, the code produces an internal compiler error starting with: internal compiler error: in tsubst, at cp/pt.c:11350 auto f = [r,x]() { return r(x); }; The full output and test case is attached. This was run under Ubuntu 13.10. // $ g++ --version // g++ (GCC) 4.9.0 20131201 (experimental) template typename T constexpr int r(T x) { auto f = [r,x]() { return r(x); }; return 0; } int main(int argc, char *argv[]) { r(0); return 0; }
[Bug c++/59991] Recursive lambda capture in C++1y constexpr function template causes internal compiler error
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59991 --- Comment #1 from Paul Keir pkeir at outlook dot com --- Created attachment 31988 -- http://gcc.gnu.org/bugzilla/attachment.cgi?id=31988action=edit The output following: g++ -std=c++1y bug.cpp
[Bug c++/56387] Alias of class template wrongly seen as different
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56387 --- Comment #2 from Paul Keir pkeir at outlook dot com 2013-02-19 12:01:51 UTC --- Created attachment 29492 -- http://gcc.gnu.org/bugzilla/attachment.cgi?id=29492 Another unexpected error; and also an internal compiler error
[Bug c++/56387] Alias of class template wrongly seen as different
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56387 --- Comment #3 from Paul Keir pkeir at outlook dot com 2013-02-19 12:18:17 UTC --- I've added gcc472aliastemplatebug.cpp which also displays an unexpected error; shown below along with the code. This is hopefully a related (and simpler) example. Also, by using the non-template alias, ein2, and uncommenting the last two statements of test, an internal compiler error occurs. Again, an online 4.8.0 compiler gives the same errors. template int ...Is struct is1 {}; template typename, int, int struct ein_helper; template int ...Is, int N struct ein_helperis1Is...,N,N { typedef is1Is... type; }; template int ...Is, int N, int Ne struct ein_helperis1Is...,N,Ne { typedef typename ein_helperis1Is...,N,N+1,Ne::type type; }; template typename T using ein1 = typename ein_helperis1,0,5::type; using ein2 = typename ein_helperis1,0,5::type; template template int ... class C, int ...Is inline void burst(CIs... const arg_ixs) {} void test() { ein1int abc; // ein2 abc; // Use instead for an internal compiler error burst(abc); } // Error messages: gcc472aliastemplatebug.cpp: In function ‘void test()’: gcc472aliastemplatebug.cpp:28:12: error: no matching function for call to ‘burst(ein1int)’ gcc472aliastemplatebug.cpp:28:12: note: candidate is: gcc472aliastemplatebug.cpp:23:13: note: templatetemplateint ...anonymous class C, int ...Is void burst(const CIs ...) gcc472aliastemplatebug.cpp:23:13: note: template argument deduction/substitution failed: gcc472aliastemplatebug.cpp:28:12: error: type/value mismatch at argument 1 in template parameter list for ‘templateint ...anonymous class C’ gcc472aliastemplatebug.cpp:28:12: error: expected a constant of type ‘int’, got ‘int’ // Internal compiler error: gcc472aliastemplatebug.cpp: In function ‘void test()’: gcc472aliastemplatebug.cpp:28:12: internal compiler error: Segmentation fault Please submit a full bug report, with preprocessed source if appropriate. See https://bugs.archlinux.org/ for instructions.
[Bug c++/56387] Alias of class template wrongly seen as different
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56387 --- Comment #4 from Paul Keir pkeir at outlook dot com 2013-02-19 12:20:39 UTC --- Comment on attachment 29492 -- http://gcc.gnu.org/bugzilla/attachment.cgi?id=29492 Another unexpected error; and also an internal compiler error template int ...Is struct is1 {}; template typename, int, int struct ein_helper; template int ...Is, int N struct ein_helperis1Is...,N,N { typedef is1Is... type; }; template int ...Is, int N, int Ne struct ein_helperis1Is...,N,Ne { typedef typename ein_helperis1Is...,N,N+1,Ne::type type; }; template typename T using ein1 = typename ein_helperis1,0,5::type; using ein2 = typename ein_helperis1,0,5::type; template template int ... class C, int ...Is inline void burst(CIs... const arg_ixs) {} void test() { ein1int abc; // ein2 abc; // Use instead for an internal compiler error burst(abc); }
[Bug c++/56387] New: Alias of class template wrongly seen as different
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56387 Bug #: 56387 Summary: Alias of class template wrongly seen as different Classification: Unclassified Product: gcc Version: 4.7.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: pk...@outlook.com Created attachment 29490 -- http://gcc.gnu.org/bugzilla/attachment.cgi?id=29490 Minimal test case The attached minimal test case creates an alias template of a variadic class template. A function foo2 fails to unify a template template parameter C when given two arguments created using both forms - but only if the object created using the alias template is passed to a parameter expecting a reference. An online 4.8.0 compiler also failed. g++ -c -std=c++11 -Wall -Wextra gcc472templatetemplatebug.cpp The code and error are also listed below: template int ...Is struct is1 {}; template int ...Is using is2 = is1Is...; template template int ... class C, int ...Is, int ...Js void foo1(CIs... a, CJs... b) {} template template int ... class C, int ...Is, int ...Js void foo2(CIs... a, CJs... b) {} // ! void test() { is11,2,345 x; is26,78,90 y; foo1(x,y); foo2(x,y); } // Now the error messages: cc472templatetemplatebug.cpp: In function ‘void test()’: gcc472templatetemplatebug.cpp:18:11: error: no matching function for call to ‘foo2(is11, 2, 345, is26, 78, 90)’ gcc472templatetemplatebug.cpp:18:11: note: candidate is: gcc472templatetemplatebug.cpp:11:6: note: templatetemplateint ...anonymous class C, int ...Is, int ...Js void foo2(CIs ..., CJs ...) gcc472templatetemplatebug.cpp:11:6: note: template argument deduction/substitution failed: gcc472templatetemplatebug.cpp:18:11: note: deduced conflicting types for parameter ‘CJs ...’ (‘templateint ...Is struct is1’ and ‘templateint . ..Is using is2 = is1Is ...’) gcc472templatetemplatebug.cpp: In instantiation of ‘void foo1(CIs ..., CJs ...) [with C = is1; int ...Is = {1, 2, 345}; int ...Js = {6, 78, 90}]’: gcc472templatetemplatebug.cpp:17:11: required from here gcc472templatetemplatebug.cpp:8:6: warning: unused parameter ‘a’ [-Wunused-parameter] gcc472templatetemplatebug.cpp:8:6: warning: unused parameter ‘b’ [-Wunused-parameter]
[Bug c++/55013] New: variadic sizeof non-constant with alias template
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55013 Bug #: 55013 Summary: variadic sizeof non-constant with alias template Classification: Unclassified Product: gcc Version: 4.8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: pk...@outlook.com Created attachment 28500 -- http://gcc.gnu.org/bugzilla/attachment.cgi?id=28500 Code that produces the error The following code fails to compile as the size of the variadic template parameter pack Ts is considered to be non-constant: template typename ...Ts struct Foo {}; template std::size_t I using PI = int; template typename ...Ts PIsizeof...(Ts) q(FooTs...) { return PIsizeof...(Ts)(42); } With GCC 4.7.2 and Clang 3.2 there is no problem. I am using GCC snapshot 4.8.0 20121014 under Ubuntu. Compiled with: g++ -std=c++11 -c alias.cpp
[Bug middle-end/40205] OpenMP do loop with MAXINT gives wrong trip count
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40205 --- Comment #3 from Paul Keir pkeir at outlook dot com 2012-09-30 21:29:22 UTC --- Still present in GFortran 4.7.2 on 32-bit Ubuntu 12.04.1.
[Bug c++/54763] New: Crash with enable_if (instead of recursive template errors)
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54763 Bug #: 54763 Summary: Crash with enable_if (instead of recursive template errors) Classification: Unclassified Product: gcc Version: 4.7.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: pk...@outlook.com Created attachment 28308 -- http://gcc.gnu.org/bugzilla/attachment.cgi?id=28308 C++11 code which causes an internal compiler error The attached minimised C++11 test case causes an internal compiler error. Clang instead gives an endless list of errors such as: fatal error: recursive template instantiation exceeded maximum depth of 512 The code, which is also shown below, will run correctly if the enable_if is instead set to: std::enable_if(I0)::type. #include type_traits template unsigned struct tint {}; double zod(tint0) { return 3.142; } template unsigned I, typename = typename std::enable_if(I0),decltype(zod(tintI-1()))::type decltype(zod(tintI-1())) zod(tintI) { return zod(tintI-1()); } int main(int argc, char *argv[]) { zod(tint0()); return 0; }