The following code fails to compile on GCC trunk: constexpr void f() { if (false) throw; } The error is: [snip]: In function 'constexpr void f()': [snip]: error: expression '<throw-expression>' is not a constant-expression } ^ The code should compile because the throw expression is never executed inside a constexpr context. Clang indeed compiles this just fine. Live example: http://melpon.org/wandbox/permlink/V0g96xpWdO2eWGNx
This is almost certainly a duplicate of #66026, yet it is still unconfirmed.
*** Bug 66026 has been marked as a duplicate of this bug. ***
Switch statements are rejected, too: constexpr int fun(int n) { switch (n) { case 0: return 1; default: throw; } } static_assert(fun(0), ""); Only the ternary operator works fine.
The fix might be as simple as: diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 1eacb8be9a44..7016b347a79c 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -4324,7 +4324,6 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, case VEC_NEW_EXPR: case DELETE_EXPR: case VEC_DELETE_EXPR: - case THROW_EXPR: case OMP_ATOMIC: case OMP_ATOMIC_READ: case OMP_ATOMIC_CAPTURE_OLD: @@ -4629,6 +4628,9 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, /* We can see these in statement-expressions. */ return true; + case THROW_EXPR: + return true; + default: if (objc_is_property_ref (t)) return false;
(In reply to Markus Trippelsdorf from comment #4) > The fix might be as simple as: I tried something similar but got: ./constexpr_throw.cc:4:15: error: call to non-constexpr function 'void* __cxa_allocate_exception(long unsigned int)' throw 1; or: ./constexpr_throw.cc:4:9: error: call to non-constexpr function 'void __cxa_rethrow()' throw;
Well, my patch survives regression testing and fixes the issue. But unfortunately it leads to accept invalid cases like: constexpr int f1() { throw; return 0; } or constexpr void f2() { throw; } (Even clang accepts f2.)
(In reply to Markus Trippelsdorf from comment #6) > Well, my patch survives regression testing and fixes the issue. > > But unfortunately it leads to accept invalid cases like: > > constexpr int f1() { > throw; > return 0; > } > > or > > constexpr void f2() { > throw; > } > > (Even clang accepts f2.) I think it would be better for the compiler to accept constexpr functions that are ill-formed NDR - like f1 and f2 - than to reject constexpr functions that are conforming like: constexpr int f3() { return 0; throw; } constexpr int* f4(bool b) { if (b) { return nullptr; } else { return new int{42}; } }
Author: trippels Date: Sat Aug 29 18:51:26 2015 New Revision: 227323 URL: https://gcc.gnu.org/viewcvs?rev=227323&root=gcc&view=rev Log: Fix c++/67371 (issues with throw in constexpr) As PR67371 shows gcc currently rejects all throw statements in constant-expressions, even when they are never executed. PR c++/67371 * constexpr.c (potential_constant_expression_1): Remove IF_STMT case. Move label to COND_EXPR case. Remove checking of SWITCH_STMT_BODY. Added: trunk/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C trunk/gcc/testsuite/g++.dg/cpp1y/constexpr-throw.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/constexpr.c
Fixed.
Ping to get this merged into the upcoming 5.4 release.
(In reply to rhalbersma from comment #10) > Ping to get this merged into the upcoming 5.4 release. Only regressions should be backported. This isn't one.
(In reply to Markus Trippelsdorf from comment #11) > (In reply to rhalbersma from comment #10) > > Ping to get this merged into the upcoming 5.4 release. > > Only regressions should be backported. This isn't one. s/regressions/regression fixes/
This is still not working for me in g++ 6 and 7: constexpr void foo( bool ok ) { if( ok ) return; throw; } In function ‘constexpr void foo(bool)’: error: expression ‘<throw-expression>’ is not a constant-expression Rewriting the code as: constexpr void foo( bool ok ) { if( ok ) return; else throw; } gets rid of the error, but this can be really awkward to do in more complicated functions.
Please reopen! Only a part of this bug is fixed: constexpr int f(){ if(false) throw 0; return 0; } int main(){ constexpr auto i = f(); } is OK now, but constexpr int f(){ if(true) return 0; throw 0; } int main(){ constexpr auto i = f(); } still fails. Tested with: $ g++ --version g++ (GCC) 8.0.0 20170818 (experimental) Copyright (C) 2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
This seems to have been solved entirely with the release of 9.1! So it should remain closed. (8.3 is still broken)
I'd guess it was fixed by the patch for PR 86678.
(In reply to Jonathan Wakely from comment #16) > I'd guess it was fixed by the patch for PR 86678. Confirmed, it was fixed by r264171 for PR 86678.