Commit f3c2dfc6 by Mark Mitchell Committed by Mark Mitchell

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
parent ca11c37c
2003-08-21 Mark Mitchell <mark@codesourcery.com>
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 <mark@codesourcery.com> 2003-08-20 Mark Mitchell <mark@codesourcery.com>
PR c++/11834 PR c++/11834
......
...@@ -795,7 +795,7 @@ standard_conversion (tree to, tree from, tree expr) ...@@ -795,7 +795,7 @@ standard_conversion (tree to, tree from, tree expr)
conv = build_conv (STD_CONV, to, conv); conv = build_conv (STD_CONV, to, conv);
/* Give this a better rank if it's a promotion. */ /* 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 (TREE_OPERAND (conv, 0)) <= PROMO_RANK)
ICS_STD_RANK (conv) = PROMO_RANK; ICS_STD_RANK (conv) = PROMO_RANK;
} }
......
...@@ -4091,27 +4091,13 @@ do_class_using_decl (tree decl) ...@@ -4091,27 +4091,13 @@ do_class_using_decl (tree decl)
error ("using-declaration cannot name destructor"); error ("using-declaration cannot name destructor");
return NULL_TREE; 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 (TREE_CODE (name) == TYPE_DECL)
{ name = DECL_NAME (name);
if (CLASSTYPE_USE_TEMPLATE (TREE_TYPE (name)))
goto template_id_error;
name = DECL_NAME (name);
}
else if (TREE_CODE (name) == TEMPLATE_DECL) else if (TREE_CODE (name) == TEMPLATE_DECL)
name = DECL_NAME (name); name = DECL_NAME (name);
else if (BASELINK_P (name)) else if (BASELINK_P (name))
{ {
tree fns = BASELINK_FUNCTIONS (name); tree fns = BASELINK_FUNCTIONS (name);
if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
goto template_id_error;
name = DECL_NAME (get_first_fn (fns)); name = DECL_NAME (get_first_fn (fns));
} }
......
...@@ -1296,9 +1296,9 @@ static bool cp_parser_translation_unit ...@@ -1296,9 +1296,9 @@ static bool cp_parser_translation_unit
static tree cp_parser_primary_expression static tree cp_parser_primary_expression
(cp_parser *, cp_id_kind *, tree *); (cp_parser *, cp_id_kind *, tree *);
static tree cp_parser_id_expression static tree cp_parser_id_expression
(cp_parser *, bool, bool, bool *); (cp_parser *, bool, bool, bool *, bool);
static tree cp_parser_unqualified_id static tree cp_parser_unqualified_id
(cp_parser *, bool, bool); (cp_parser *, bool, bool, bool);
static tree cp_parser_nested_name_specifier_opt static tree cp_parser_nested_name_specifier_opt
(cp_parser *, bool, bool, bool); (cp_parser *, bool, bool, bool);
static tree cp_parser_nested_name_specifier static tree cp_parser_nested_name_specifier
...@@ -2398,7 +2398,8 @@ cp_parser_primary_expression (cp_parser *parser, ...@@ -2398,7 +2398,8 @@ cp_parser_primary_expression (cp_parser *parser,
= cp_parser_id_expression (parser, = cp_parser_id_expression (parser,
/*template_keyword_p=*/false, /*template_keyword_p=*/false,
/*check_dependency_p=*/true, /*check_dependency_p=*/true,
/*template_p=*/NULL); /*template_p=*/NULL,
/*declarator_p=*/false);
if (id_expression == error_mark_node) if (id_expression == error_mark_node)
return error_mark_node; return error_mark_node;
/* If we have a template-id, then no further lookup is /* If we have a template-id, then no further lookup is
...@@ -2495,13 +2496,17 @@ cp_parser_primary_expression (cp_parser *parser, ...@@ -2495,13 +2496,17 @@ cp_parser_primary_expression (cp_parser *parser,
If *TEMPLATE_P is non-NULL, it is set to true iff the If *TEMPLATE_P is non-NULL, it is set to true iff the
`template' keyword is used to explicitly indicate that the entity `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 static tree
cp_parser_id_expression (cp_parser *parser, cp_parser_id_expression (cp_parser *parser,
bool template_keyword_p, bool template_keyword_p,
bool check_dependency_p, bool check_dependency_p,
bool *template_p) bool *template_p,
bool declarator_p)
{ {
bool global_scope_p; bool global_scope_p;
bool nested_name_specifier_p; bool nested_name_specifier_p;
...@@ -2542,7 +2547,8 @@ cp_parser_id_expression (cp_parser *parser, ...@@ -2542,7 +2547,8 @@ cp_parser_id_expression (cp_parser *parser,
saved_qualifying_scope = parser->qualifying_scope; saved_qualifying_scope = parser->qualifying_scope;
/* Process the final unqualified-id. */ /* Process the final unqualified-id. */
unqualified_id = cp_parser_unqualified_id (parser, *template_p, unqualified_id = cp_parser_unqualified_id (parser, *template_p,
check_dependency_p); check_dependency_p,
declarator_p);
/* Restore the SAVED_SCOPE for our caller. */ /* Restore the SAVED_SCOPE for our caller. */
parser->scope = saved_scope; parser->scope = saved_scope;
parser->object_scope = saved_object_scope; parser->object_scope = saved_object_scope;
...@@ -2597,7 +2603,8 @@ cp_parser_id_expression (cp_parser *parser, ...@@ -2597,7 +2603,8 @@ cp_parser_id_expression (cp_parser *parser,
} }
else else
return cp_parser_unqualified_id (parser, template_keyword_p, return cp_parser_unqualified_id (parser, template_keyword_p,
/*check_dependency_p=*/true); /*check_dependency_p=*/true,
declarator_p);
} }
/* Parse an unqualified-id. /* Parse an unqualified-id.
...@@ -2618,12 +2625,15 @@ cp_parser_id_expression (cp_parser *parser, ...@@ -2618,12 +2625,15 @@ cp_parser_id_expression (cp_parser *parser,
BIT_NOT_EXPR is an IDENTIFIER_NODE for the class-name. For the BIT_NOT_EXPR is an IDENTIFIER_NODE for the class-name. For the
other productions, see the documentation accompanying the other productions, see the documentation accompanying the
corresponding parsing functions. If CHECK_DEPENDENCY_P is false, 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 static tree
cp_parser_unqualified_id (cp_parser* parser, cp_parser_unqualified_id (cp_parser* parser,
bool template_keyword_p, bool template_keyword_p,
bool check_dependency_p) bool check_dependency_p,
bool declarator_p)
{ {
cp_token *token; cp_token *token;
...@@ -2781,6 +2791,16 @@ cp_parser_unqualified_id (cp_parser* parser, ...@@ -2781,6 +2791,16 @@ cp_parser_unqualified_id (cp_parser* parser,
else if (type_decl == error_mark_node) else if (type_decl == error_mark_node)
return 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)); return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
} }
...@@ -3625,7 +3645,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p) ...@@ -3625,7 +3645,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
name = cp_parser_id_expression (parser, name = cp_parser_id_expression (parser,
template_p, template_p,
/*check_dependency_p=*/true, /*check_dependency_p=*/true,
/*template_p=*/NULL); /*template_p=*/NULL,
/*declarator_p=*/false);
/* In general, build a SCOPE_REF if the member name is /* In general, build a SCOPE_REF if the member name is
qualified. However, if the name was not dependent qualified. However, if the name was not dependent
and has already been resolved; there is no need to and has already been resolved; there is no need to
...@@ -7386,7 +7407,8 @@ cp_parser_type_parameter (cp_parser* parser) ...@@ -7386,7 +7407,8 @@ cp_parser_type_parameter (cp_parser* parser)
= cp_parser_id_expression (parser, = cp_parser_id_expression (parser,
/*template_keyword_p=*/false, /*template_keyword_p=*/false,
/*check_dependency_p=*/true, /*check_dependency_p=*/true,
/*template_p=*/NULL); /*template_p=*/NULL,
/*declarator_p=*/false);
/* Look up the name. */ /* Look up the name. */
default_argument default_argument
= cp_parser_lookup_name_simple (parser, default_argument); = cp_parser_lookup_name_simple (parser, default_argument);
...@@ -7805,7 +7827,8 @@ cp_parser_template_argument (cp_parser* parser) ...@@ -7805,7 +7827,8 @@ cp_parser_template_argument (cp_parser* parser)
argument = cp_parser_id_expression (parser, argument = cp_parser_id_expression (parser,
/*template_keyword_p=*/false, /*template_keyword_p=*/false,
/*check_dependency_p=*/true, /*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 /* If the next token isn't a `,' or a `>', then this argument wasn't
really finished. */ really finished. */
if (!cp_parser_next_token_ends_template_argument_p (parser)) if (!cp_parser_next_token_ends_template_argument_p (parser))
...@@ -8992,35 +9015,47 @@ cp_parser_using_declaration (cp_parser* parser) ...@@ -8992,35 +9015,47 @@ cp_parser_using_declaration (cp_parser* parser)
/* Parse the unqualified-id. */ /* Parse the unqualified-id. */
identifier = cp_parser_unqualified_id (parser, identifier = cp_parser_unqualified_id (parser,
/*template_keyword_p=*/false, /*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 /* The function we call to handle a using-declaration is different
depending on what scope we are in. */ depending on what scope we are in. */
scope = current_scope (); if (identifier == error_mark_node)
if (scope && TYPE_P (scope)) ;
{ else if (TREE_CODE (identifier) != IDENTIFIER_NODE
/* Create the USING_DECL. */ && TREE_CODE (identifier) != BIT_NOT_EXPR)
decl = do_class_using_decl (build_nt (SCOPE_REF, /* [namespace.udecl]
parser->scope,
identifier)); A using declaration shall not name a template-id. */
/* Add it to the list of members in this class. */ error ("a template-id may not appear in a using-declaration");
finish_member_declaration (decl);
}
else else
{ {
decl = cp_parser_lookup_name_simple (parser, identifier); scope = current_scope ();
if (decl == error_mark_node) if (scope && TYPE_P (scope))
{ {
if (parser->scope && parser->scope != global_namespace) /* Create the USING_DECL. */
error ("`%D::%D' has not been declared", decl = do_class_using_decl (build_nt (SCOPE_REF,
parser->scope, identifier); parser->scope,
else identifier));
error ("`::%D' has not been declared", identifier); /* Add it to the list of members in this class. */
finish_member_declaration (decl);
} }
else if (scope)
do_local_using_decl (decl);
else 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 `;'. */ /* Look for the final `;'. */
...@@ -10119,7 +10154,8 @@ cp_parser_declarator_id (cp_parser* parser) ...@@ -10119,7 +10154,8 @@ cp_parser_declarator_id (cp_parser* parser)
id_expression = cp_parser_id_expression (parser, id_expression = cp_parser_id_expression (parser,
/*template_keyword_p=*/false, /*template_keyword_p=*/false,
/*check_dependency_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 /* If the name was qualified, create a SCOPE_REF to represent
that. */ that. */
if (parser->scope) if (parser->scope)
......
2003-08-21 Mark Mitchell <mark@codesourcery.com>
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 <kazu@cs.umass.edu> 2003-08-21 Kazu Hirata <kazu@cs.umass.edu>
PR target/11805 PR target/11805
......
void foo(signed char) {}
typedef int bar;
void foo(bar) {}
int main (int, char **) {
char c;
foo(c);
return 0;
}
struct A {
typedef A A2;
~A2(); // { dg-error "" }
};
namespace N {
template <typename T>
struct foo {};
}
int main() {
using N::foo<double>; // { dg-error "" }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment