From e79fc3d4d72228eeec47b8a53721663371042b8e Mon Sep 17 00:00:00 2001 From: Edward Smith-Rowland <3dw4rd@verizon.net> Date: Wed, 24 Jun 2015 15:27:04 +0000 Subject: [PATCH] Implement N3928 - Extending static_assert cp/ 2015-06-24 Edward Smith-Rowland <3dw4rd@verizon.net> Implement N3928 - Extending static_assert * parser.c (cp_parser_static_assert): Support static_assert with no message string. Supply an empty string in this case. * semantics.c (finish_static_assert): Don't try to print a message if the message strnig is empty. testsuite/ 2015-06-24 Edward Smith-Rowland <3dw4rd@verizon.net> Implement N3928 - Extending static_assert * g++.dg/cpp0x/static_assert8.C: Adjust. * g++.dg/cpp0x/static_assert12.C: New. * g++.dg/cpp0x/static_assert13.C: New. * g++.dg/cpp1y/static_assert1.C: New. * g++.dg/cpp1y/static_assert2.C: New. * g++.dg/cpp1z/static_assert-nomsg.C: New. From-SVN: r224903 --- gcc/cp/ChangeLog | 8 ++++ gcc/cp/parser.c | 40 +++++++++++++------ gcc/cp/semantics.c | 13 +++++- gcc/testsuite/ChangeLog | 10 +++++ gcc/testsuite/g++.dg/cpp0x/static_assert12.C | 30 ++++++++++++++ gcc/testsuite/g++.dg/cpp0x/static_assert13.C | 28 +++++++++++++ gcc/testsuite/g++.dg/cpp0x/static_assert8.C | 4 +- gcc/testsuite/g++.dg/cpp1y/static_assert1.C | 30 ++++++++++++++ gcc/testsuite/g++.dg/cpp1y/static_assert2.C | 28 +++++++++++++ .../g++.dg/cpp1z/static_assert-nomsg.C | 27 +++++++++++++ 10 files changed, 203 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/static_assert12.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/static_assert13.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/static_assert1.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/static_assert2.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/static_assert-nomsg.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c9c3977a4ee..197bc77736a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2015-06-24 Edward Smith-Rowland <3dw4rd@verizon.net> + + Implement N3928 - Extending static_assert + * parser.c (cp_parser_static_assert): Support static_assert with + no message string. Supply an empty string in this case. + * semantics.c (finish_static_assert): Don't try to print a message if + the message strnig is empty. + 2015-06-24 Adam Butcher PR c++/65750 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 5150abeec23..e0e484a4c47 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -12173,6 +12173,7 @@ cp_parser_linkage_specification (cp_parser* parser) static_assert-declaration: static_assert ( constant-expression , string-literal ) ; + static_assert ( constant-expression ) ; (C++1Z) If MEMBER_P, this static_assert is a class member. */ @@ -12210,20 +12211,35 @@ cp_parser_static_assert(cp_parser *parser, bool member_p) /*allow_non_constant_p=*/true, /*non_constant_p=*/&dummy); - /* Parse the separating `,'. */ - cp_parser_require (parser, CPP_COMMA, RT_COMMA); + if (cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN) + { + if (cxx_dialect < cxx1z) + pedwarn (input_location, OPT_Wpedantic, + "static_assert without a message " + "only available with -std=c++1z or -std=gnu++1z"); + /* Eat the ')' */ + cp_lexer_consume_token (parser->lexer); + message = build_string (1, ""); + TREE_TYPE (message) = char_array_type_node; + fix_string_type (message); + } + else + { + /* Parse the separating `,'. */ + cp_parser_require (parser, CPP_COMMA, RT_COMMA); - /* Parse the string-literal message. */ - message = cp_parser_string_literal (parser, - /*translate=*/false, - /*wide_ok=*/true); + /* Parse the string-literal message. */ + message = cp_parser_string_literal (parser, + /*translate=*/false, + /*wide_ok=*/true); - /* A `)' completes the static assertion. */ - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) - cp_parser_skip_to_closing_parenthesis (parser, - /*recovering=*/true, - /*or_comma=*/false, - /*consume_paren=*/true); + /* A `)' completes the static assertion. */ + if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + } /* A semicolon terminates the declaration. */ cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index aeb5f7ba298..c0abeaba1c4 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -7174,8 +7174,17 @@ finish_static_assert (tree condition, tree message, location_t location, input_location = location; if (TREE_CODE (condition) == INTEGER_CST && integer_zerop (condition)) - /* Report the error. */ - error ("static assertion failed: %s", TREE_STRING_POINTER (message)); + { + int sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT + (TREE_TYPE (TREE_TYPE (message)))); + int len = TREE_STRING_LENGTH (message) / sz - 1; + /* Report the error. */ + if (len == 0) + error ("static assertion failed"); + else + error ("static assertion failed: %s", + TREE_STRING_POINTER (message)); + } else if (condition && condition != error_mark_node) { error ("non-constant condition for static assertion"); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index af6d43aa445..26d39ce9afd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2015-06-24 Edward Smith-Rowland <3dw4rd@verizon.net> + + Implement N3928 - Extending static_assert + * g++.dg/cpp0x/static_assert8.C: Adjust. + * g++.dg/cpp0x/static_assert12.C: New. + * g++.dg/cpp0x/static_assert13.C: New. + * g++.dg/cpp1y/static_assert1.C: New. + * g++.dg/cpp1y/static_assert2.C: New. + * g++.dg/cpp1z/static_assert-nomsg.C: New. + 2015-06-24 Adam Butcher PR c++/65750 diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert12.C b/gcc/testsuite/g++.dg/cpp0x/static_assert12.C new file mode 100644 index 00000000000..ff6f40d918f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/static_assert12.C @@ -0,0 +1,30 @@ +// { dg-do compile } +// { dg-options "-std=gnu++11 -pedantic" } + +template + struct is_float + { + static constexpr bool value = false; + }; + +template<> + struct is_float + { + static constexpr bool value = true; + }; + +template + T + float_thing(T __x) + { + static_assert(is_float::value, ""); // { dg-error "static assertion failed" } + static_assert(is_float::value); // { dg-error "static assertion failed" } + } + +int +main() +{ + float_thing(1); +} + +// { dg-warning "static_assert without a message only available with " "" { target *-*-* } 21 } diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert13.C b/gcc/testsuite/g++.dg/cpp0x/static_assert13.C new file mode 100644 index 00000000000..86b0b0360d9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/static_assert13.C @@ -0,0 +1,28 @@ +// { dg-do compile } +// { dg-options "-std=gnu++11" } + +template + struct is_float + { + static constexpr bool value = false; + }; + +template<> + struct is_float + { + static constexpr bool value = true; + }; + +template + T + float_thing(T __x) + { + static_assert(is_float::value, ""); // { dg-error "static assertion failed" } + static_assert(is_float::value); // { dg-error "static assertion failed" } + } + +int +main() +{ + float_thing(1); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert8.C b/gcc/testsuite/g++.dg/cpp0x/static_assert8.C index ea23afb857d..972f859d6ef 100644 --- a/gcc/testsuite/g++.dg/cpp0x/static_assert8.C +++ b/gcc/testsuite/g++.dg/cpp0x/static_assert8.C @@ -1,7 +1,9 @@ // { dg-do compile { target c++11 } } -static_assert (1 == 0); // { dg-error "expected (string-literal|',') before" } +static_assert (1 == 0); // { dg-error "static assertion failed" } static_assert (1 == 0,); // { dg-error "expected string-literal before '\\)'" } static_assert (1 == 0, "oops"); // { dg-error "static assertion failed" } + +// { dg-error "static_assert without a message only available with " "" { target *-*-* } 3 } diff --git a/gcc/testsuite/g++.dg/cpp1y/static_assert1.C b/gcc/testsuite/g++.dg/cpp1y/static_assert1.C new file mode 100644 index 00000000000..513e347d7e5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/static_assert1.C @@ -0,0 +1,30 @@ +// { dg-do compile } +// { dg-options "-std=gnu++14 -pedantic" } + +template + struct is_float + { + static constexpr bool value = false; + }; + +template<> + struct is_float + { + static constexpr bool value = true; + }; + +template + T + float_thing(T __x) + { + static_assert(is_float::value, ""); // { dg-error "static assertion failed" } + static_assert(is_float::value); // { dg-error "static assertion failed" } + } + +int +main() +{ + float_thing(1); +} + +// { dg-warning "static_assert without a message only available with " "" { target *-*-* } 21 } diff --git a/gcc/testsuite/g++.dg/cpp1y/static_assert2.C b/gcc/testsuite/g++.dg/cpp1y/static_assert2.C new file mode 100644 index 00000000000..d862282cda8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/static_assert2.C @@ -0,0 +1,28 @@ +// { dg-do compile } +// { dg-options "-std=gnu++14" } + +template + struct is_float + { + static constexpr bool value = false; + }; + +template<> + struct is_float + { + static constexpr bool value = true; + }; + +template + T + float_thing(T __x) + { + static_assert(is_float::value, ""); // { dg-error "static assertion failed" } + static_assert(is_float::value); // { dg-error "static assertion failed" } + } + +int +main() +{ + float_thing(1); +} diff --git a/gcc/testsuite/g++.dg/cpp1z/static_assert-nomsg.C b/gcc/testsuite/g++.dg/cpp1z/static_assert-nomsg.C new file mode 100644 index 00000000000..3d12e184675 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/static_assert-nomsg.C @@ -0,0 +1,27 @@ +// { dg-do compile { target c++1z } } + +template + struct is_float + { + static constexpr bool value = false; + }; + +template<> + struct is_float + { + static constexpr bool value = true; + }; + +template + T + float_thing(T __x) + { + static_assert(is_float::value, ""); // { dg-error "static assertion failed" } + static_assert(is_float::value); // { dg-error "static assertion failed" } + } + +int +main() +{ + float_thing(1); +} -- 2.30.2