Commit da7d9218 by Jason Merrill Committed by Jason Merrill

re PR c++/49172 ([C++0x][constexpr] References should be declarable with constexpr)

	PR c++/49172
	* decl.c (cp_finish_decl): Adjust init_const_expr_p for refs.
	(grokdeclarator): constexpr doesn't apply const for refs.
	* parser.c (cp_parser_initializer_clause): Don't call
	maybe_constant_value here.
	* call.c (initialize_reference): Handle constexpr.

From-SVN: r175284
parent 584dd700
2011-06-21 Jason Merrill <jason@redhat.com>
PR c++/49172
* decl.c (cp_finish_decl): Adjust init_const_expr_p for refs.
(grokdeclarator): constexpr doesn't apply const for refs.
* parser.c (cp_parser_initializer_clause): Don't call
maybe_constant_value here.
* call.c (initialize_reference): Handle constexpr.
PR c++/49482
* semantics.c (maybe_add_lambda_conv_op): Call mark_exp_read for
static fn parameters.
......
......@@ -8629,6 +8629,8 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup,
tree var;
tree base_conv_type;
gcc_assert (complain == tf_warning_or_error);
/* Skip over the REF_BIND. */
conv = conv->u.next;
/* If the next conversion is a BASE_CONV, skip that too -- but
......@@ -8646,7 +8648,7 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup,
/*inner=*/-1,
/*issue_conversion_warnings=*/true,
/*c_cast_p=*/false,
tf_warning_or_error);
complain);
if (error_operand_p (expr))
expr = error_mark_node;
else
......@@ -8667,18 +8669,24 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup,
}
else
/* Take the address of EXPR. */
expr = cp_build_addr_expr (expr, tf_warning_or_error);
expr = cp_build_addr_expr (expr, complain);
/* If a BASE_CONV was required, perform it now. */
if (base_conv_type)
expr = (perform_implicit_conversion
(build_pointer_type (base_conv_type), expr,
tf_warning_or_error));
complain));
expr = build_nop (type, expr);
if (DECL_DECLARED_CONSTEXPR_P (decl))
{
expr = cxx_constant_value (expr);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)
= reduced_constant_expression_p (expr);
}
}
}
else
/* Perform the conversion. */
expr = convert_like (conv, expr, tf_warning_or_error);
expr = convert_like (conv, expr, complain);
/* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p);
......
......@@ -5987,6 +5987,11 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
if (init && TREE_CODE (decl) == VAR_DECL)
{
DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1;
/* If DECL is a reference, then we want to know whether init is a
reference constant; init_const_expr_p as passed tells us whether
it's an rvalue constant. */
if (TREE_CODE (type) == REFERENCE_TYPE)
init_const_expr_p = potential_constant_expression (init);
if (init_const_expr_p)
{
/* Set these flags now for templates. We'll update the flags in
......@@ -9333,8 +9338,11 @@ grokdeclarator (const cp_declarator *declarator,
error ("both %<const%> and %<constexpr%> cannot be used here");
if (type_quals & TYPE_QUAL_VOLATILE)
error ("both %<volatile%> and %<constexpr%> cannot be used here");
type_quals |= TYPE_QUAL_CONST;
type = cp_build_qualified_type (type, type_quals);
if (TREE_CODE (type) != REFERENCE_TYPE)
{
type_quals |= TYPE_QUAL_CONST;
type = cp_build_qualified_type (type, type_quals);
}
}
if (unqualified_id && TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR
......
......@@ -16532,16 +16532,6 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
= cp_parser_constant_expression (parser,
/*allow_non_constant_p=*/true,
non_constant_p);
if (!*non_constant_p)
{
/* We only want to fold if this is really a constant
expression. FIXME Actually, we don't want to fold here, but in
cp_finish_decl. */
tree folded = fold_non_dependent_expr (initializer);
folded = maybe_constant_value (folded);
if (TREE_CONSTANT (folded))
initializer = folded;
}
}
else
initializer = cp_parser_braced_list (parser, non_constant_p);
......
2011-06-21 Jason Merrill <jason@redhat.com>
PR c++/49172
* g++.dg/cpp0x/constexpr-ref1.C: New.
* g++.dg/cpp0x/constexpr-ref2.C: New.
* g++.dg/cpp0x/constexpr-ice2.C: Remove dg-error tag.
PR c++/49482
* g++.dg/cpp0x/lambda/lambda-warn3.C: New.
......
// { dg-options -std=c++0x }
int x;
constexpr int& rx = x; // { dg-error "int&" }
constexpr int& rx = x;
// PR c++/49172
// { dg-options -std=c++0x }
#define SA(X) static_assert((X),#X)
constexpr int g() { return 42; };
constexpr int(&rg)() = g; // #1
SA(rg() == 42);
constexpr int i = 24;
constexpr int const& ri = i; // #2
SA(&ri == &i);
SA(ri == 24);
void f()
{
constexpr int(&rg)() = g; // #1
SA(rg() == 42);
constexpr static int i = 24;
constexpr int const& ri = i; // #2
SA(&ri == &i);
SA(ri == 24);
}
template <class T>
void f2()
{
constexpr int(&rg)() = g; // #1
SA(rg() == 42);
constexpr static int i = 24;
constexpr int const& ri = i; // #2
SA(&ri == &i);
SA(ri == 24);
}
template void f2<int>();
// Negative reference variable tests.
// { dg-options -std=c++0x }
extern int *p;
constexpr int& ri = *p; // { dg-error "p" }
extern constexpr int &er; // { dg-error "not a definition" }
constexpr int& ri2 = er; // { dg-error "er" }
void f(int j)
{
constexpr int i = 42;
constexpr int const& ri = i; // { dg-error "" }
constexpr int& rj = j; // { dg-error "" }
}
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