re PR c++/23287 (Explicitly invoking destructor of template class in a template and is dependent)

cp/
	PR c++/23287
	* parser.c (cp_parser_id_expression): Add member_p
	argument. Update all callers.
	(cp_parser_unqualified_id): Likewise.  Lookup a destructor name in
	the object's scope, if valid.
	(cp_parser_global_scope_opt): Add object_scope_valid_p.  Update
	callers.
	(cp_parser_postfix_dot_deref_expression): Set object_scope.
	* pt.c (tsubst_copy_and_build): Lookup dependent dtor name here.
testsuite/
	PR c++/23287
	* g++.dg/parse/dtor12.C: New.

From-SVN: r116623
This commit is contained in:
Nathan Sidwell 2006-09-01 13:46:19 +00:00 committed by Nathan Sidwell
parent 39aa3581c4
commit 429b876b07
5 changed files with 147 additions and 42 deletions

View File

@ -1,3 +1,15 @@
2006-09-01 Nathan Sidwell <nathan@codesourcery.com>
PR c++/23287
* parser.c (cp_parser_id_expression): Add member_p
argument. Update all callers.
(cp_parser_unqualified_id): Likewise. Lookup a destructor name in
the object's scope, if valid.
(cp_parser_global_scope_opt): Add object_scope_valid_p. Update
callers.
(cp_parser_postfix_dot_deref_expression): Set object_scope.
* pt.c (tsubst_copy_and_build): Lookup dependent dtor name here.
2006-08-30 Jason Merrill <jason@redhat.com> 2006-08-30 Jason Merrill <jason@redhat.com>
PR c++/26670 PR c++/26670

View File

