Patchwork C++ PATCH for c++/49369 (wrong cv-quals on base member in unevaluated context)

login
register
mail settings
Submitter Jason Merrill
Date June 14, 2011, 5:33 p.m.
Message ID <4DF79B72.1080401@redhat.com>
Download mbox | patch
Permalink /patch/100388/
State New
Headers show

Comments

Jason Merrill - June 14, 2011, 5:33 p.m.
We were forgetting to propagate cv-quals from 'this' to the result along 
one code path.  Fixed by moving the cv-qual propagation up so it's 
shared by all code paths.

Tested x86_64-pc-linux-gnu, applying to trunk and 4.6.

Patch

commit a7eeb9dc7b67d159f46e9d8e7976332bd73332ca
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Jun 13 17:26:38 2011 -0400

    	PR c++/49369
    	* class.c (build_base_path): Fix cv-quals in unevaluated context.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 69627cb..09444fb 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -289,6 +289,12 @@  build_base_path (enum tree_code code,
   offset = BINFO_OFFSET (binfo);
   fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
   target_type = code == PLUS_EXPR ? BINFO_TYPE (binfo) : BINFO_TYPE (d_binfo);
+  /* TARGET_TYPE has been extracted from BINFO, and, is therefore always
+     cv-unqualified.  Extract the cv-qualifiers from EXPR so that the
+     expression returned matches the input.  */
+  target_type = cp_build_qualified_type
+    (target_type, cp_type_quals (TREE_TYPE (TREE_TYPE (expr))));
+  ptr_target_type = build_pointer_type (target_type);
 
   /* Do we need to look in the vtable for the real offset?  */
   virtual_access = (v_binfo && fixed_type_p <= 0);
@@ -297,7 +303,7 @@  build_base_path (enum tree_code code,
      source type is incomplete and the pointer value doesn't matter.  */
   if (cp_unevaluated_operand != 0)
     {
-      expr = build_nop (build_pointer_type (target_type), expr);
+      expr = build_nop (ptr_target_type, expr);
       if (!want_pointer)
 	expr = build_indirect_ref (EXPR_LOCATION (expr), expr, RO_NULL);
       return expr;
@@ -312,18 +318,7 @@  build_base_path (enum tree_code code,
 	 field, because other parts of the compiler know that such
 	 expressions are always non-NULL.  */
       if (!virtual_access && integer_zerop (offset))
-	{
-	  tree class_type;
-	  /* TARGET_TYPE has been extracted from BINFO, and, is
-	     therefore always cv-unqualified.  Extract the
-	     cv-qualifiers from EXPR so that the expression returned
-	     matches the input.  */
-	  class_type = TREE_TYPE (TREE_TYPE (expr));
-	  target_type
-	    = cp_build_qualified_type (target_type,
-				       cp_type_quals (class_type));
-	  return build_nop (build_pointer_type (target_type), expr);
-	}
+	return build_nop (ptr_target_type, expr);
       null_test = error_mark_node;
     }
 
@@ -407,9 +402,6 @@  build_base_path (enum tree_code code,
 	offset = v_offset;
     }
 
-  target_type = cp_build_qualified_type
-    (target_type, cp_type_quals (TREE_TYPE (TREE_TYPE (expr))));
-  ptr_target_type = build_pointer_type (target_type);
   if (want_pointer)
     target_type = ptr_target_type;
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype30.C b/gcc/testsuite/g++.dg/cpp0x/decltype30.C
new file mode 100644
index 0000000..b23c9a9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype30.C
@@ -0,0 +1,17 @@ 
+// PR c++/49369
+// { dg-options -std=c++0x }
+
+template <class,class> struct assert_same;
+template <class T> struct assert_same<T,T> {};
+
+struct B {
+  int member;
+};
+
+struct C: B {
+  void method() const;
+};
+
+void C::method() const {
+  assert_same<decltype((B::member)), const int&> a;
+}