OSDN Git Service

PR c++/44193
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 May 2010 21:01:50 +0000 (21:01 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 May 2010 21:01:50 +0000 (21:01 +0000)
* typeck.c (type_memfn_quals): New fn.
(apply_memfn_quals): New fn.
(cp_type_quals): Return TYPE_UNQUALIFIED for FUNCTION_TYPE.
(cp_type_readonly): Use cp_type_quals.
* cp-tree.h: Add declarations.
* tree.c (cp_build_qualified_type_real): Don't set, but do
preserve, quals on FUNCTION_TYPE.
(strip_typedefs): Use apply_memfn_quals and type_memfn_quals.
* decl.c (build_ptrmem_type): Likewise.
(grokdeclarator): Likewise.
(static_fn_type): Likewise.
* decl2.c (change_return_type): Likewise.
(cp_reconstruct_complex_type): Likewise.
* pt.c (tsubst_function_type): Likewise.
(unify): Likewise.
(tsubst): Likewise.  Drop special FUNCTION_TYPE substitution code.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@159596 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/pt.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/fntype1.C [new file with mode: 0644]

index 0d927c9..255ecd3 100644 (file)
@@ -1,3 +1,23 @@
+2010-05-19  Jason Merrill  <jason@redhat.com>
+
+       PR c++/44193
+       * typeck.c (type_memfn_quals): New fn.
+       (apply_memfn_quals): New fn.
+       (cp_type_quals): Return TYPE_UNQUALIFIED for FUNCTION_TYPE.
+       (cp_type_readonly): Use cp_type_quals.
+       * cp-tree.h: Add declarations.
+       * tree.c (cp_build_qualified_type_real): Don't set, but do
+       preserve, quals on FUNCTION_TYPE.
+       (strip_typedefs): Use apply_memfn_quals and type_memfn_quals.
+       * decl.c (build_ptrmem_type): Likewise.
+       (grokdeclarator): Likewise.
+       (static_fn_type): Likewise.
+       * decl2.c (change_return_type): Likewise.
+       (cp_reconstruct_complex_type): Likewise.
+       * pt.c (tsubst_function_type): Likewise.
+       (unify): Likewise.
+       (tsubst): Likewise.  Drop special FUNCTION_TYPE substitution code.
+
 2010-05-18  Nathan Froyd  <froydnj@codesourcery.com>
 
        * tree.c (build_min_non_dep_call_vec): Update comment.
 2010-05-18  Nathan Froyd  <froydnj@codesourcery.com>
 
        * tree.c (build_min_non_dep_call_vec): Update comment.
index 361a6f2..6a0dd12 100644 (file)
@@ -5413,6 +5413,8 @@ extern bool error_type_p                  (const_tree);
 extern int ptr_reasonably_similar              (const_tree, const_tree);
 extern tree build_ptrmemfunc                   (tree, tree, int, bool);
 extern int cp_type_quals                       (const_tree);
 extern int ptr_reasonably_similar              (const_tree, const_tree);
 extern tree build_ptrmemfunc                   (tree, tree, int, bool);
 extern int cp_type_quals                       (const_tree);
+extern int type_memfn_quals                    (const_tree);
+extern tree apply_memfn_quals                  (tree, cp_cv_quals);
 extern bool cp_type_readonly                   (const_tree);
 extern bool cp_has_mutable_p                   (const_tree);
 extern bool at_least_as_qualified_p            (const_tree, const_tree);
 extern bool cp_type_readonly                   (const_tree);
 extern bool cp_has_mutable_p                   (const_tree);
 extern bool at_least_as_qualified_p            (const_tree, const_tree);
index 0636aba..e57a753 100644 (file)
@@ -7265,8 +7265,7 @@ build_ptrmem_type (tree class_type, tree member_type)
 {
   if (TREE_CODE (member_type) == METHOD_TYPE)
     {
 {
   if (TREE_CODE (member_type) == METHOD_TYPE)
     {
-      tree arg_types = TYPE_ARG_TYPES (member_type);
-      cp_cv_quals quals = cp_type_quals (TREE_TYPE (TREE_VALUE (arg_types)));
+      cp_cv_quals quals = type_memfn_quals (member_type);
       member_type = build_memfn_type (member_type, class_type, quals);
       return build_ptrmemfunc_type (build_pointer_type (member_type));
     }
       member_type = build_memfn_type (member_type, class_type, quals);
       return build_ptrmemfunc_type (build_pointer_type (member_type));
     }
@@ -8683,7 +8682,7 @@ grokdeclarator (const cp_declarator *declarator,
              && (TREE_CODE (type) == FUNCTION_TYPE
                  || (memfn_quals && TREE_CODE (type) == METHOD_TYPE)))
            {
              && (TREE_CODE (type) == FUNCTION_TYPE
                  || (memfn_quals && TREE_CODE (type) == METHOD_TYPE)))
            {
-             memfn_quals |= cp_type_quals (type);
+             memfn_quals |= type_memfn_quals (type);
              type = build_memfn_type (type,
                                       declarator->u.pointer.class_type,
                                       memfn_quals);
              type = build_memfn_type (type,
                                       declarator->u.pointer.class_type,
                                       memfn_quals);
@@ -8691,7 +8690,7 @@ grokdeclarator (const cp_declarator *declarator,
            }
 
          if (TREE_CODE (type) == FUNCTION_TYPE
            }
 
          if (TREE_CODE (type) == FUNCTION_TYPE
-             && cp_type_quals (type) != TYPE_UNQUALIFIED)
+             && type_memfn_quals (type) != TYPE_UNQUALIFIED)
             error (declarator->kind == cdk_reference
                    ? G_("cannot declare reference to qualified function type %qT")
                    : G_("cannot declare pointer to qualified function type %qT"),
             error (declarator->kind == cdk_reference
                    ? G_("cannot declare reference to qualified function type %qT")
                    : G_("cannot declare pointer to qualified function type %qT"),
@@ -8994,7 +8993,7 @@ grokdeclarator (const cp_declarator *declarator,
         function type.  */
       if (memfn_quals && TREE_CODE (type) == FUNCTION_TYPE)
         {
         function type.  */
       if (memfn_quals && TREE_CODE (type) == FUNCTION_TYPE)
         {
-          type = cp_build_qualified_type (type, memfn_quals);
+          type = apply_memfn_quals (type, memfn_quals);
           
           /* We have now dealt with these qualifiers.  */
           memfn_quals = TYPE_UNQUALIFIED;
           
           /* We have now dealt with these qualifiers.  */
           memfn_quals = TYPE_UNQUALIFIED;
@@ -9114,7 +9113,7 @@ grokdeclarator (const cp_declarator *declarator,
        {
          /* A cv-qualifier-seq shall only be part of the function type
             for a non-static member function. [8.3.5/4 dcl.fct] */
        {
          /* A cv-qualifier-seq shall only be part of the function type
             for a non-static member function. [8.3.5/4 dcl.fct] */
-         if (cp_type_quals (type) != TYPE_UNQUALIFIED
+         if (type_memfn_quals (type) != TYPE_UNQUALIFIED
              && (current_class_type == NULL_TREE || staticp) )
            {
              error (staticp
              && (current_class_type == NULL_TREE || staticp) )
            {
              error (staticp
@@ -9127,7 +9126,7 @@ grokdeclarator (const cp_declarator *declarator,
 
          /* The qualifiers on the function type become the qualifiers on
             the non-static member function. */
 
          /* The qualifiers on the function type become the qualifiers on
             the non-static member function. */
-         memfn_quals |= cp_type_quals (type);
+         memfn_quals |= type_memfn_quals (type);
          type_quals = TYPE_UNQUALIFIED;
        }
     }
          type_quals = TYPE_UNQUALIFIED;
        }
     }
@@ -9195,7 +9194,7 @@ grokdeclarator (const cp_declarator *declarator,
            type = build_memfn_type (type, ctype, memfn_quals);
          /* Core issue #547: need to allow this in template type args.  */
          else if (template_type_arg && TREE_CODE (type) == FUNCTION_TYPE)
            type = build_memfn_type (type, ctype, memfn_quals);
          /* Core issue #547: need to allow this in template type args.  */
          else if (template_type_arg && TREE_CODE (type) == FUNCTION_TYPE)
-           type = cp_build_qualified_type (type, memfn_quals);
+           type = apply_memfn_quals (type, memfn_quals);
          else
            error ("invalid qualifiers on non-member function type");
        }
          else
            error ("invalid qualifiers on non-member function type");
        }
@@ -12944,7 +12943,6 @@ static_fn_type (tree memfntype)
 {
   tree fntype;
   tree args;
 {
   tree fntype;
   tree args;
-  int quals;
 
   if (TYPE_PTRMEMFUNC_P (memfntype))
     memfntype = TYPE_PTRMEMFUNC_FN_TYPE (memfntype);
 
   if (TYPE_PTRMEMFUNC_P (memfntype))
     memfntype = TYPE_PTRMEMFUNC_FN_TYPE (memfntype);
@@ -12956,8 +12954,7 @@ static_fn_type (tree memfntype)
   gcc_assert (TREE_CODE (memfntype) == METHOD_TYPE);
   args = TYPE_ARG_TYPES (memfntype);
   fntype = build_function_type (TREE_TYPE (memfntype), TREE_CHAIN (args));
   gcc_assert (TREE_CODE (memfntype) == METHOD_TYPE);
   args = TYPE_ARG_TYPES (memfntype);
   fntype = build_function_type (TREE_TYPE (memfntype), TREE_CHAIN (args));
-  quals = cp_type_quals (TREE_TYPE (TREE_VALUE (args)));
-  fntype = build_qualified_type (fntype, quals);
+  fntype = apply_memfn_quals (fntype, type_memfn_quals (memfntype));
   fntype = (cp_build_type_attribute_variant
            (fntype, TYPE_ATTRIBUTES (memfntype)));
   fntype = (build_exception_variant
   fntype = (cp_build_type_attribute_variant
            (fntype, TYPE_ATTRIBUTES (memfntype)));
   fntype = (build_exception_variant
index d811c9e..29971ce 100644 (file)
@@ -154,7 +154,10 @@ change_return_type (tree new_ret, tree fntype)
     return fntype;
 
   if (TREE_CODE (fntype) == FUNCTION_TYPE)
     return fntype;
 
   if (TREE_CODE (fntype) == FUNCTION_TYPE)
-    newtype = build_function_type (new_ret, args);
+    {
+      newtype = build_function_type (new_ret, args);
+      newtype = apply_memfn_quals (newtype, type_memfn_quals (fntype));
+    }
   else
     newtype = build_method_type_directly
       (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))),
   else
     newtype = build_method_type_directly
       (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))),
@@ -1246,6 +1249,7 @@ cp_reconstruct_complex_type (tree type, tree bottom)
     {
       inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
       outer = build_function_type (inner, TYPE_ARG_TYPES (type));
     {
       inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
       outer = build_function_type (inner, TYPE_ARG_TYPES (type));
+      outer = apply_memfn_quals (outer, type_memfn_quals (type));
     }
   else if (TREE_CODE (type) == METHOD_TYPE)
     {
     }
   else if (TREE_CODE (type) == METHOD_TYPE)
     {
index 7a66d36..949734d 100644 (file)
@@ -9791,7 +9791,10 @@ tsubst_function_type (tree t,
 
   /* Construct a new type node and return it.  */
   if (TREE_CODE (t) == FUNCTION_TYPE)
 
   /* Construct a new type node and return it.  */
   if (TREE_CODE (t) == FUNCTION_TYPE)
-    fntype = build_function_type (return_type, arg_types);
+    {
+      fntype = build_function_type (return_type, arg_types);
+      fntype = apply_memfn_quals (fntype, type_memfn_quals (t));
+    }
   else
     {
       tree r = TREE_TYPE (TREE_VALUE (arg_types));
   else
     {
       tree r = TREE_TYPE (TREE_VALUE (arg_types));
@@ -9813,7 +9816,6 @@ tsubst_function_type (tree t,
       fntype = build_method_type_directly (r, return_type,
                                           TREE_CHAIN (arg_types));
     }
       fntype = build_method_type_directly (r, return_type,
                                           TREE_CHAIN (arg_types));
     }
-  fntype = cp_build_qualified_type_real (fntype, TYPE_QUALS (t), complain);
   fntype = cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
 
   return fntype;
   fntype = cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
 
   return fntype;
@@ -10111,14 +10113,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
                int quals;
                gcc_assert (TYPE_P (arg));
 
                int quals;
                gcc_assert (TYPE_P (arg));
 
-               /* cv-quals from the template are discarded when
-                  substituting in a function or reference type.  */
-               if (TREE_CODE (arg) == FUNCTION_TYPE
-                   || TREE_CODE (arg) == METHOD_TYPE
-                   || TREE_CODE (arg) == REFERENCE_TYPE)
-                 quals = cp_type_quals (arg);
-               else
-                 quals = cp_type_quals (arg) | cp_type_quals (t);
+               quals = cp_type_quals (arg) | cp_type_quals (t);
                  
                return cp_build_qualified_type_real
                  (arg, quals, complain | tf_ignore_bad_quals);
                  
                return cp_build_qualified_type_real
                  (arg, quals, complain | tf_ignore_bad_quals);
@@ -10378,7 +10373,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
            /* The type of the implicit object parameter gets its
               cv-qualifiers from the FUNCTION_TYPE. */
            tree memptr;
            /* The type of the implicit object parameter gets its
               cv-qualifiers from the FUNCTION_TYPE. */
            tree memptr;
-           tree method_type = build_memfn_type (type, r, cp_type_quals (type));
+           tree method_type = build_memfn_type (type, r, type_memfn_quals (type));
            memptr = build_ptrmemfunc_type (build_pointer_type (method_type));
            return cp_build_qualified_type_real (memptr, cp_type_quals (t),
                                                 complain);
            memptr = build_ptrmemfunc_type (build_pointer_type (method_type));
            return cp_build_qualified_type_real (memptr, cp_type_quals (t),
                                                 complain);
@@ -15042,7 +15037,6 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
        {
          tree method_type;
          tree fntype;
        {
          tree method_type;
          tree fntype;
-         cp_cv_quals cv_quals;
 
          /* Check top-level cv qualifiers */
          if (!check_cv_quals_for_unify (UNIFY_ALLOW_NONE, arg, parm))
 
          /* Check top-level cv qualifiers */
          if (!check_cv_quals_for_unify (UNIFY_ALLOW_NONE, arg, parm))
@@ -15061,9 +15055,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
          /* Extract the cv-qualifiers of the member function from the
             implicit object parameter and place them on the function
             type to be restored later. */
          /* Extract the cv-qualifiers of the member function from the
             implicit object parameter and place them on the function
             type to be restored later. */
-         cv_quals =
-           cp_type_quals(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (method_type))));
-         fntype = build_qualified_type (fntype, cv_quals);
+         fntype = apply_memfn_quals (fntype, type_memfn_quals (method_type));
          return unify (tparms, targs, TREE_TYPE (parm), fntype, strict);
        }
 
          return unify (tparms, targs, TREE_TYPE (parm), fntype, strict);
        }
 
index bfe65b8..04bfae0 100644 (file)
@@ -868,12 +868,17 @@ cp_build_qualified_type_real (tree type,
      [dcl.ref], [dcl.fct]  */
   if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
       && (TREE_CODE (type) == REFERENCE_TYPE
      [dcl.ref], [dcl.fct]  */
   if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
       && (TREE_CODE (type) == REFERENCE_TYPE
+         || TREE_CODE (type) == FUNCTION_TYPE
          || TREE_CODE (type) == METHOD_TYPE))
     {
       bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
       type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
     }
 
          || TREE_CODE (type) == METHOD_TYPE))
     {
       bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
       type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
     }
 
+  /* But preserve any function-cv-quals on a FUNCTION_TYPE.  */
+  if (TREE_CODE (type) == FUNCTION_TYPE)
+    type_quals |= type_memfn_quals (type);
+
   /* A restrict-qualified type must be a pointer (or reference)
      to object or incomplete type. */
   if ((type_quals & TYPE_QUAL_RESTRICT)
   /* A restrict-qualified type must be a pointer (or reference)
      to object or incomplete type. */
   if ((type_quals & TYPE_QUAL_RESTRICT)
@@ -1038,8 +1043,11 @@ strip_typedefs (tree t)
                                          TREE_CHAIN (arg_types));
          }
        else
                                          TREE_CHAIN (arg_types));
          }
        else
+         {
            result = build_function_type (type,
                                          arg_types);
            result = build_function_type (type,
                                          arg_types);
+           result = apply_memfn_quals (result, type_memfn_quals (t));
+         }
 
        if (TYPE_RAISES_EXCEPTIONS (t))
          result = build_exception_variant (result,
 
        if (TYPE_RAISES_EXCEPTIONS (t))
          result = build_exception_variant (result,
index dfdd592..a291a9c 100644 (file)
@@ -7851,12 +7851,50 @@ comp_ptr_ttypes_const (tree to, tree from)
 int
 cp_type_quals (const_tree type)
 {
 int
 cp_type_quals (const_tree type)
 {
+  int quals;
   /* This CONST_CAST is okay because strip_array_types returns its
      argument unmodified and we assign it to a const_tree.  */
   /* This CONST_CAST is okay because strip_array_types returns its
      argument unmodified and we assign it to a const_tree.  */
-  type = strip_array_types (CONST_CAST_TREE(type));
-  if (type == error_mark_node)
+  type = strip_array_types (CONST_CAST_TREE (type));
+  if (type == error_mark_node
+      /* Quals on a FUNCTION_TYPE are memfn quals.  */
+      || TREE_CODE (type) == FUNCTION_TYPE)
     return TYPE_UNQUALIFIED;
     return TYPE_UNQUALIFIED;
-  return TYPE_QUALS (type);
+  quals = TYPE_QUALS (type);
+  /* METHOD and REFERENCE_TYPEs should never have quals.  */
+  gcc_assert ((TREE_CODE (type) != METHOD_TYPE
+              && TREE_CODE (type) != REFERENCE_TYPE)
+             || ((quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE))
+                 == TYPE_UNQUALIFIED));
+  return quals;
+}
+
+/* Returns the function-cv-quals for TYPE, which must be a FUNCTION_TYPE or
+   METHOD_TYPE.  */
+
+int
+type_memfn_quals (const_tree type)
+{
+  if (TREE_CODE (type) == FUNCTION_TYPE)
+    return TYPE_QUALS (type);
+  else if (TREE_CODE (type) == METHOD_TYPE)
+    return cp_type_quals (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))));
+  else
+    gcc_unreachable ();
+}
+
+/* Returns the FUNCTION_TYPE TYPE with its function-cv-quals changed to
+   MEMFN_QUALS.  */
+
+tree
+apply_memfn_quals (tree type, cp_cv_quals memfn_quals)
+{
+  /* Could handle METHOD_TYPE here if necessary.  */
+  gcc_assert (TREE_CODE (type) == FUNCTION_TYPE);
+  if (TYPE_QUALS (type) == memfn_quals)
+    return type;
+  /* This should really have a different TYPE_MAIN_VARIANT, but that gets
+     complex.  */
+  return build_qualified_type (type, memfn_quals);
 }
 
 /* Returns nonzero if the TYPE is const from a C++ perspective: look inside
 }
 
 /* Returns nonzero if the TYPE is const from a C++ perspective: look inside
@@ -7867,8 +7905,7 @@ cp_type_readonly (const_tree type)
 {
   /* This CONST_CAST is okay because strip_array_types returns its
      argument unmodified and we assign it to a const_tree.  */
 {
   /* This CONST_CAST is okay because strip_array_types returns its
      argument unmodified and we assign it to a const_tree.  */
-  type = strip_array_types (CONST_CAST_TREE(type));
-  return TYPE_READONLY (type);
+  return (cp_type_quals (type) & TYPE_QUAL_CONST) != 0;
 }
 
 /* Returns nonzero if TYPE is const or volatile.  */
 }
 
 /* Returns nonzero if TYPE is const or volatile.  */
index dc5afe3..7339c62 100644 (file)
@@ -1,3 +1,8 @@
+2010-05-19  Jason Merrill  <jason@redhat.com>
+
+       PR c++/44193
+       * g++.dg/template/fntype1.C: New.
+
 2010-05-19  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/discr23.ad[sb]: New test.
 2010-05-19  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/discr23.ad[sb]: New test.
diff --git a/gcc/testsuite/g++.dg/template/fntype1.C b/gcc/testsuite/g++.dg/template/fntype1.C
new file mode 100644 (file)
index 0000000..d7be273
--- /dev/null
@@ -0,0 +1,26 @@
+bool f(int i) { return i != 5; }
+
+template <class X, class P = bool(X)>
+struct Traits
+{
+ typedef P type;
+};
+
+template <class X, class P = typename Traits<X>::type>
+struct S
+{
+ const P& p_;
+ S( const P& p ) : p_(p) {} // const reference
+};
+
+template <class X>
+S<X> make_s(const typename Traits<X>::type & p) // const reference
+{
+ return S<X>(p); // << HERE
+}
+
+
+int main()
+{
+ make_s<int>(f);
+}