diff mbox

C++ PATCH for c++/49418 (lost cv-quals on template parameter type)

Message ID 4E00EAE6.8090709@redhat.com
State New
Headers show

Commit Message

Jason Merrill June 21, 2011, 7:03 p.m. UTC
cv-qualifiers are dropped from a function parameter type in order to 
produce the parameter-type-list, but the parameter itself still has the 
qualified type within the function body.  When I added cv-qualification 
stripping to type_decays_to, it started affecting instantiation of 
template function parameters, which is wrong.  So I've reverted that 
change and instead added explicit cv-qualification stripping to 
lambda_return_type.

While looking at this, I've also changed a few more TYPE_MAIN_VARIANTs 
to cv_unqualified.

Tested x86_64-pc-linux-gnu, applying to trunk.  I'll apply the first 
part to 4.6 after the branch unfreezes.

Comments

H.J. Lu June 24, 2011, 12:45 a.m. UTC | #1
On Tue, Jun 21, 2011 at 12:03 PM, Jason Merrill <jason@redhat.com> wrote:
> cv-qualifiers are dropped from a function parameter type in order to produce
> the parameter-type-list, but the parameter itself still has the qualified
> type within the function body.  When I added cv-qualification stripping to
> type_decays_to, it started affecting instantiation of template function
> parameters, which is wrong.  So I've reverted that change and instead added
> explicit cv-qualification stripping to lambda_return_type.
>
> While looking at this, I've also changed a few more TYPE_MAIN_VARIANTs to
> cv_unqualified.

This caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49519
diff mbox

Patch

commit 50b67060545a6d7322c423866d8ffd55f4be42af
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Jun 21 13:21:06 2011 -0400

    	PR c++/49418
    	* call.c (cxx_type_promotes_to): Don't strip cv-quals.
    	* semantics.c (lambda_return_type): Strip them here.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index caf95b0..3ac7a8e 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -2640,8 +2640,6 @@  type_decays_to (tree type)
     return build_pointer_type (TREE_TYPE (type));
   if (TREE_CODE (type) == FUNCTION_TYPE)
     return build_pointer_type (type);
-  if (!MAYBE_CLASS_TYPE_P (type))
-    type = cv_unqualified (type);
   return type;
 }
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index cfe3959..04d797a 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -8177,7 +8177,7 @@  lambda_return_type (tree expr)
       SET_TYPE_STRUCTURAL_EQUALITY (type);
     }
   else
-    type = type_decays_to (unlowered_expr_type (expr));
+    type = cv_unqualified (type_decays_to (unlowered_expr_type (expr)));
   return type;
 }
 
diff --git a/gcc/testsuite/g++.dg/template/param3.C b/gcc/testsuite/g++.dg/template/param3.C
new file mode 100644
index 0000000..0c1e703
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/param3.C
@@ -0,0 +1,12 @@ 
+// PR c++/49418
+
+template <class T>
+void f (const T t)
+{
+  t = 1;			// { dg-error "" }
+}
+
+int main()
+{
+  f(1);
+}

commit b84cd9b997b527960d42d0855ff281af1550b627
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Jun 21 13:22:34 2011 -0400

    	* call.c (add_builtin_candidates): Use cv_unqualified rather than
    	TYPE_MAIN_VARIANT.
    	* pt.c (tsubst_arg_types): Likewise.
    	* except.c (build_throw): Use cv_unqualified.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 3ac7a8e..8123e3d 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -2773,7 +2773,7 @@  add_builtin_candidates (struct z_candidate **candidates, enum tree_code code,
 	      type = non_reference (type);
 	      if (i != 0 || ! ref1)
 		{
-		  type = TYPE_MAIN_VARIANT (type_decays_to (type));
+		  type = cv_unqualified (type_decays_to (type));
 		  if (enum_p && TREE_CODE (type) == ENUMERAL_TYPE)
 		    VEC_safe_push (tree, gc, types[i], type);
 		  if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
@@ -2792,7 +2792,7 @@  add_builtin_candidates (struct z_candidate **candidates, enum tree_code code,
 	  type = non_reference (argtypes[i]);
 	  if (i != 0 || ! ref1)
 	    {
-	      type = TYPE_MAIN_VARIANT (type_decays_to (type));
+	      type = cv_unqualified (type_decays_to (type));
 	      if (enum_p && UNSCOPED_ENUM_P (type))
 		VEC_safe_push (tree, gc, types[i], type);
 	      if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index 3399652..f8c8e47 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -722,7 +722,7 @@  build_throw (tree exp)
 	 respectively.  */
       temp_type = is_bitfield_expr_with_lowered_type (exp);
       if (!temp_type)
-	temp_type = type_decays_to (TREE_TYPE (exp));
+	temp_type = cv_unqualified (type_decays_to (TREE_TYPE (exp)));
 
       /* OK, this is kind of wacky.  The standard says that we call
 	 terminate when the exception handling mechanism, after
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 4d2caa8..2716f78 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10246,7 +10246,7 @@  tsubst_arg_types (tree arg_types,
     
     /* Do array-to-pointer, function-to-pointer conversion, and ignore
        top-level qualifiers as required.  */
-    type = TYPE_MAIN_VARIANT (type_decays_to (type));
+    type = cv_unqualified (type_decays_to (type));
 
     /* We do not substitute into default arguments here.  The standard
        mandates that they be instantiated only when needed, which is