This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 11551, 11919, 10762
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 21 Aug 2003 10:46:59 -0700
- Subject: C++ PATCH: PR 11551, 11919, 10762
- Reply-to: mark at codesourcery dot com
This patch fixes a few more C++ PRs.
PR 11551 is a regression where the new parser was allowing
typedef-names in the declarator-id for a destructor.
PR 11919 is a bug in overload resolution that has probably been there
forever; we were using pointer equality to determine type equality.
PR 10762 (where we were accepting template-ids in using-declarations)
is another case where we can leverage the new parser; by moving
syntax-checking into the parser, the code gets simpler and more
robust.
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
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-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.
Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.421
diff -c -5 -p -r1.421 call.c
*** cp/call.c 12 Aug 2003 22:26:20 -0000 1.421
--- cp/call.c 21 Aug 2003 17:40:10 -0000
*************** standard_conversion (tree to, tree from,
*** 793,803 ****
if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE))
return 0;
conv = build_conv (STD_CONV, to, conv);
/* Give this a better rank if it's a promotion. */
! if (to == type_promotes_to (from)
&& ICS_STD_RANK (TREE_OPERAND (conv, 0)) <= PROMO_RANK)
ICS_STD_RANK (conv) = PROMO_RANK;
}
else if (fcode == VECTOR_TYPE && tcode == VECTOR_TYPE
&& ((*targetm.vector_opaque_p) (from)
--- 793,803 ----
if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE))
return 0;
conv = build_conv (STD_CONV, to, conv);
/* Give this a better rank if it's a promotion. */
! if (same_type_p (to, type_promotes_to (from))
&& ICS_STD_RANK (TREE_OPERAND (conv, 0)) <= PROMO_RANK)
ICS_STD_RANK (conv) = PROMO_RANK;
}
else if (fcode == VECTOR_TYPE && tcode == VECTOR_TYPE
&& ((*targetm.vector_opaque_p) (from)
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.662
diff -c -5 -p -r1.662 decl2.c
*** cp/decl2.c 20 Aug 2003 07:06:41 -0000 1.662
--- cp/decl2.c 21 Aug 2003 17:40:12 -0000
*************** do_class_using_decl (tree decl)
*** 4089,4119 ****
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
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);
! }
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));
}
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716);
--- 4089,4105 ----
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
error ("using-declaration cannot name destructor");
return NULL_TREE;
}
if (TREE_CODE (name) == TYPE_DECL)
! 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);
name = DECL_NAME (get_first_fn (fns));
}
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716);
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.102
diff -c -5 -p -r1.102 parser.c
*** cp/parser.c 20 Aug 2003 07:06:42 -0000 1.102
--- cp/parser.c 21 Aug 2003 17:40:17 -0000
*************** static bool cp_parser_translation_unit
*** 1294,1306 ****
/* Expressions [gram.expr] */
static tree cp_parser_primary_expression
(cp_parser *, cp_id_kind *, tree *);
static tree cp_parser_id_expression
! (cp_parser *, bool, bool, bool *);
static tree cp_parser_unqualified_id
! (cp_parser *, bool, bool);
static tree cp_parser_nested_name_specifier_opt
(cp_parser *, bool, bool, bool);
static tree cp_parser_nested_name_specifier
(cp_parser *, bool, bool, bool);
static tree cp_parser_class_or_namespace_name
--- 1294,1306 ----
/* Expressions [gram.expr] */
static tree cp_parser_primary_expression
(cp_parser *, cp_id_kind *, tree *);
static tree cp_parser_id_expression
! (cp_parser *, bool, bool, bool *, bool);
static tree cp_parser_unqualified_id
! (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
(cp_parser *, bool, bool, bool);
static tree cp_parser_class_or_namespace_name
*************** cp_parser_primary_expression (cp_parser
*** 2396,2406 ****
/* Parse the id-expression. */
id_expression
= cp_parser_id_expression (parser,
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
! /*template_p=*/NULL);
if (id_expression == error_mark_node)
return error_mark_node;
/* If we have a template-id, then no further lookup is
required. If the template-id was for a template-class, we
will sometimes have a TYPE_DECL at this point. */
--- 2396,2407 ----
/* Parse the id-expression. */
id_expression
= cp_parser_id_expression (parser,
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
! /*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
required. If the template-id was for a template-class, we
will sometimes have a TYPE_DECL at this point. */
*************** cp_parser_primary_expression (cp_parser
*** 2493,2509 ****
If CHECK_DEPENDENCY_P is false, then names are looked up inside
uninstantiated templates.
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. */
static tree
cp_parser_id_expression (cp_parser *parser,
bool template_keyword_p,
bool check_dependency_p,
! bool *template_p)
{
bool global_scope_p;
bool nested_name_specifier_p;
/* Assume the `template' keyword was not used. */
--- 2494,2514 ----
If CHECK_DEPENDENCY_P is false, then names are looked up inside
uninstantiated templates.
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.
!
! 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 declarator_p)
{
bool global_scope_p;
bool nested_name_specifier_p;
/* Assume the `template' keyword was not used. */
*************** cp_parser_id_expression (cp_parser *pars
*** 2540,2550 ****
saved_scope = parser->scope;
saved_object_scope = parser->object_scope;
saved_qualifying_scope = parser->qualifying_scope;
/* Process the final unqualified-id. */
unqualified_id = cp_parser_unqualified_id (parser, *template_p,
! check_dependency_p);
/* Restore the SAVED_SCOPE for our caller. */
parser->scope = saved_scope;
parser->object_scope = saved_object_scope;
parser->qualifying_scope = saved_qualifying_scope;
--- 2545,2556 ----
saved_scope = parser->scope;
saved_object_scope = parser->object_scope;
saved_qualifying_scope = parser->qualifying_scope;
/* Process the final unqualified-id. */
unqualified_id = cp_parser_unqualified_id (parser, *template_p,
! check_dependency_p,
! declarator_p);
/* Restore the SAVED_SCOPE for our caller. */
parser->scope = saved_scope;
parser->object_scope = saved_object_scope;
parser->qualifying_scope = saved_qualifying_scope;
*************** cp_parser_id_expression (cp_parser *pars
*** 2595,2605 ****
return error_mark_node;
}
}
else
return cp_parser_unqualified_id (parser, template_keyword_p,
! /*check_dependency_p=*/true);
}
/* Parse an unqualified-id.
unqualified-id:
--- 2601,2612 ----
return error_mark_node;
}
}
else
return cp_parser_unqualified_id (parser, template_keyword_p,
! /*check_dependency_p=*/true,
! declarator_p);
}
/* Parse an unqualified-id.
unqualified-id:
*************** cp_parser_id_expression (cp_parser *pars
*** 2616,2631 ****
production, an IDENTIFIER_NODE is returned. For the `~ class-name'
production a BIT_NOT_EXPR is returned; the operand of the
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. */
static tree
cp_parser_unqualified_id (cp_parser* parser,
bool template_keyword_p,
! bool check_dependency_p)
{
cp_token *token;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
--- 2623,2641 ----
production, an IDENTIFIER_NODE is returned. For the `~ class-name'
production a BIT_NOT_EXPR is returned; the operand of the
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. 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 declarator_p)
{
cp_token *token;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
*************** cp_parser_unqualified_id (cp_parser* par
*** 2779,2788 ****
--- 2789,2808 ----
if (type_decl == error_mark_node && scope && TYPE_P (scope))
return build_nt (BIT_NOT_EXPR, scope);
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));
}
case CPP_KEYWORD:
if (token->keyword == RID_OPERATOR)
*************** cp_parser_postfix_expression (cp_parser
*** 3623,3633 ****
template_p = cp_parser_optional_template_keyword (parser);
/* Parse the id-expression. */
name = cp_parser_id_expression (parser,
template_p,
/*check_dependency_p=*/true,
! /*template_p=*/NULL);
/* 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
build the SCOPE_REF. For example;
--- 3643,3654 ----
template_p = cp_parser_optional_template_keyword (parser);
/* Parse the id-expression. */
name = cp_parser_id_expression (parser,
template_p,
/*check_dependency_p=*/true,
! /*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
build the SCOPE_REF. For example;
*************** cp_parser_type_parameter (cp_parser* par
*** 7384,7394 ****
/* Parse the id-expression. */
default_argument
= cp_parser_id_expression (parser,
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
! /*template_p=*/NULL);
/* Look up the name. */
default_argument
= cp_parser_lookup_name_simple (parser, default_argument);
/* See if the default argument is valid. */
default_argument
--- 7405,7416 ----
/* Parse the id-expression. */
default_argument
= cp_parser_id_expression (parser,
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
! /*template_p=*/NULL,
! /*declarator_p=*/false);
/* Look up the name. */
default_argument
= cp_parser_lookup_name_simple (parser, default_argument);
/* See if the default argument is valid. */
default_argument
*************** cp_parser_template_argument (cp_parser*
*** 7803,7813 ****
cp_parser_parse_tentatively (parser);
/* Try a template. */
argument = cp_parser_id_expression (parser,
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
! &template_p);
/* 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))
cp_parser_error (parser, "expected template-argument");
if (!cp_parser_error_occurred (parser))
--- 7825,7836 ----
cp_parser_parse_tentatively (parser);
/* Try a template. */
argument = cp_parser_id_expression (parser,
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
! &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))
cp_parser_error (parser, "expected template-argument");
if (!cp_parser_error_occurred (parser))
*************** cp_parser_using_declaration (cp_parser*
*** 8990,9028 ****
/*type_p=*/false);
/* Parse the unqualified-id. */
identifier = cp_parser_unqualified_id (parser,
/*template_keyword_p=*/false,
! /*check_dependency_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);
! }
else
{
! 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 `;'. */
cp_parser_require (parser, CPP_SEMICOLON, "`;'");
}
--- 9013,9063 ----
/*type_p=*/false);
/* Parse the unqualified-id. */
identifier = cp_parser_unqualified_id (parser,
/*template_keyword_p=*/false,
! /*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. */
! 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
{
! 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);
}
else
! {
! 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 `;'. */
cp_parser_require (parser, CPP_SEMICOLON, "`;'");
}
*************** cp_parser_declarator_id (cp_parser* pars
*** 10117,10127 ****
will work, too. */
id_expression = cp_parser_id_expression (parser,
/*template_keyword_p=*/false,
/*check_dependency_p=*/false,
! /*template_p=*/NULL);
/* If the name was qualified, create a SCOPE_REF to represent
that. */
if (parser->scope)
{
id_expression = build_nt (SCOPE_REF, parser->scope, id_expression);
--- 10152,10163 ----
will work, too. */
id_expression = cp_parser_id_expression (parser,
/*template_keyword_p=*/false,
/*check_dependency_p=*/false,
! /*template_p=*/NULL,
! /*declarator_p=*/true);
/* If the name was qualified, create a SCOPE_REF to represent
that. */
if (parser->scope)
{
id_expression = build_nt (SCOPE_REF, parser->scope, id_expression);
Index: testsuite/g++.dg/overload/prom1.C
===================================================================
RCS file: testsuite/g++.dg/overload/prom1.C
diff -N testsuite/g++.dg/overload/prom1.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/overload/prom1.C 21 Aug 2003 17:40:24 -0000
***************
*** 0 ****
--- 1,9 ----
+ void foo(signed char) {}
+ typedef int bar;
+ void foo(bar) {}
+
+ int main (int, char **) {
+ char c;
+ foo(c);
+ return 0;
+ }
Index: testsuite/g++.dg/parse/dtor2.C
===================================================================
RCS file: testsuite/g++.dg/parse/dtor2.C
diff -N testsuite/g++.dg/parse/dtor2.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/dtor2.C 21 Aug 2003 17:40:24 -0000
***************
*** 0 ****
--- 1,4 ----
+ struct A {
+ typedef A A2;
+ ~A2(); // { dg-error "" }
+ };
Index: testsuite/g++.dg/parse/using2.C
===================================================================
RCS file: testsuite/g++.dg/parse/using2.C
diff -N testsuite/g++.dg/parse/using2.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/using2.C 21 Aug 2003 17:40:24 -0000
***************
*** 0 ****
--- 1,8 ----
+ namespace N {
+ template <typename T>
+ struct foo {};
+ }
+
+ int main() {
+ using N::foo<double>; // { dg-error "" }
+ }