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.
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
/*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
}
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);
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
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
= 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;
--- /dev/null
+// 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>();
--- /dev/null
+// 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 "" }
+}
+