Index: cp/parser.c =================================================================== --- cp/parser.c (revision 224897) +++ cp/parser.c (working copy) @@ -12173,6 +12173,7 @@ 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 @@ /*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); Index: cp/semantics.c =================================================================== --- cp/semantics.c (revision 224897) +++ cp/semantics.c (working copy) @@ -7174,8 +7174,17 @@ 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"); Index: testsuite/g++.dg/cpp0x/static_assert12.C =================================================================== --- testsuite/g++.dg/cpp0x/static_assert12.C (revision 0) +++ testsuite/g++.dg/cpp0x/static_assert12.C (working copy) @@ -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 } Index: testsuite/g++.dg/cpp0x/static_assert13.C =================================================================== --- testsuite/g++.dg/cpp0x/static_assert13.C (revision 0) +++ testsuite/g++.dg/cpp0x/static_assert13.C (working copy) @@ -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); +} Index: testsuite/g++.dg/cpp0x/static_assert8.C =================================================================== --- testsuite/g++.dg/cpp0x/static_assert8.C (revision 224897) +++ testsuite/g++.dg/cpp0x/static_assert8.C (working copy) @@ -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 } Index: testsuite/g++.dg/cpp1y/static_assert1.C =================================================================== --- testsuite/g++.dg/cpp1y/static_assert1.C (revision 0) +++ testsuite/g++.dg/cpp1y/static_assert1.C (working copy) @@ -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 } Index: testsuite/g++.dg/cpp1y/static_assert2.C =================================================================== --- testsuite/g++.dg/cpp1y/static_assert2.C (revision 0) +++ testsuite/g++.dg/cpp1y/static_assert2.C (working copy) @@ -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); +} Index: testsuite/g++.dg/cpp1z/static_assert-nomsg.C =================================================================== --- testsuite/g++.dg/cpp1z/static_assert-nomsg.C (revision 0) +++ testsuite/g++.dg/cpp1z/static_assert-nomsg.C (working copy) @@ -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); +}