If we handle PTRMEM_CST specially, we also need to handle any
CONSTRUCTORs that wrap them.
Tested x86_64-pc-linux-gnu, applying to trunk and 4.9.
commit a2f90f6d52fa4c3d5391b23914c4177c3272817c
Author: Jason Merrill <ja...@redhat.com>
Date: Thu Jul 10 17:05:28 2014 -0400
PR c++/61661
* semantics.c (reduced_constant_expression_p): Handle CONSTRUCTOR.
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index a6f5a4a..a6d941b 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -8519,11 +8519,24 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
bool
reduced_constant_expression_p (tree t)
{
- if (TREE_CODE (t) == PTRMEM_CST)
- /* Even if we can't lower this yet, it's constant. */
- return true;
- /* FIXME are we calling this too much? */
- return initializer_constant_valid_p (t, TREE_TYPE (t)) != NULL_TREE;
+ switch (TREE_CODE (t))
+ {
+ case PTRMEM_CST:
+ /* Even if we can't lower this yet, it's constant. */
+ return true;
+
+ case CONSTRUCTOR:
+ /* And we need to handle PTRMEM_CST wrapped in a CONSTRUCTOR. */
+ tree elt; unsigned HOST_WIDE_INT idx;
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (t), idx, elt)
+ if (!reduced_constant_expression_p (elt))
+ return false;
+ return true;
+
+ default:
+ /* FIXME are we calling this too much? */
+ return initializer_constant_valid_p (t, TREE_TYPE (t)) != NULL_TREE;
+ }
}
/* Some expressions may have constant operands but are not constant
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem2.C
new file mode 100644
index 0000000..86859aa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem2.C
@@ -0,0 +1,13 @@
+// PR c++/61661
+// { dg-do compile { target c++11 } }
+
+struct Outer {
+
+ void Bar();
+
+ struct Foo {
+ void (Outer::*ptr)() ;
+ };
+
+ static constexpr Foo foo = { &Outer::Bar };
+};