diff options
author | Jason Merrill <jason@redhat.com> | 2009-03-31 14:31:17 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2009-03-31 14:31:17 -0400 |
commit | 0d9c089222329e55fb3d372e3c8029f5a18a080f (patch) | |
tree | 155b10aa3c254e87c8ef3b1be4137739cf355dfb /gcc | |
parent | a3c497526740202a565d78c77d29f2b93c92f1ee (diff) | |
download | gcc-0d9c089222329e55fb3d372e3c8029f5a18a080f.zip gcc-0d9c089222329e55fb3d372e3c8029f5a18a080f.tar.gz gcc-0d9c089222329e55fb3d372e3c8029f5a18a080f.tar.bz2 |
re PR c++/37806 (CV-qualifiers on function typedef's are inconsistently accepted depending on typedef scope)
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/decl.c | 32 | ||||
-rw-r--r-- | gcc/cp/decl.h | 1 | ||||
-rw-r--r-- | gcc/cp/error.c | 19 | ||||
-rw-r--r-- | gcc/cp/parser.c | 25 | ||||
-rw-r--r-- | gcc/cp/tree.c | 3 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/qualttp20.C | 2 |
9 files changed, 74 insertions, 27 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 033a8f1..95079f1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4fc86c3..9878d9d 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 b16ae26..6537c50 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 b070be0..d6e3c83 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 161fa55..7d3756e 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 eacf5e9..28f47c8 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 2287f11..b4b977e 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 3788a7e..fe791f3 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 d65fd1b..f42981b5 100644 --- a/gcc/testsuite/g++.dg/template/qualttp20.C +++ b/gcc/testsuite/g++.dg/template/qualttp20.C @@ -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; |