In this PR, the constexpr evaluator was confused by a parameter that changed to a reference type after the constant expression body was saved for later evaluation; we ended up trying to evaluate an address of an address, since we added one address on the caller side to pass to the invisible reference and another on the callee side to pass the value parameter to a reference parameter. Fixed by stripping the reference on the caller side.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 34ef3b1602847bb7e1af4b7c0eb918dcdfcfea97
Author: Jason Merrill <ja...@redhat.com>
Date:   Wed Feb 13 00:01:52 2013 -0500

    	PR c++/55879
    	* semantics.c (cxx_bind_parameters_in_call): Undo DECL_BY_REFERENCE.

diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 59a50f2..7d93d72 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -6512,6 +6512,15 @@ cxx_bind_parameters_in_call (const constexpr_call *old_call, tree t,
       if (i == 0 && DECL_CONSTRUCTOR_P (fun))
         goto next;
       x = get_nth_callarg (t, i);
+      if (parms && DECL_BY_REFERENCE (parms))
+	{
+	  /* cp_genericize made this a reference for argument passing, but
+	     we don't want to treat it like one for constexpr evaluation.  */
+	  gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
+	  gcc_assert (TREE_CODE (TREE_TYPE (x)) == REFERENCE_TYPE);
+	  type = TREE_TYPE (type);
+	  x = convert_from_reference (x);
+	}
       arg = cxx_eval_constant_expression (old_call, x, allow_non_constant,
 					  TREE_CODE (type) == REFERENCE_TYPE,
 					  non_constant_p, overflow_p);
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-invisiref1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-invisiref1.C
new file mode 100644
index 0000000..e0ede73
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-invisiref1.C
@@ -0,0 +1,36 @@
+// PR c++/55879
+// { dg-do compile { target c++11 } }
+
+class CAddress
+{
+public:
+  constexpr CAddress(unsigned long begin) : m_Begin(begin) {}
+  constexpr CAddress(const CAddress &other) : m_Begin(other.m_Begin) {}
+
+private:
+  unsigned long m_Begin;
+};
+
+extern "C" char _lnkDDRRAM;
+/* internal compiler error on gcc 4.6.3 */
+const CAddress s_Memmap[2]
+{
+  {(unsigned long)&_lnkDDRRAM}, /* segmentation fault */
+  {0x40000000},
+};
+
+class CNested {
+public:
+  constexpr CNested(const CAddress primary)
+    : m_PrimaryBlock(primary) {}
+
+private:
+  CAddress m_PrimaryBlock;
+};
+
+/* internal compiler error on gcc 4.7.2 */
+const CNested s_taskDescriptions[2]
+{
+  {{0x42000000}},
+  {{0x43000000}},
+};

Reply via email to