+2014-10-09 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * semantics.c (check_constexpr_ctor_body_1): New.
+ (check_constexpr_ctor_body): Use it; add bool parameter.
+ (build_data_member_initialization): Handle BIND_EXPR and
+ USING_STMT in the main conditional.
+ (build_constexpr_constructor_member_initializers): Do not
+ handle BIND_EXPR here.
+ (constexpr_fn_retval): Handle BIND_EXPR in the switch.
+ (massage_constexpr_body): Don't do it here.
+ * parser.c (cp_parser_ctor_initializer_opt_and_function_body):
+ Adjust check_constexpr_ctor_body call.
+ (cp_parser_compound_statement): Do not pedwarn for compound-statement
+ in constexpr function in C++14 mode.
+ * cp-tree.h (check_constexpr_ctor_body): Update declaration.
+
2014-10-09 Jason Merrill <jason@redhat.com>
PR c++/63309
extern void finish_cleanup (tree, tree);
extern bool literal_type_p (tree);
extern tree register_constexpr_fundef (tree, tree);
-extern bool check_constexpr_ctor_body (tree, tree);
+extern bool check_constexpr_ctor_body (tree, tree, bool);
extern tree ensure_literal_type_for_constexpr_object (tree);
extern bool potential_constant_expression (tree);
extern bool potential_rvalue_constant_expression (tree);
if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
return error_mark_node;
if (DECL_DECLARED_CONSTEXPR_P (current_function_decl)
- && !function_body)
+ && !function_body && cxx_dialect < cxx14)
pedwarn (input_location, OPT_Wpedantic,
"compound-statement in constexpr function");
/* Begin the compound-statement. */
/* Parse the function-body. */
cp_parser_function_body (parser, in_function_try_block);
if (check_body_p)
- check_constexpr_ctor_body (last, list);
+ check_constexpr_ctor_body (last, list, /*complain=*/true);
/* Finish the function body. */
finish_function_body (body);
wrong type, but cxx_eval_constant_expression doesn't care. */
init = break_out_target_exprs (t);
}
- else if (TREE_CODE (t) == DECL_EXPR)
- /* Declaring a temporary, don't add it to the CONSTRUCTOR. */
+ else if (TREE_CODE (t) == BIND_EXPR)
+ return build_data_member_initialization (BIND_EXPR_BODY (t), vec);
+ else if (TREE_CODE (t) == DECL_EXPR
+ || TREE_CODE (t) == USING_STMT)
+ /* Declaring a temporary, don't add it to the CONSTRUCTOR.
+ Likewise for using directives. */
return true;
else
gcc_unreachable ();
return true;
}
-/* Subroutine of check_constexpr_ctor_body and massage_constexpr_body.
+/* Subroutine of check_constexpr_ctor_body_1 and constexpr_fn_retval.
In C++11 mode checks that the TYPE_DECLs in the BIND_EXPR_VARS of a
BIND_EXPR conform to 7.1.5/3/4 on typedef and alias declarations. */
return true;
}
+/* Subroutine of check_constexpr_ctor_body. */
+
+static bool
+check_constexpr_ctor_body_1 (tree last, tree list)
+{
+ switch (TREE_CODE (list))
+ {
+ case DECL_EXPR:
+ if (TREE_CODE (DECL_EXPR_DECL (list)) == USING_DECL)
+ return true;
+ if (cxx_dialect >= cxx14)
+ return true;
+ return false;
+
+ case CLEANUP_POINT_EXPR:
+ return check_constexpr_ctor_body (last, TREE_OPERAND (list, 0),
+ /*complain=*/false);
+
+ case BIND_EXPR:
+ if (!check_constexpr_bind_expr_vars (list)
+ || !check_constexpr_ctor_body (last, BIND_EXPR_BODY (list),
+ /*complain=*/false))
+ return false;
+ return true;
+
+ case USING_STMT:
+ case STATIC_ASSERT:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
/* Make sure that there are no statements after LAST in the constructor
body represented by LIST. */
bool
-check_constexpr_ctor_body (tree last, tree list)
+check_constexpr_ctor_body (tree last, tree list, bool complain)
{
bool ok = true;
if (TREE_CODE (list) == STATEMENT_LIST)
tree t = tsi_stmt (i);
if (t == last)
break;
- if (TREE_CODE (t) == BIND_EXPR)
- {
- if (!check_constexpr_bind_expr_vars (t))
- {
- ok = false;
- break;
- }
- if (!check_constexpr_ctor_body (last, BIND_EXPR_BODY (t)))
- return false;
- else
- continue;
- }
- if (TREE_CODE (t) != STATIC_ASSERT)
+ if (!check_constexpr_ctor_body_1 (last, t))
{
ok = false;
break;
}
}
else if (list != last
- && TREE_CODE (list) != STATIC_ASSERT)
+ && !check_constexpr_ctor_body_1 (last, list))
ok = false;
if (!ok)
{
- error ("constexpr constructor does not have empty body");
+ if (complain)
+ error ("constexpr constructor does not have empty body");
DECL_DECLARED_CONSTEXPR_P (current_function_decl) = false;
}
return ok;
"a function-try-block");
return error_mark_node;
}
- else if (TREE_CODE (body) == BIND_EXPR)
- ok = build_data_member_initialization (BIND_EXPR_BODY (body), &vec);
else if (EXPR_P (body))
ok = build_data_member_initialization (body, &vec);
else
case CLEANUP_POINT_EXPR:
return constexpr_fn_retval (TREE_OPERAND (body, 0));
+ case BIND_EXPR:
+ if (!check_constexpr_bind_expr_vars (body))
+ return error_mark_node;
+ return constexpr_fn_retval (BIND_EXPR_BODY (body));
+
case USING_STMT:
return NULL_TREE;
body = EH_SPEC_STMTS (body);
if (TREE_CODE (body) == MUST_NOT_THROW_EXPR)
body = TREE_OPERAND (body, 0);
- if (TREE_CODE (body) == BIND_EXPR
- && check_constexpr_bind_expr_vars (body))
- body = BIND_EXPR_BODY (body);
body = constexpr_fn_retval (body);
}
return body;
+2014-10-09 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.dg/cpp0x/constexpr-using3.C: New.
+ * g++.dg/cpp1y/constexpr-local-compound1.C: Likewise.
+ * g++.dg/cpp1y/constexpr-type-def-compound1.C: Likewise.
+ * g++.dg/cpp1y/constexpr-local1.C: Extend.
+ * g++.dg/cpp0x/constexpr-compound.C: Specify expected error.
+
2014-10-09 Joseph Myers <joseph@codesourcery.com>
* gcc.dg/torture/float128-extendxf-underflow.c: New test.
constexpr int f()
{
- { // { dg-error "" }
+ { // { dg-error "compound-statement" "" { target { c++11_only } } }
return 1;
}
- { } // { dg-error "" }
+ { } // { dg-error "compound-statement" "" { target { c++11_only } } }
}
--- /dev/null
+// { dg-do compile { target c++11 } }
+// { dg-options "-pedantic" }
+
+namespace ns { typedef int T; }
+
+constexpr int Test1(int x) { using ns::T; typedef T U; return U(x); }
+constexpr int Test2(int x) { using namespace ns; typedef T U; return U(x); }
+constexpr int Test3(int x) { { using ns::T; typedef T U; return U(x); } } // { dg-warning "compound-statement" "" { target { c++11_only } } }
+constexpr int Test4(int x) { { using namespace ns; typedef T U; return T(x); } } // { dg-warning "compound-statement" "" { target { c++11_only } } }
+
+struct S1
+{
+ constexpr S1() { using ns::T; typedef T U; }
+};
+
+struct S2
+{
+ constexpr S2() { using namespace ns; typedef T U; }
+};
+
+struct S3
+{
+ constexpr S3() { { using ns::T; typedef T U; } } // { dg-warning "compound-statement" "" { target { c++11_only } } }
+};
+
+struct S4
+{
+ constexpr S4() { { using namespace ns; typedef T U; } } // { dg-warning "compound-statement" "" { target { c++11_only } } }
+};
--- /dev/null
+// { dg-do compile { target c++14 } }
+
+#define SA(X) static_assert((X),#X)
+
+constexpr int f(int i) { { int j = i+1; return j; } }
+
+constexpr int i = f(41);
+
+struct S
+{
+ constexpr S() { { constexpr int j = 17; SA(j == 17); } }
+};
+
+SA(i==42);
// { dg-do compile { target c++14 } }
+#define SA(X) static_assert((X),#X)
+
constexpr int f(int i) { int j = i+1; return j; }
constexpr int i = f(41);
-#define SA(X) static_assert((X),#X)
+struct S
+{
+ constexpr S() { constexpr int j = 17; SA(j == 17); }
+};
SA(i==42);
--- /dev/null
+// PR c++/55250
+// { dg-do compile { target c++14 } }
+
+#define SA(X) static_assert((X),#X)
+
+constexpr int Test1(int x) { { enum E { y = 1 }; return x + y; } }
+
+constexpr int Test2(int x) { { struct T { constexpr operator int() { return 1; } }; return x + T(); } }
+
+constexpr int Test3(int x) { { typedef enum E { y = 1 } EE; return x + EE::y; } }
+
+constexpr int Test4(int x) { { typedef struct T { constexpr operator int() { return 1; } } TT; return x + TT(); } }
+
+constexpr int Test5(int x) { { using EE = enum E { y = 1 }; return x + EE::y; } }
+
+constexpr int Test6(int x) { { using TT = struct T { constexpr operator int() { return 1; } }; return x + TT(); } }
+
+SA(Test1(2) == 3);
+SA(Test2(2) == 3);
+SA(Test3(2) == 3);
+SA(Test4(2) == 3);
+SA(Test5(2) == 3);
+SA(Test6(2) == 3);
+
+struct S1
+{
+ constexpr S1() { { enum E { y = 1 }; SA(y == 1); } }
+};
+
+struct S2
+{
+ constexpr S2() { { struct T { constexpr operator int() { return 1; } }; SA(T() == 1); } }
+};
+
+struct S3
+{
+ constexpr S3() { { typedef enum E { y = 1} EE; SA(EE::y == 1); } }
+};
+
+struct S4
+{
+ constexpr S4() { { typedef struct T { constexpr operator int() { return 1; } } TT; SA(TT() == 1); } }
+};
+
+struct S5
+{
+ constexpr S5() { { using EE = enum E { y = 1}; SA(EE::y == 1); } }
+};
+
+struct S6
+{
+ constexpr S6() { { using TT = struct T { constexpr operator int() { return 1; } }; SA(TT() == 1); } }
+};
+
+S1 s1;
+S2 s2;
+S3 s3;
+S4 s4;
+S5 s5;
+S6 s6;