@ -1393,9 +1393,9 @@ static bool cp_parser_translation_unit
static tree cp_parser_primary_expression static tree cp_parser_primary_expression
(cp_parser *, bool, bool, bool, cp_id_kind *); (cp_parser *, bool, bool, bool, cp_id_kind *);
static tree cp_parser_id_expression static tree cp_parser_id_expression
(cp_parser *, bool, bool, bool *, bool, bool); (cp_parser *, bool, bool, bool *, bool, bool, bool);
static tree cp_parser_unqualified_id static tree cp_parser_unqualified_id
(cp_parser *, bool, bool, bool, bool); (cp_parser *, bool, bool, bool, bool, bool);
static tree cp_parser_nested_name_specifier_opt static tree cp_parser_nested_name_specifier_opt
(cp_parser *, bool, bool, bool, bool); (cp_parser *, bool, bool, bool, bool);
static tree cp_parser_nested_name_specifier static tree cp_parser_nested_name_specifier
@ -1720,7 +1720,7 @@ static bool cp_parser_check_template_parameters
static tree cp_parser_simple_cast_expression static tree cp_parser_simple_cast_expression
(cp_parser *); (cp_parser *);
static tree cp_parser_global_scope_opt static tree cp_parser_global_scope_opt
(cp_parser *, bool); (cp_parser *, bool, bool);
static bool cp_parser_constructor_declarator_p static bool cp_parser_constructor_declarator_p
(cp_parser *, bool); (cp_parser *, bool);
static tree cp_parser_function_definition_from_specifiers_and_declarator static tree cp_parser_function_definition_from_specifiers_and_declarator
@ -2182,7 +2182,8 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
/*check_dependency_p=*/true, /*check_dependency_p=*/true,
/*template_p=*/NULL, /*template_p=*/NULL,
/*declarator_p=*/true, /*declarator_p=*/true,
/*optional_p=*/false); /*optional_p=*/false,
/*member_p=*/false);
/* After the id-expression, there should be a plain identifier, /* After the id-expression, there should be a plain identifier,
otherwise this is not a simple variable declaration. Also, if otherwise this is not a simple variable declaration. Also, if
the scope is dependent, we cannot do much. */ the scope is dependent, we cannot do much. */
@ -3061,7 +3062,8 @@ cp_parser_primary_expression (cp_parser *parser,
/*check_dependency_p=*/true, /*check_dependency_p=*/true,
&template_p, &template_p,
/*declarator_p=*/false, /*declarator_p=*/false,
/*optional_p=*/false); /*optional_p=*/false,
/*member_p=*/false);
if (id_expression == error_mark_node) if (id_expression == error_mark_node)
return error_mark_node; return error_mark_node;
token = cp_lexer_peek_token (parser->lexer); token = cp_lexer_peek_token (parser->lexer);
@ -3195,7 +3197,8 @@ cp_parser_id_expression (cp_parser *parser,
bool check_dependency_p, bool check_dependency_p,
bool *template_p, bool *template_p,
bool declarator_p, bool declarator_p,
bool optional_p) bool optional_p,
bool member_p)
{ {
bool global_scope_p; bool global_scope_p;
bool nested_name_specifier_p; bool nested_name_specifier_p;
@ -3206,8 +3209,10 @@ cp_parser_id_expression (cp_parser *parser,
/* Look for the optional `::' operator. */ /* Look for the optional `::' operator. */
global_scope_p global_scope_p
= (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false) = (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false,
/*object_scope_valid_p=*/member_p)
!= NULL_TREE); != NULL_TREE);
/* Look for the optional nested-name-specifier. */ /* Look for the optional nested-name-specifier. */
nested_name_specifier_p nested_name_specifier_p
= (cp_parser_nested_name_specifier_opt (parser, = (cp_parser_nested_name_specifier_opt (parser,
@ -3239,7 +3244,8 @@ cp_parser_id_expression (cp_parser *parser,
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, declarator_p,
/*optional_p=*/false); /*optional_p=*/false,
/*member_p=*/false);
/* 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;
@ -3297,8 +3303,7 @@ 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, declarator_p, optional_p, member_p);
optional_p);
} }
/* Parse an unqualified-id. /* Parse an unqualified-id.
@ -3328,7 +3333,8 @@ 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, bool declarator_p,
bool optional_p) bool optional_p,
bool member_p)
{ {
cp_token *token; cp_token *token;
@ -3456,6 +3462,7 @@ cp_parser_unqualified_id (cp_parser* parser,
if (cp_parser_parse_definitely (parser)) if (cp_parser_parse_definitely (parser))
done = true; done = true;
} }
/* In "N::S::~S", look in "N" as well. */ /* In "N::S::~S", look in "N" as well. */
if (!done && scope && qualifying_scope) if (!done && scope && qualifying_scope)
{ {
@ -3474,24 +3481,56 @@ cp_parser_unqualified_id (cp_parser* parser,
if (cp_parser_parse_definitely (parser)) if (cp_parser_parse_definitely (parser))
done = true; done = true;
} }
/* In "p->S::~T", look in the scope given by "*p" as well. */ /* In "p->~T", look in the scope given by "*p" as well. */
else if (!done && object_scope) else if (!done && member_p)
{ {
if (!object_scope)
{
/* It's a dependent expression, so just parse the
dtor name. */
tree id;
if (template_keyword_p)
/* It's a template-id. */
id = cp_parser_template_id (parser, true,
check_dependency_p,
declarator_p);
else
{
/* Otherwise, it's an ordinary identifier. */
id = cp_parser_identifier (parser);
/* If ID is a template type parm, then use that
directly. */
if (TREE_TYPE (id)
&& TREE_CODE (TREE_TYPE (id)) == TEMPLATE_TYPE_PARM)
id = TREE_TYPE (id);
}
if (id != error_mark_node)
id = build_nt (BIT_NOT_EXPR, id);
return id;
}
cp_parser_parse_tentatively (parser); cp_parser_parse_tentatively (parser);
parser->scope = object_scope; parser->scope = object_scope;
parser->object_scope = NULL_TREE; parser->object_scope = NULL_TREE;
parser->qualifying_scope = NULL_TREE; parser->qualifying_scope = NULL_TREE;
type_decl type_decl
= cp_parser_class_name (parser, = cp_parser_class_name (parser,
/*typename_keyword_p=*/false, /*typename_keyword_p=*/false,
/*template_keyword_p=*/false, /*template_keyword_p=*/false,
none_type, none_type,
/*check_dependency=*/false, /*check_dependency=*/false,
/*class_head_p=*/false, /*class_head_p=*/false,
declarator_p); declarator_p);
/* The name is not qualified, so reset the parser scopes
so our callers do not get confused. */
parser->object_scope = object_scope;
parser->scope = NULL_TREE;
if (cp_parser_parse_definitely (parser)) if (cp_parser_parse_definitely (parser))
done = true; done = true;
} }
/* Look in the surrounding context. */ /* Look in the surrounding context. */
if (!done) if (!done)
{ {
@ -4482,11 +4521,12 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
parser->qualifying_scope = NULL_TREE; parser->qualifying_scope = NULL_TREE;
parser->object_scope = NULL_TREE; parser->object_scope = NULL_TREE;
*idk = CP_ID_KIND_NONE; *idk = CP_ID_KIND_NONE;
/* Enter the scope corresponding to the type of the object /* Enter the scope corresponding to the type of the object
given by the POSTFIX_EXPRESSION. */ given by the POSTFIX_EXPRESSION. */
if (!dependent_p && TREE_TYPE (postfix_expression) != NULL_TREE) scope = TREE_TYPE (postfix_expression);
if (!dependent_p && scope)
{ {
scope = TREE_TYPE (postfix_expression);
/* According to the standard, no expression should ever have /* According to the standard, no expression should ever have
reference type. Unfortunately, we do not currently match reference type. Unfortunately, we do not currently match
the standard in this respect in that our internal representation the standard in this respect in that our internal representation
@ -4500,11 +4540,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
error ("%qE does not have class type", postfix_expression); error ("%qE does not have class type", postfix_expression);
scope = NULL_TREE; scope = NULL_TREE;
} }
else else if (!dependent_p)
scope = complete_type_or_else (scope, NULL_TREE); scope = complete_type_or_else (scope, NULL_TREE);
/* Let the name lookup machinery know that we are processing a
class member access expression. */
parser->context->object_type = scope;
/* If something went wrong, we want to be able to discern that case, /* If something went wrong, we want to be able to discern that case,
as opposed to the case where there was no SCOPE due to the type as opposed to the case where there was no SCOPE due to the type
of expression being dependent. */ of expression being dependent. */
@ -4516,6 +4553,10 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
if (scope == error_mark_node) if (scope == error_mark_node)
postfix_expression = error_mark_node; postfix_expression = error_mark_node;
} }
/* Let the name lookup machinery know that we are processing a class
member access expression. */
parser->context->object_type = scope;
parser->object_scope = scope;
/* Assume this expression is not a pseudo-destructor access. */ /* Assume this expression is not a pseudo-destructor access. */
pseudo_destructor_p = false; pseudo_destructor_p = false;
@ -4553,7 +4594,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
/*check_dependency_p=*/true, /*check_dependency_p=*/true,
&template_p, &template_p,
/*declarator_p=*/false, /*declarator_p=*/false,
/*optional_p=*/false)); /*optional_p=*/false,
/*member_p=*/true));
/* In general, build a SCOPE_REF if the member name is qualified. /* In general, build a SCOPE_REF if the member name is qualified.
However, if the name was not dependent and has already been However, if the name was not dependent and has already been
resolved; there is no need to build the SCOPE_REF. For example; resolved; there is no need to build the SCOPE_REF. For example;
@ -4758,7 +4800,9 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
*type = error_mark_node; *type = error_mark_node;
/* Look for the optional `::' operator. */ /* Look for the optional `::' operator. */
cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/true); cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/true,
/*object_scop_valid_p=*/true);
/* Look for the optional nested-name-specifier. */ /* Look for the optional nested-name-specifier. */
nested_name_specifier_p nested_name_specifier_p
= (cp_parser_nested_name_specifier_opt (parser, = (cp_parser_nested_name_specifier_opt (parser,
@ -5069,7 +5113,8 @@ cp_parser_new_expression (cp_parser* parser)
/* Look for the optional `::' operator. */ /* Look for the optional `::' operator. */
global_scope_p global_scope_p
= (cp_parser_global_scope_opt (parser, = (cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/false) /*current_scope_valid_p=*/false,
/*object_scope_valid_p=*/false)
!= NULL_TREE); != NULL_TREE);
/* Look for the `new' operator. */ /* Look for the `new' operator. */
cp_parser_require_keyword (parser, RID_NEW, "`new'"); cp_parser_require_keyword (parser, RID_NEW, "`new'");
@ -5367,7 +5412,8 @@ cp_parser_delete_expression (cp_parser* parser)
/* Look for the optional `::' operator. */ /* Look for the optional `::' operator. */
global_scope_p global_scope_p
= (cp_parser_global_scope_opt (parser, = (cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/false) /*current_scope_valid_p=*/false,
/*object_scope_valid_p=*/false)
!= NULL_TREE); != NULL_TREE);
/* Look for the `delete' keyword. */ /* Look for the `delete' keyword. */
cp_parser_require_keyword (parser, RID_DELETE, "`delete'"); cp_parser_require_keyword (parser, RID_DELETE, "`delete'");
@ -8022,7 +8068,8 @@ cp_parser_mem_initializer_id (cp_parser* parser)
/* Look for the optional `::' operator. */ /* Look for the optional `::' operator. */
global_scope_p global_scope_p
= (cp_parser_global_scope_opt (parser, = (cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/false) /*current_scope_valid_p=*/false,
/*object_scope_valid_p=*/false)
!= NULL_TREE); != NULL_TREE);
/* Look for the optional nested-name-specifier. The simplest way to /* Look for the optional nested-name-specifier. The simplest way to
implement: implement:
@ -8594,7 +8641,8 @@ cp_parser_type_parameter (cp_parser* parser)
/*check_dependency_p=*/true, /*check_dependency_p=*/true,
/*template_p=*/&is_template, /*template_p=*/&is_template,
/*declarator_p=*/false, /*declarator_p=*/false,
/*optional_p=*/false); /*optional_p=*/false,
/*member_p=*/false);
if (TREE_CODE (default_argument) == TYPE_DECL) if (TREE_CODE (default_argument) == TYPE_DECL)
/* If the id-expression was a template-id that refers to /* If the id-expression was a template-id that refers to
a template-class, we already have the declaration here, a template-class, we already have the declaration here,
@ -9159,7 +9207,8 @@ cp_parser_template_argument (cp_parser* parser)
/*check_dependency_p=*/true, /*check_dependency_p=*/true,
&template_p, &template_p,
/*declarator_p=*/false, /*declarator_p=*/false,
/*optional_p=*/false); /*optional_p=*/false,
/*member_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))
@ -9799,7 +9848,8 @@ cp_parser_simple_type_specifier (cp_parser* parser,
/* Look for the optional `::' operator. */ /* Look for the optional `::' operator. */
global_p global_p
= (cp_parser_global_scope_opt (parser, = (cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/false) /*current_scope_valid_p=*/false,
/*object_scope_valid_p=*/false)
!= NULL_TREE); != NULL_TREE);
/* Look for the nested-name specifier. */ /* Look for the nested-name specifier. */
qualified_p qualified_p
@ -10024,7 +10074,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
/* Look for the `::' operator. */ /* Look for the `::' operator. */
cp_parser_global_scope_opt (parser, cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/false); /*current_scope_valid_p=*/false,
/*object_scope_valid_p=*/false);
/* Look for the nested-name-specifier. */ /* Look for the nested-name-specifier. */
if (tag_type == typename_type) if (tag_type == typename_type)
{ {
@ -10559,7 +10610,8 @@ cp_parser_qualified_namespace_specifier (cp_parser* parser)
{ {
/* Look for the optional `::'. */ /* Look for the optional `::'. */
cp_parser_global_scope_opt (parser, cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/false); /*current_scope_valid_p=*/false,
/*object_scope_valid_p=*/false);
/* Look for the optional nested-name-specifier. */ /* Look for the optional nested-name-specifier. */
cp_parser_nested_name_specifier_opt (parser, cp_parser_nested_name_specifier_opt (parser,
@ -10604,7 +10656,8 @@ cp_parser_using_declaration (cp_parser* parser)
/* Look for the optional global scope qualification. */ /* Look for the optional global scope qualification. */
global_scope_p global_scope_p
= (cp_parser_global_scope_opt (parser, = (cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/false) /*current_scope_valid_p=*/false,
/*object_scope_valid_p=*/false)
!= NULL_TREE); != NULL_TREE);
/* If we saw `typename', or didn't see `::', then there must be a /* If we saw `typename', or didn't see `::', then there must be a
@ -10630,7 +10683,8 @@ cp_parser_using_declaration (cp_parser* parser)
/*template_keyword_p=*/false, /*template_keyword_p=*/false,
/*check_dependency_p=*/true, /*check_dependency_p=*/true,
/*declarator_p=*/true, /*declarator_p=*/true,
/*optional_p=*/false); /*optional_p=*/false,
/*member_p=*/false);
/* 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. */
@ -10684,7 +10738,8 @@ cp_parser_using_directive (cp_parser* parser)
/* And the `namespace' keyword. */ /* And the `namespace' keyword. */
cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'"); cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'");
/* Look for the optional `::' operator. */ /* Look for the optional `::' operator. */
cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false); cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false,
/*object_scope_valid_p=*/false);
/* And the optional nested-name-specifier. */ /* And the optional nested-name-specifier. */
cp_parser_nested_name_specifier_opt (parser, cp_parser_nested_name_specifier_opt (parser,
/*typename_keyword_p=*/false, /*typename_keyword_p=*/false,
@ -11752,7 +11807,8 @@ cp_parser_ptr_operator (cp_parser* parser,
cp_parser_parse_tentatively (parser); cp_parser_parse_tentatively (parser);
/* Look for the optional `::' operator. */ /* Look for the optional `::' operator. */
cp_parser_global_scope_opt (parser, cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/false); /*current_scope_valid_p=*/false,
/*object_scope_valid_p=*/false);
/* Look for the nested-name specifier. */ /* Look for the nested-name specifier. */
cp_parser_nested_name_specifier (parser, cp_parser_nested_name_specifier (parser,
/*typename_keyword_p=*/false, /*typename_keyword_p=*/false,
@ -11892,7 +11948,8 @@ cp_parser_declarator_id (cp_parser* parser, bool optional_p)
/*check_dependency_p=*/false, /*check_dependency_p=*/false,
/*template_p=*/NULL, /*template_p=*/NULL,
/*declarator_p=*/true, /*declarator_p=*/true,
optional_p); optional_p,
/*member_p=*/false);
if (id && BASELINK_P (id)) if (id && BASELINK_P (id))
id = BASELINK_FUNCTIONS (id); id = BASELINK_FUNCTIONS (id);
return id; return id;
@ -13097,7 +13154,8 @@ cp_parser_class_head (cp_parser* parser,
issuing an error about it later if this really is a issuing an error about it later if this really is a
class-head. If it turns out just to be an elaborated type class-head. If it turns out just to be an elaborated type
specifier, remain silent. */ specifier, remain silent. */
if (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false)) if (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false,
/*object_scope_valid_p=*/false))
qualified_p = true; qualified_p = true;
push_deferring_access_checks (dk_no_check); push_deferring_access_checks (dk_no_check);
@ -14083,7 +14141,8 @@ cp_parser_base_specifier (cp_parser* parser)
} }
/* Look for the optional `::' operator. */ /* Look for the optional `::' operator. */
cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false); cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false,
/*object_scope_valid_p=*/false);
/* Look for the nested-name-specifier. The simplest way to /* Look for the nested-name-specifier. The simplest way to
implement: implement:
@ -15132,7 +15191,8 @@ cp_parser_check_template_parameters (cp_parser* parser,
present, and NULL_TREE otherwise. */ present, and NULL_TREE otherwise. */
static tree static tree
cp_parser_global_scope_opt (cp_parser* parser, bool current_scope_valid_p) cp_parser_global_scope_opt (cp_parser* parser, bool current_scope_valid_p,
bool object_scope_valid_p)
{ {
cp_token *token; cp_token *token;
@ -15151,12 +15211,15 @@ cp_parser_global_scope_opt (cp_parser* parser, bool current_scope_valid_p)
return parser->scope; return parser->scope;
} }
else if (!current_scope_valid_p)
if (!current_scope_valid_p)
{ {
parser->scope = NULL_TREE; parser->scope = NULL_TREE;
parser->qualifying_scope = NULL_TREE; parser->qualifying_scope = NULL_TREE;
parser->object_scope = NULL_TREE;
} }
if (!object_scope_valid_p)
parser->object_scope = NULL_TREE;
return NULL_TREE; return NULL_TREE;
} }
@ -15194,7 +15257,8 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
/* Look for the optional `::' operator. */ /* Look for the optional `::' operator. */
cp_parser_global_scope_opt (parser, cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/false); /*current_scope_valid_p=*/false,
/*object_scope_valid_p=*/false);
/* Look for the nested-name-specifier. */ /* Look for the nested-name-specifier. */
nested_name_p nested_name_p
= (cp_parser_nested_name_specifier_opt (parser, = (cp_parser_nested_name_specifier_opt (parser,
@ -17901,7 +17965,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
/*check_dependency_p=*/true, /*check_dependency_p=*/true,
/*template_p=*/NULL, /*template_p=*/NULL,
/*declarator_p=*/false, /*declarator_p=*/false,
/*optional_p=*/false); /*optional_p=*/false,
/*member_p=*/false);
if (name == error_mark_node) if (name == error_mark_node)
goto skip_comma; goto skip_comma;

View File

@ -9200,6 +9200,14 @@ tsubst_copy_and_build (tree t,
member = tsubst_baselink (member, member = tsubst_baselink (member,
non_reference (TREE_TYPE (object)), non_reference (TREE_TYPE (object)),
args, complain, in_decl); args, complain, in_decl);
else if (TREE_CODE (member) == BIT_NOT_EXPR
&& !TYPE_P (TREE_OPERAND (member, 0)))
{
tree id = TREE_OPERAND (member, 0);
id = make_typename_type (object_type, id, typename_type, complain);
gcc_assert (TREE_CODE (id) != TYPENAME_TYPE);
member = build_nt (BIT_NOT_EXPR, id);
}
else else
member = tsubst_copy (member, args, complain, in_decl); member = tsubst_copy (member, args, complain, in_decl);
if (member == error_mark_node) if (member == error_mark_node)

View File

@ -1,3 +1,8 @@
2006-09-01 Nathan Sidwell <nathan@codesourcery.com>
PR c++/23287
* g++.dg/parse/dtor12.C: New.
2006-08-31 Zdenek Dvorak <dvorakz@suse.cz> 2006-08-31 Zdenek Dvorak <dvorakz@suse.cz>
PR tree-optimization/28839 PR tree-optimization/28839

View File

@ -0,0 +1,15 @@
// Copyright (C) 2006 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 1 Sep 2006 <nathan@codesourcery.com>
// PR 23287: Failure to parse dependent dtor name
// Origin:Wolfgang Bangerth <bangerth@dealii.org>
template <class T> struct A {};
template <class T> void f(A<T> *ptr) {
ptr->~A();
}
template void f<void> (A<void> *);