From f3c2dfc6293ec19dd6cd7c975d77eee3420f4cef Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Thu, 21 Aug 2003 17:44:16 +0000 Subject: [PATCH] re PR c++/11551 (g++ accepts typedef as destructor name) PR c++/11551 * parser.c (cp_parser_id_expression): Add declarator_p parameter. (cp_parser_primary_expression): Adjust call to cp_parser_id_expression. (cp_parser_unqualified_id): Complain about the use of typedef-names in a destructor declarator. (cp_parser_postfix_expression): Adjust call to cp_parser_id_expression. (cp_parser_type_parameter): Likewise. (cp_parser_template_argument): Likewise. (cp_parser_declarator_id): Likewise. PR c++/11919 * call.c (standard_conversion): Use same_type_p, not pointer equality, to compare types. PR c++/10762 * parser.c (cp_parser_using_declaration): Check for invalid uses of template-ids here... * decl2.c (do_class_using_decl): ... rather than here. PR c++/11919 * g++.dg/overload/prom1.C: New test. PR c++/11551 * g++.dg/parse/dtor2.C: New test. PR c++/10762 * g++.dg/parse/using2.C: New test. From-SVN: r70652 --- gcc/cp/ChangeLog | 23 ++++++ gcc/cp/call.c | 2 +- gcc/cp/decl2.c | 16 +--- gcc/cp/parser.c | 104 +++++++++++++++++--------- gcc/testsuite/ChangeLog | 11 +++ gcc/testsuite/g++.dg/overload/prom1.C | 9 +++ gcc/testsuite/g++.dg/parse/dtor2.C | 4 + gcc/testsuite/g++.dg/parse/using2.C | 8 ++ 8 files changed, 127 insertions(+), 50 deletions(-) create mode 100644 gcc/testsuite/g++.dg/overload/prom1.C create mode 100644 gcc/testsuite/g++.dg/parse/dtor2.C create mode 100644 gcc/testsuite/g++.dg/parse/using2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8ef1aeb0d1f..ec4f44458bd 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,26 @@ +2003-08-21 Mark Mitchell + + PR c++/11551 + * parser.c (cp_parser_id_expression): Add declarator_p parameter. + (cp_parser_primary_expression): Adjust call to + cp_parser_id_expression. + (cp_parser_unqualified_id): Complain about the use of + typedef-names in a destructor declarator. + (cp_parser_postfix_expression): Adjust call to + cp_parser_id_expression. + (cp_parser_type_parameter): Likewise. + (cp_parser_template_argument): Likewise. + (cp_parser_declarator_id): Likewise. + + PR c++/11919 + * call.c (standard_conversion): Use same_type_p, not pointer + equality, to compare types. + + PR c++/10762 + * parser.c (cp_parser_using_declaration): Check for invalid uses + of template-ids here... + * decl2.c (do_class_using_decl): ... rather than here. + 2003-08-20 Mark Mitchell PR c++/11834 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index afdc2911891..a76d2ac022a 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -795,7 +795,7 @@ standard_conversion (tree to, tree from, tree expr) conv = build_conv (STD_CONV, to, conv); /* Give this a better rank if it's a promotion. */ - if (to == type_promotes_to (from) + if (same_type_p (to, type_promotes_to (from)) && ICS_STD_RANK (TREE_OPERAND (conv, 0)) <= PROMO_RANK) ICS_STD_RANK (conv) = PROMO_RANK; } diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index a38d993e067..4eb5c0e6dae 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -4091,27 +4091,13 @@ do_class_using_decl (tree decl) error ("using-declaration cannot name destructor"); return NULL_TREE; } - else if (TREE_CODE (name) == TEMPLATE_ID_EXPR) - { - template_id_error:; - - error ("a using-declaration cannot specify a template-id"); - return NULL_TREE; - } if (TREE_CODE (name) == TYPE_DECL) - { - if (CLASSTYPE_USE_TEMPLATE (TREE_TYPE (name))) - goto template_id_error; - name = DECL_NAME (name); - } + name = DECL_NAME (name); else if (TREE_CODE (name) == TEMPLATE_DECL) name = DECL_NAME (name); else if (BASELINK_P (name)) { tree fns = BASELINK_FUNCTIONS (name); - - if (TREE_CODE (fns) == TEMPLATE_ID_EXPR) - goto template_id_error; name = DECL_NAME (get_first_fn (fns)); } diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index b2a11131463..c177a6c778d 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1296,9 +1296,9 @@ static bool cp_parser_translation_unit static tree cp_parser_primary_expression (cp_parser *, cp_id_kind *, tree *); static tree cp_parser_id_expression - (cp_parser *, bool, bool, bool *); + (cp_parser *, bool, bool, bool *, bool); static tree cp_parser_unqualified_id - (cp_parser *, bool, bool); + (cp_parser *, bool, bool, bool); static tree cp_parser_nested_name_specifier_opt (cp_parser *, bool, bool, bool); static tree cp_parser_nested_name_specifier @@ -2398,7 +2398,8 @@ cp_parser_primary_expression (cp_parser *parser, = cp_parser_id_expression (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, - /*template_p=*/NULL); + /*template_p=*/NULL, + /*declarator_p=*/false); if (id_expression == error_mark_node) return error_mark_node; /* If we have a template-id, then no further lookup is @@ -2495,13 +2496,17 @@ cp_parser_primary_expression (cp_parser *parser, If *TEMPLATE_P is non-NULL, it is set to true iff the `template' keyword is used to explicitly indicate that the entity - named is a template. */ + named is a template. + + If DECLARATOR_P is true, the id-expression is appearing as part of + a declarator, rather than as part of an exprsesion. */ static tree cp_parser_id_expression (cp_parser *parser, bool template_keyword_p, bool check_dependency_p, - bool *template_p) + bool *template_p, + bool declarator_p) { bool global_scope_p; bool nested_name_specifier_p; @@ -2542,7 +2547,8 @@ cp_parser_id_expression (cp_parser *parser, saved_qualifying_scope = parser->qualifying_scope; /* Process the final unqualified-id. */ unqualified_id = cp_parser_unqualified_id (parser, *template_p, - check_dependency_p); + check_dependency_p, + declarator_p); /* Restore the SAVED_SCOPE for our caller. */ parser->scope = saved_scope; parser->object_scope = saved_object_scope; @@ -2597,7 +2603,8 @@ cp_parser_id_expression (cp_parser *parser, } else return cp_parser_unqualified_id (parser, template_keyword_p, - /*check_dependency_p=*/true); + /*check_dependency_p=*/true, + declarator_p); } /* Parse an unqualified-id. @@ -2618,12 +2625,15 @@ cp_parser_id_expression (cp_parser *parser, BIT_NOT_EXPR is an IDENTIFIER_NODE for the class-name. For the other productions, see the documentation accompanying the corresponding parsing functions. If CHECK_DEPENDENCY_P is false, - names are looked up in uninstantiated templates. */ + names are looked up in uninstantiated templates. If DECLARATOR_P + is true, the unqualified-id is appearing as part of a declarator, + rather than as part of an expression. */ static tree cp_parser_unqualified_id (cp_parser* parser, bool template_keyword_p, - bool check_dependency_p) + bool check_dependency_p, + bool declarator_p) { cp_token *token; @@ -2781,6 +2791,16 @@ cp_parser_unqualified_id (cp_parser* parser, else if (type_decl == error_mark_node) return error_mark_node; + /* [class.dtor] + + A typedef-name that names a class shall not be used as the + identifier in the declarator for a destructor declaration. */ + if (declarator_p + && !DECL_IMPLICIT_TYPEDEF_P (type_decl) + && !DECL_SELF_REFERENCE_P (type_decl)) + error ("typedef-name `%D' used as destructor declarator", + type_decl); + return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl)); } @@ -3625,7 +3645,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p) name = cp_parser_id_expression (parser, template_p, /*check_dependency_p=*/true, - /*template_p=*/NULL); + /*template_p=*/NULL, + /*declarator_p=*/false); /* In general, build a SCOPE_REF if the member name is qualified. However, if the name was not dependent and has already been resolved; there is no need to @@ -7386,7 +7407,8 @@ cp_parser_type_parameter (cp_parser* parser) = cp_parser_id_expression (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, - /*template_p=*/NULL); + /*template_p=*/NULL, + /*declarator_p=*/false); /* Look up the name. */ default_argument = cp_parser_lookup_name_simple (parser, default_argument); @@ -7805,7 +7827,8 @@ cp_parser_template_argument (cp_parser* parser) argument = cp_parser_id_expression (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, - &template_p); + &template_p, + /*declarator_p=*/false); /* If the next token isn't a `,' or a `>', then this argument wasn't really finished. */ if (!cp_parser_next_token_ends_template_argument_p (parser)) @@ -8992,35 +9015,47 @@ cp_parser_using_declaration (cp_parser* parser) /* Parse the unqualified-id. */ identifier = cp_parser_unqualified_id (parser, /*template_keyword_p=*/false, - /*check_dependency_p=*/true); + /*check_dependency_p=*/true, + /*declarator_p=*/true); /* The function we call to handle a using-declaration is different depending on what scope we are in. */ - scope = current_scope (); - if (scope && TYPE_P (scope)) - { - /* Create the USING_DECL. */ - decl = do_class_using_decl (build_nt (SCOPE_REF, - parser->scope, - identifier)); - /* Add it to the list of members in this class. */ - finish_member_declaration (decl); - } + if (identifier == error_mark_node) + ; + else if (TREE_CODE (identifier) != IDENTIFIER_NODE + && TREE_CODE (identifier) != BIT_NOT_EXPR) + /* [namespace.udecl] + + A using declaration shall not name a template-id. */ + error ("a template-id may not appear in a using-declaration"); else { - decl = cp_parser_lookup_name_simple (parser, identifier); - if (decl == error_mark_node) + scope = current_scope (); + if (scope && TYPE_P (scope)) { - if (parser->scope && parser->scope != global_namespace) - error ("`%D::%D' has not been declared", - parser->scope, identifier); - else - error ("`::%D' has not been declared", identifier); + /* Create the USING_DECL. */ + decl = do_class_using_decl (build_nt (SCOPE_REF, + parser->scope, + identifier)); + /* Add it to the list of members in this class. */ + finish_member_declaration (decl); } - else if (scope) - do_local_using_decl (decl); else - do_toplevel_using_decl (decl); + { + decl = cp_parser_lookup_name_simple (parser, identifier); + if (decl == error_mark_node) + { + if (parser->scope && parser->scope != global_namespace) + error ("`%D::%D' has not been declared", + parser->scope, identifier); + else + error ("`::%D' has not been declared", identifier); + } + else if (scope) + do_local_using_decl (decl); + else + do_toplevel_using_decl (decl); + } } /* Look for the final `;'. */ @@ -10119,7 +10154,8 @@ cp_parser_declarator_id (cp_parser* parser) id_expression = cp_parser_id_expression (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/false, - /*template_p=*/NULL); + /*template_p=*/NULL, + /*declarator_p=*/true); /* If the name was qualified, create a SCOPE_REF to represent that. */ if (parser->scope) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 65d03080db4..6aa9a0a3a72 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2003-08-21 Mark Mitchell + + PR c++/11919 + * g++.dg/overload/prom1.C: New test. + + PR c++/11551 + * g++.dg/parse/dtor2.C: New test. + + PR c++/10762 + * g++.dg/parse/using2.C: New test. + 2003-08-21 Kazu Hirata PR target/11805 diff --git a/gcc/testsuite/g++.dg/overload/prom1.C b/gcc/testsuite/g++.dg/overload/prom1.C new file mode 100644 index 00000000000..9eb387dc43a --- /dev/null +++ b/gcc/testsuite/g++.dg/overload/prom1.C @@ -0,0 +1,9 @@ +void foo(signed char) {} +typedef int bar; +void foo(bar) {} + +int main (int, char **) { + char c; + foo(c); + return 0; +} diff --git a/gcc/testsuite/g++.dg/parse/dtor2.C b/gcc/testsuite/g++.dg/parse/dtor2.C new file mode 100644 index 00000000000..60e132b4a9b --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/dtor2.C @@ -0,0 +1,4 @@ +struct A { + typedef A A2; + ~A2(); // { dg-error "" } +}; diff --git a/gcc/testsuite/g++.dg/parse/using2.C b/gcc/testsuite/g++.dg/parse/using2.C new file mode 100644 index 00000000000..bfdb09f8833 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/using2.C @@ -0,0 +1,8 @@ +namespace N { + template + struct foo {}; +} + +int main() { + using N::foo; // { dg-error "" } +}