diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 033a8f13628..95079f15c31 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,19 @@ 2009-03-31 Jason Merrill + 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. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4fc86c38d1f..9878d9d29a0 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index b16ae262bea..6537c50409f 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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; diff --git a/gcc/cp/decl.h b/gcc/cp/decl.h index b070be0ec95..d6e3c83bcbf 100644 --- a/gcc/cp/decl.h +++ b/gcc/cp/decl.h @@ -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 */ }; diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 161fa55a17f..7d3756e3340 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -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; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index eacf5e91c88..28f47c8f402 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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. diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 2287f11f04b..b4b977ef1a9 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 3788a7e8b9e..fe791f3d707 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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) { diff --git a/gcc/testsuite/g++.dg/template/qualttp20.C b/gcc/testsuite/g++.dg/template/qualttp20.C index d65fd1b61e7..f42981b52b7 100644 --- a/gcc/testsuite/g++.dg/template/qualttp20.C +++ b/gcc/testsuite/g++.dg/template/qualttp20.C @@ -17,7 +17,7 @@ struct AS template 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; diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 6b474462152..1bcfc0b8045 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,11 @@ +2009-03-31 Jason Merrill + + 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 * include/backward/hashtable.h (clear): Return quickly if the diff --git a/libstdc++-v3/include/tr1_impl/type_traits b/libstdc++-v3/include/tr1_impl/type_traits index cb0ad44a5ff..0672c398693 100644 --- a/libstdc++-v3/include/tr1_impl/type_traits +++ b/libstdc++-v3/include/tr1_impl/type_traits @@ -224,24 +224,34 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1 : public integral_constant { }; - template - struct __is_function_helper - : public false_type { }; - - template - struct __is_function_helper<_Res(_ArgTypes...)> - : public true_type { }; - - template - struct __is_function_helper<_Res(_ArgTypes......)> - : public true_type { }; - /// is_function - template + template struct is_function - : public integral_constant::type>::value)> - { }; + : public false_type { }; + template + struct is_function<_Res(_ArgTypes...)> + : public true_type { }; + template + struct is_function<_Res(_ArgTypes......)> + : public true_type { }; + template + struct is_function<_Res(_ArgTypes...) const> + : public true_type { }; + template + struct is_function<_Res(_ArgTypes......) const> + : public true_type { }; + template + struct is_function<_Res(_ArgTypes...) volatile> + : public true_type { }; + template + struct is_function<_Res(_ArgTypes......) volatile> + : public true_type { }; + template + struct is_function<_Res(_ArgTypes...) const volatile> + : public true_type { }; + template + struct is_function<_Res(_ArgTypes......) const volatile> + : public true_type { }; // composite type traits [4.5.2]. @@ -287,10 +297,14 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1 /// is_member_pointer template - struct is_member_pointer - : public integral_constant::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 + struct is_member_pointer + : public integral_constant::type>::value)> { }; // type properties [4.5.3].