commit 02d12daad9a5d1b265a328e43d758d9eedd9bb04
Author: Jason Merrill <jason@redhat.com>
Date: Tue Jun 21 22:24:29 2011 -0400
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.
@@ -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);
@@ -1,3 +1,3 @@
// { dg-options -std=c++0x }
int x;
-constexpr int& rx = x; // { dg-error "int&" }
+constexpr int& rx = x;
new file mode 100644
@@ -0,0 +1,44 @@
+// 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>();
new file mode 100644
@@ -0,0 +1,17 @@
+// 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 "" }
+}
+