Patchwork C++ PATCH for c++/55879 (constexpr confusion with invisible references)

login
register
mail settings
Submitter Jason Merrill
Date Feb. 13, 2013, 4:50 p.m.
Message ID <511BC43A.3000204@redhat.com>
Download mbox | patch
Permalink /patch/220201/
State New
Headers show

Comments

Jason Merrill - Feb. 13, 2013, 4:50 p.m.
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.

Patch

commit 34ef3b1602847bb7e1af4b7c0eb918dcdfcfea97
Author: Jason Merrill <jason@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}},
+};