aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-06-22 00:18:02 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-06-22 00:18:02 -0400
commitda7d921819a3e2ba17fd01d93fedf1cd4e2a5819 (patch)
treeec54c4196b5464b246ae415206f98a796fd8bc2d
parent584dd700750ea6be613de4ae449726a08169eff6 (diff)
downloadgcc-da7d921819a3e2ba17fd01d93fedf1cd4e2a5819.zip
gcc-da7d921819a3e2ba17fd01d93fedf1cd4e2a5819.tar.gz
gcc-da7d921819a3e2ba17fd01d93fedf1cd4e2a5819.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/call.c16
-rw-r--r--gcc/cp/decl.c12
-rw-r--r--gcc/cp/parser.c10
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ref1.C44
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ref2.C17
8 files changed, 96 insertions, 17 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index cf325fc..a329733 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,12 @@
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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 8123e3d..dd4dced 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 263ab3f..b8435a6 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 856a8a7..f1b7976 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 59464fa..fae9f95 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
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.
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C
index 35643b9..856246f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C
@@ -1,3 +1,3 @@
// { dg-options -std=c++0x }
int x;
-constexpr int& rx = x; // { dg-error "int&" }
+constexpr int& rx = x;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref1.C
new file mode 100644
index 0000000..482e1ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref1.C
@@ -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>();
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref2.C
new file mode 100644
index 0000000..2a86eb7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref2.C
@@ -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 "" }
+}
+