Commit 1259cb6d by Jakub Jelinek Committed by Jakub Jelinek

Implement P1002R1, Try-catch blocks in constexpr functions PR c++/89513

	Implement P1002R1, Try-catch blocks in constexpr functions
	PR c++/89513
	* parser.c (cp_parser_ctor_initializer_opt_and_function_body):
	Diagnose constexpr ctor or function with function-try-block with
	pedwarn for c++17 and earlier.  Formatting fix.
	(cp_parser_try_block): Use pedwarn instead of error and only for
	c++17 and earlier when try block appears in constexpr function.
	* constexpr.c (build_constexpr_constructor_member_initializers):
	Handle TRY_BLOCK here instead of erroring on it.

	* g++.dg/cpp2a/constexpr-try1.C: New test.
	* g++.dg/cpp2a/constexpr-try2.C: New test.
	* g++.dg/cpp2a/constexpr-try3.C: New test.
	* g++.dg/cpp2a/constexpr-try4.C: New test.
	* g++.dg/cpp2a/constexpr-try5.C: New test.
	* g++.dg/cpp0x/constexpr-ctor10.C: Don't expect error for C++2a.

From-SVN: r269314
parent c5effe96
2019-03-01 Jakub Jelinek <jakub@redhat.com>
Implement P1002R1, Try-catch blocks in constexpr functions
PR c++/89513
* parser.c (cp_parser_ctor_initializer_opt_and_function_body):
Diagnose constexpr ctor or function with function-try-block with
pedwarn for c++17 and earlier. Formatting fix.
(cp_parser_try_block): Use pedwarn instead of error and only for
c++17 and earlier when try block appears in constexpr function.
* constexpr.c (build_constexpr_constructor_member_initializers):
Handle TRY_BLOCK here instead of erroring on it.
2019-02-28 Jason Merrill <jason@redhat.com>
PR c++/88183 - ICE with .* fold-expression.
......
......@@ -601,6 +601,12 @@ build_constexpr_constructor_member_initializers (tree type, tree body)
gcc_unreachable ();
}
found:
if (TREE_CODE (body) == TRY_BLOCK)
{
body = TREE_OPERAND (body, 0);
if (TREE_CODE (body) == BIND_EXPR)
body = BIND_EXPR_BODY (body);
}
if (TREE_CODE (body) == CLEANUP_POINT_EXPR)
{
body = TREE_OPERAND (body, 0);
......@@ -626,12 +632,6 @@ build_constexpr_constructor_member_initializers (tree type, tree body)
break;
}
}
else if (TREE_CODE (body) == TRY_BLOCK)
{
error ("body of %<constexpr%> constructor cannot be "
"a function-try-block");
return error_mark_node;
}
else if (EXPR_P (body))
ok = build_data_member_initialization (body, &vec);
else
......
......@@ -22590,11 +22590,25 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser,
bool in_function_try_block)
{
tree body, list;
const bool check_body_p =
DECL_CONSTRUCTOR_P (current_function_decl)
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl);
const bool check_body_p
= (DECL_CONSTRUCTOR_P (current_function_decl)
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl));
tree last = NULL;
if (in_function_try_block
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl)
&& cxx_dialect < cxx2a)
{
if (DECL_CONSTRUCTOR_P (current_function_decl))
pedwarn (input_location, 0,
"function-try-block body of %<constexpr%> constructor only "
"available with -std=c++2a or -std=gnu++2a");
else
pedwarn (input_location, 0,
"function-try-block body of %<constexpr%> function only "
"available with -std=c++2a or -std=gnu++2a");
}
/* Begin the function body. */
body = begin_function_body ();
/* Parse the optional ctor-initializer. */
......@@ -25329,8 +25343,11 @@ cp_parser_try_block (cp_parser* parser)
cp_parser_require_keyword (parser, RID_TRY, RT_TRY);
if (parser->in_function_body
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl))
error ("%<try%> in %<constexpr%> function");
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl)
&& cxx_dialect < cxx2a)
pedwarn (input_location, 0,
"%<try%> in %<constexpr%> function only "
"available with -std=c++2a or -std=gnu++2a");
try_block = begin_try_block ();
cp_parser_compound_statement (parser, NULL, BCS_TRY_BLOCK, false);
2019-03-01 Jakub Jelinek <jakub@redhat.com>
Implement P1002R1, Try-catch blocks in constexpr functions
PR c++/89513
* g++.dg/cpp2a/constexpr-try1.C: New test.
* g++.dg/cpp2a/constexpr-try2.C: New test.
* g++.dg/cpp2a/constexpr-try3.C: New test.
* g++.dg/cpp2a/constexpr-try4.C: New test.
* g++.dg/cpp2a/constexpr-try5.C: New test.
* g++.dg/cpp0x/constexpr-ctor10.C: Don't expect error for C++2a.
2019-03-01 Richard Sandiford <richard.sandiford@arm.com>
PR tree-optimization/89535
......
......@@ -2,5 +2,5 @@
// { dg-do compile { target c++11 } }
struct foo {
constexpr foo() try { } catch(...) { }; // { dg-error "constexpr" }
constexpr foo() try { } catch(...) { }; // { dg-error "constexpr" "" { target c++17_down } }
};
// PR c++/89513
// { dg-do compile { target c++11 } }
constexpr bool foo ()
try { // { dg-error "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
return true;
} catch (...) { // { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } }
return false;
} // { dg-error "body of 'constexpr' function" "" { target c++11_only } }
constexpr bool bar ()
try { // { dg-error "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
try { // { dg-error "'try' in 'constexpr' function only available with" "" { target c++17_down } }
return true; // { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } .-1 }
} catch (int) { // { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } }
return false;
}
} catch (...) { // { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } }
return false;
} // { dg-error "not a return-statement" "" { target c++11_only } }
constexpr bool baz ()
{
try { return true; } catch (...) { return false; } // { dg-error "'try' in 'constexpr' function only available with" "" { target c++17_down } }
} // { dg-error "not a return-statement" "" { target c++11_only } }
// { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } .-2 }
struct S {
constexpr S () try : m (1) // { dg-error "function-try-block body of 'constexpr' constructor only available with" "" { target c++17_down } }
{
try { // { dg-error "'try' in 'constexpr' function only available with" "" { target c++17_down } }
} catch (int) { // { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } }
} // { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } .-2 }
} catch (...) { // { dg-error "'constexpr' constructor does not have empty body" "" { target c++11_only } }
}
int m;
};
struct T {
constexpr T ()
try { // { dg-error "function-try-block body of 'constexpr' constructor only available with" "" { target c++17_down } }
} catch (...) { // { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } }
}
};
// PR c++/89513
// { dg-do compile { target c++11 } }
// { dg-options "-pedantic" }
constexpr bool foo ()
try { // { dg-warning "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
return true;
} catch (...) { // { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } }
return false;
} // { dg-error "body of 'constexpr' function" "" { target c++11_only } }
constexpr bool bar ()
try { // { dg-warning "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
return true; // { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } .-1 }
} catch (int) { // { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } }
return false;
}
} catch (...) { // { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } }
return false;
} // { dg-error "not a return-statement" "" { target c++11_only } }
constexpr bool baz ()
{
try { return true; } catch (...) { return false; } // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
} // { dg-error "not a return-statement" "" { target c++11_only } }
// { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } .-2 }
struct S {
constexpr S () try : m (1) // { dg-warning "function-try-block body of 'constexpr' constructor only available with" "" { target c++17_down } }
{
try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
} catch (int) { // { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } }
} // { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } .-2 }
} catch (...) { // { dg-error "'constexpr' constructor does not have empty body" "" { target c++11_only } }
}
int m;
};
struct T {
constexpr T ()
try { // { dg-warning "function-try-block body of 'constexpr' constructor only available with" "" { target c++17_down } }
} catch (...) { // { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } }
}
};
// PR c++/89513
// { dg-do compile { target c++11 } }
// { dg-options "" }
constexpr bool foo ()
try { // { dg-warning "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
return true;
} catch (...) {
return false;
} // { dg-error "body of 'constexpr' function" "" { target c++11_only } }
constexpr bool bar ()
try { // { dg-warning "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
return true;
} catch (int) {
return false;
}
} catch (...) {
return false;
} // { dg-error "not a return-statement" "" { target c++11_only } }
constexpr bool baz ()
{
try { return true; } catch (...) { return false; } // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
} // { dg-error "not a return-statement" "" { target c++11_only } }
struct S {
constexpr S () try : m (1) // { dg-warning "function-try-block body of 'constexpr' constructor only available with" "" { target c++17_down } }
{
try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
} catch (int) {
}
} catch (...) { // { dg-error "'constexpr' constructor does not have empty body" "" { target c++11_only } }
}
int m;
};
struct T {
constexpr T ()
try { // { dg-warning "function-try-block body of 'constexpr' constructor only available with" "" { target c++17_down } }
} catch (...) {
}
};
// PR c++/89513
// { dg-do compile { target c++14 } }
// { dg-options "" }
constexpr int foo ()
try { // { dg-warning "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
int a = 1;
for (int i = 0; i < 10; i++)
a += i;
return a;
} catch (...) {
return -1;
}
constexpr int bar ()
try { // { dg-warning "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
int a = 0;
for (int i = 0; i < 9; i++)
try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
a += i;
} catch (int) {
return -1;
}
return a;
} catch (...) {
return -2;
}
constexpr bool baz ()
{
try { return true; } catch (...) { return false; } // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
}
struct S {
constexpr S () try : m (1) // { dg-warning "function-try-block body of 'constexpr' constructor only available with" "" { target c++17_down } }
{
try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
m += 2;
} catch (int) {
m = -1;
}
} catch (...) {
m = -2;
}
int m;
constexpr int get () const { return m; }
};
struct T {
constexpr T ()
try { // { dg-warning "function-try-block body of 'constexpr' constructor only available with" "" { target c++17_down } }
} catch (...) {
}
};
static_assert (foo () == 46, "");
static_assert (bar () == 36, "");
static_assert (baz (), "");
constexpr S s;
static_assert (s.get () == 3, "");
constexpr T t;
// PR c++/89513
// { dg-do compile { target c++14 } }
// { dg-options "" }
constexpr int foo ()
try { // { dg-warning "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
int a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" }
static double b = 1.0;// { dg-error "'b' declared 'static' in 'constexpr' function" }
goto l; // { dg-error "'goto' in 'constexpr' function" }
l:;
return 0;
} catch (...) {
long int c; // { dg-error "uninitialized variable 'c' in 'constexpr' function" }
static float d = 2.0f;// { dg-error "'d' declared 'static' in 'constexpr' function" }
goto l2; // { dg-error "'goto' in 'constexpr' function" }
l2:;
return -1;
}
constexpr int bar ()
{
int a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" }
static long double b = 3.0;// { dg-error "'b' declared 'static' in 'constexpr' function" }
goto l; // { dg-error "'goto' in 'constexpr' function" }
l:;
try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
short c; // { dg-error "uninitialized variable 'c' in 'constexpr' function" }
static float d; // { dg-error "'d' declared 'static' in 'constexpr' function" }
// { dg-error "uninitialized variable 'd' in 'constexpr' function" "" { target *-*-* } .-1 }
goto l2; // { dg-error "'goto' in 'constexpr' function" }
l2:;
return 0;
} catch (int) {
char e; // { dg-error "uninitialized variable 'e' in 'constexpr' function" }
static int f = 5; // { dg-error "'f' declared 'static' in 'constexpr' function" }
goto l3; // { dg-error "'goto' in 'constexpr' function" }
l3:;
return 1;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment