]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/37806 (CV-qualifiers on function typedef's are inconsistently accepted...
authorJason Merrill <jason@redhat.com>
Tue, 31 Mar 2009 18:31:17 +0000 (14:31 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 31 Mar 2009 18:31:17 +0000 (14:31 -0400)
        PR c++/37806
        * typeck.c (cp_apply_type_quals_to_decl): Don't apply any quals
        to a typedef.
        * tree.c (cp_build_qualified_type_real): Don't apply restrict to a
        function type.
        * decl.h (enum decl_context): Add TEMPLATE_TYPE_ARG.
        * decl.c (groktypename): Add is_template_arg parameter.
        (grokdeclarator): Allow function cv-quals on a template type arg.
        * parser.c (cp_parser_new_type_id, cp_parser_type_id): Add
        is_template_arg argument in calls to groktypename.
        * cp-tree.h: Adjust prototype.
        * error.c (dump_type_prefix, dump_type_suffix): Fix plain
        FUNCTION_TYPE printing.

        PR libstdc++/39310
        * include/tr1_impl/type_traits (is_function): Add partial
        specializations with function cv-quals.
        (__is_function_helper): Remove.
        (is_member_pointer): Don't define in terms of is_member_*_pointer.

From-SVN: r145365

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl.h
gcc/cp/error.c
gcc/cp/parser.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/g++.dg/template/qualttp20.C
libstdc++-v3/ChangeLog
libstdc++-v3/include/tr1_impl/type_traits

index 033a8f1362841c0a734751d5cc02ad283b90b32a..95079f15c31fb75291a10f7b1fd01b25bfff427d 100644 (file)
@@ -1,5 +1,19 @@
 2009-03-31  Jason Merrill  <jason@redhat.com>
 
+       PR c++/37806
+       * typeck.c (cp_apply_type_quals_to_decl): Don't apply any quals
+       to a typedef.
+       * tree.c (cp_build_qualified_type_real): Don't apply restrict to a 
+       function type.
+       * decl.h (enum decl_context): Add TEMPLATE_TYPE_ARG.
+       * decl.c (groktypename): Add is_template_arg parameter.
+       (grokdeclarator): Allow function cv-quals on a template type arg.
+       * parser.c (cp_parser_new_type_id, cp_parser_type_id): Add
+       is_template_arg argument in calls to groktypename.
+       * cp-tree.h: Adjust prototype.
+       * error.c (dump_type_prefix, dump_type_suffix): Fix plain 
+       FUNCTION_TYPE printing.
+       
        * mangle.c (write_expression): Mangle dependent name as
        source-name.
 
index 4fc86c38d1f3e3507813e7c997482670479c21dc..9878d9d29a027c2c7ae9d224b25caeddd07021fa 100644 (file)
@@ -4328,7 +4328,7 @@ extern tree push_void_library_fn          (tree, tree);
 extern tree push_throw_library_fn              (tree, tree);
 extern tree check_tag_decl                     (cp_decl_specifier_seq *);
 extern tree shadow_tag                         (cp_decl_specifier_seq *);
-extern tree groktypename                       (cp_decl_specifier_seq *, const cp_declarator *);
+extern tree groktypename                       (cp_decl_specifier_seq *, const cp_declarator *, bool);
 extern tree start_decl                         (const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree, tree *);
 extern void start_decl_1                       (tree, bool);
 extern bool check_array_initializer            (tree, tree, tree);
index b16ae262bea3ca7d487a52b1709fd7dea30cfb8b..6537c50409fc3ce32ec3bc2987fd5b37488924ce 100644 (file)
@@ -3967,13 +3967,16 @@ shadow_tag (cp_decl_specifier_seq *declspecs)
 
 tree
 groktypename (cp_decl_specifier_seq *type_specifiers,
-             const cp_declarator *declarator)
+             const cp_declarator *declarator,
+             bool is_template_arg)
 {
   tree attrs;
   tree type;
+  enum decl_context context
+    = is_template_arg ? TEMPLATE_TYPE_ARG : TYPENAME;
   attrs = type_specifiers->attributes;
   type_specifiers->attributes = NULL_TREE;
-  type = grokdeclarator (declarator, type_specifiers, TYPENAME, 0, &attrs);
+  type = grokdeclarator (declarator, type_specifiers, context, 0, &attrs);
   if (attrs && type != error_mark_node)
     {
       if (CLASS_TYPE_P (type))
@@ -7603,6 +7606,7 @@ grokdeclarator (const cp_declarator *declarator,
   bool type_was_error_mark_node = false;
   bool parameter_pack_p = declarator? declarator->parameter_pack_p : false;
   bool set_no_warning = false;
+  bool template_type_arg = false;
 
   signed_p = declspecs->specs[(int)ds_signed];
   unsigned_p = declspecs->specs[(int)ds_unsigned];
@@ -7617,6 +7621,8 @@ grokdeclarator (const cp_declarator *declarator,
     funcdef_flag = true, decl_context = FIELD;
   else if (decl_context == BITFIELD)
     bitfield = 1, decl_context = FIELD;
+  else if (decl_context == TEMPLATE_TYPE_ARG)
+    template_type_arg = true, decl_context = TYPENAME;
 
   if (initialized > 1)
     funcdef_flag = true;
@@ -8476,6 +8482,12 @@ grokdeclarator (const cp_declarator *declarator,
              memfn_quals = TYPE_UNQUALIFIED;
            }
 
+         if (TREE_CODE (type) == FUNCTION_TYPE
+             && cp_type_quals (type) != TYPE_UNQUALIFIED)
+           error ("cannot declare %s to qualified function type %qT",
+                  declarator->kind == cdk_reference ? "reference" : "pointer",
+                  type);
+
          if (declarator->kind == cdk_reference)
            {
              /* In C++0x, the type we are creating a reference to might be
@@ -8948,15 +8960,17 @@ grokdeclarator (const cp_declarator *declarator,
        }
       else if (memfn_quals)
        {
-         if (ctype == NULL_TREE)
-           {
-             if (TREE_CODE (type) != METHOD_TYPE)
-               error ("invalid qualifiers on non-member function type");
-             else
-               ctype = TYPE_METHOD_BASETYPE (type);
-           }
+         if (ctype == NULL_TREE
+             && TREE_CODE (type) == METHOD_TYPE)
+           ctype = TYPE_METHOD_BASETYPE (type);
+
          if (ctype)
            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);
+         else
+           error ("invalid qualifiers on non-member function type");
        }
 
       return type;
index b070be0ec95c5522ac67a6ed5e48ba8808ec2cc5..d6e3c83bcbfecebff0055c69d5eda4327477cdaf 100644 (file)
@@ -27,6 +27,7 @@ enum decl_context
   FIELD,                       /* Declaration inside struct or union */
   BITFIELD,                    /* Likewise but with specified width */
   TYPENAME,                    /* Typename (inside cast or sizeof)  */
+  TEMPLATE_TYPE_ARG,           /* Almost the same as TYPENAME  */
   MEMFUNCDEF                   /* Member function definition */
 };
 
index 161fa55a17fba3cf057614066d3d501581c747b8..7d3756e33402e31eda2ad7ca1a99d4d7f3231e84 100644 (file)
@@ -550,7 +550,8 @@ dump_type_prefix (tree t, int flags)
        tree sub = TREE_TYPE (t);
 
        dump_type_prefix (sub, flags);
-       if (TREE_CODE (sub) == ARRAY_TYPE)
+       if (TREE_CODE (sub) == ARRAY_TYPE
+           || TREE_CODE (sub) == FUNCTION_TYPE)
          {
            pp_cxx_whitespace (cxx_pp);
            pp_cxx_left_paren (cxx_pp);
@@ -585,12 +586,10 @@ dump_type_prefix (tree t, int flags)
       pp_base (cxx_pp)->padding = pp_before;
       break;
 
-      /* Can only be reached through function pointer -- this would not be
-        correct if FUNCTION_DECLs used it.  */
+      /* This can be reached without a pointer when dealing with
+        templates, e.g. std::is_function.  */
     case FUNCTION_TYPE:
       dump_type_prefix (TREE_TYPE (t), flags);
-      pp_maybe_space (cxx_pp);
-      pp_cxx_left_paren (cxx_pp);
       break;
 
     case METHOD_TYPE:
@@ -654,17 +653,19 @@ dump_type_suffix (tree t, int flags)
     case POINTER_TYPE:
     case REFERENCE_TYPE:
     case OFFSET_TYPE:
-      if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
+      if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE
+         || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
        pp_cxx_right_paren (cxx_pp);
       dump_type_suffix (TREE_TYPE (t), flags);
       break;
 
-      /* Can only be reached through function pointer.  */
     case FUNCTION_TYPE:
     case METHOD_TYPE:
       {
        tree arg;
-       pp_cxx_right_paren (cxx_pp);
+       if (TREE_CODE (t) == METHOD_TYPE)
+         /* Can only be reached through a pointer.  */
+         pp_cxx_right_paren (cxx_pp);
        arg = TYPE_ARG_TYPES (t);
        if (TREE_CODE (t) == METHOD_TYPE)
          arg = TREE_CHAIN (arg);
@@ -677,7 +678,7 @@ dump_type_suffix (tree t, int flags)
          pp_cxx_cv_qualifier_seq
            (cxx_pp, TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))));
        else
-         pp_cxx_cv_qualifier_seq(cxx_pp, t);
+         pp_cxx_cv_qualifier_seq (cxx_pp, t);
        dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), flags);
        dump_type_suffix (TREE_TYPE (t), flags);
        break;
index eacf5e91c88f43a0af366872cc88afefe5a29f47..28f47c8f402282f86c54a5726c52f9cfd2235319 100644 (file)
@@ -1732,6 +1732,10 @@ static tree cp_parser_declarator_id
   (cp_parser *, bool);
 static tree cp_parser_type_id
   (cp_parser *);
+static tree cp_parser_template_type_arg
+  (cp_parser *);
+static tree cp_parser_type_id_1
+  (cp_parser *, bool);
 static void cp_parser_type_specifier_seq
   (cp_parser *, bool, cp_decl_specifier_seq *);
 static tree cp_parser_parameter_declaration_clause
@@ -5772,7 +5776,7 @@ cp_parser_new_type_id (cp_parser* parser, tree *nelts)
        new_declarator = NULL;
     }
 
-  type = groktypename (&type_specifier_seq, new_declarator);
+  type = groktypename (&type_specifier_seq, new_declarator, false);
   return type;
 }
 
@@ -10544,7 +10548,7 @@ cp_parser_template_argument (cp_parser* parser)
 
      Therefore, we try a type-id first.  */
   cp_parser_parse_tentatively (parser);
-  argument = cp_parser_type_id (parser);
+  argument = cp_parser_template_type_arg (parser);
   /* If there was no error parsing the type-id but the next token is a
      '>>', our behavior depends on which dialect of C++ we're
      parsing. In C++98, we probably found a typo for '> >'. But there
@@ -10732,7 +10736,7 @@ cp_parser_template_argument (cp_parser* parser)
      was the only alternative that matched (albeit with a '>' after
      it). We can assume it's just a typo from the user, and a
      diagnostic will then be issued.  */
-  return cp_parser_type_id (parser);
+  return cp_parser_template_type_arg (parser);
 }
 
 /* Parse an explicit-instantiation.
@@ -13766,7 +13770,7 @@ cp_parser_declarator_id (cp_parser* parser, bool optional_p)
    Returns the TYPE specified.  */
 
 static tree
-cp_parser_type_id (cp_parser* parser)
+cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg)
 {
   cp_decl_specifier_seq type_specifier_seq;
   cp_declarator *abstract_declarator;
@@ -13795,7 +13799,18 @@ cp_parser_type_id (cp_parser* parser)
       return error_mark_node;
     }
   
-  return groktypename (&type_specifier_seq, abstract_declarator);
+  return groktypename (&type_specifier_seq, abstract_declarator,
+                      is_template_arg);
+}
+
+static tree cp_parser_type_id (cp_parser *parser)
+{
+  return cp_parser_type_id_1 (parser, false);
+}
+
+static tree cp_parser_template_type_arg (cp_parser *parser)
+{
+  return cp_parser_type_id_1 (parser, true);
 }
 
 /* Parse a type-specifier-seq.
index 2287f11f04b87c7253b931ec2a50061a5e0c39b8..b4b977ef1a990187cc469031f0e3eede597eb37a 100644 (file)
@@ -852,11 +852,10 @@ cp_build_qualified_type_real (tree type,
     }
 
   /* A restrict-qualified type must be a pointer (or reference)
-     to object or incomplete type, or a function type. */
+     to object or incomplete type. */
   if ((type_quals & TYPE_QUAL_RESTRICT)
       && TREE_CODE (type) != TEMPLATE_TYPE_PARM
       && TREE_CODE (type) != TYPENAME_TYPE
-      && TREE_CODE (type) != FUNCTION_TYPE
       && !POINTER_TYPE_P (type))
     {
       bad_quals |= TYPE_QUAL_RESTRICT;
index 3788a7e8b9e4d06a4714ee573621838c077e4ce0..fe791f3d707f920648c85ede79db562b4ad23180 100644 (file)
@@ -7239,6 +7239,9 @@ cp_apply_type_quals_to_decl (int type_quals, tree decl)
   if (type == error_mark_node)
     return;
 
+  if (TREE_CODE (decl) == TYPE_DECL)
+    return;
+
   if (TREE_CODE (type) == FUNCTION_TYPE
       && type_quals != TYPE_UNQUALIFIED)
     {
index d65fd1b61e73fdc1a03a50132fb60941cc241438..f42981b52b7a5fa3704138b3dde45a857858547f 100644 (file)
@@ -17,7 +17,7 @@ struct AS
 template <typename T> struct B1 : T
 {
   typedef typename T::L __restrict__ r;// { dg-error "'__restrict__' qualifiers cannot" "" }
-  typedef typename T::myT __restrict__ p;// { dg-error "ignoring '__restrict__'" }
+  typedef typename T::myT __restrict__ p;
 
   // The following are DR 295 dependent
   typedef typename T::myT volatile *myvolatile;
index 6b47446215283923bd3352df6e73e9cdae9f0679..1bcfc0b8045147d3ffa68759aaacd0808d1a2bf9 100644 (file)
@@ -1,3 +1,11 @@
+2009-03-31  Jason Merrill  <jason@redhat.com>
+
+       PR libstdc++/39310
+       * include/tr1_impl/type_traits (is_function): Add partial
+       specializations with function cv-quals.
+       (__is_function_helper): Remove.
+       (is_member_pointer): Don't define in terms of is_member_*_pointer.
+
 2009-03-30  Ian Lance Taylor  <iant@google.com>
 
        * include/backward/hashtable.h (clear): Return quickly if the
index cb0ad44a5ff82ef5553e22d390ca4dc5f4ca8116..0672c398693cdbca8041c7357098baaf5a0cf269 100644 (file)
@@ -224,24 +224,34 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
     : public integral_constant<bool, __is_class(_Tp)>
     { };
 
+  /// is_function
   template<typename>
-    struct __is_function_helper
+    struct is_function
     : public false_type { };
-
   template<typename _Res, typename... _ArgTypes>
-    struct __is_function_helper<_Res(_ArgTypes...)>
+    struct is_function<_Res(_ArgTypes...)>
     : public true_type { };
-
   template<typename _Res, typename... _ArgTypes>
-    struct __is_function_helper<_Res(_ArgTypes......)>
+    struct is_function<_Res(_ArgTypes......)>
+    : public true_type { };
+  template<typename _Res, typename... _ArgTypes>
+    struct is_function<_Res(_ArgTypes...) const>
+    : public true_type { };
+  template<typename _Res, typename... _ArgTypes>
+    struct is_function<_Res(_ArgTypes......) const>
+    : public true_type { };
+  template<typename _Res, typename... _ArgTypes>
+    struct is_function<_Res(_ArgTypes...) volatile>
+    : public true_type { };
+  template<typename _Res, typename... _ArgTypes>
+    struct is_function<_Res(_ArgTypes......) volatile>
+    : public true_type { };
+  template<typename _Res, typename... _ArgTypes>
+    struct is_function<_Res(_ArgTypes...) const volatile>
+    : public true_type { };
+  template<typename _Res, typename... _ArgTypes>
+    struct is_function<_Res(_ArgTypes......) const volatile>
     : public true_type { };
-
-  /// is_function
-  template<typename _Tp>
-    struct is_function
-    : public integral_constant<bool, (__is_function_helper<typename
-                                     remove_cv<_Tp>::type>::value)>
-    { };
 
   // composite type traits [4.5.2].
   
@@ -287,10 +297,14 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
 
   /// is_member_pointer
   template<typename _Tp>
-    struct is_member_pointer
-    : public integral_constant<bool,
-                              (is_member_object_pointer<_Tp>::value
-                               || is_member_function_pointer<_Tp>::value)>
+    struct __is_member_pointer_helper
+    : public false_type { };
+  _DEFINE_SPEC(2, __is_member_pointer_helper, _Tp _Cp::*, true)
+
+  template<typename _Tp>
+  struct is_member_pointer
+    : public integral_constant<bool, (__is_member_pointer_helper<
+                                     typename remove_cv<_Tp>::type>::value)>
     { };
 
   // type properties [4.5.3].