2008-02-13 Jakub Jelinek <jakub@redhat.com> Manuel Lopez-Ibanez <manu@gcc.gnu.org> PR c++/35138 * parser.c (cp_parser_pseudo_destructor_name): If next tokens are not identifier :: ~, return before calling cp_parser_type_name. 2008-02-13 Jakub Jelinek <jakub@redhat.com> PR c++/35138 * g++.dg/template/member8.C: New test. 2007-11-01 Jakub Jelinek <jakub@redhat.com> PR c++/32384 * parser.c (cp_parser_postfix_dot_deref_expression): If POSTFIX_EXPRESSION is type dependent, try to parse it as pseudo dtor first and if that succeeds and type is SCALAR_TYPE_P, create PSEUDO_DTOR_EXPR. * g++.dg/template/pseudodtor1.C: New test. * g++.dg/template/pseudodtor2.C: New test. --- gcc/cp/parser.c (revision 129835) +++ gcc/cp/parser.c (revision 129836) @@ -4850,8 +4850,10 @@ cp_parser_postfix_dot_deref_expression ( pseudo_destructor_p = false; /* If the SCOPE is a scalar type, then, if this is a valid program, - we must be looking at a pseudo-destructor-name. */ - if (scope && SCALAR_TYPE_P (scope)) + we must be looking at a pseudo-destructor-name. If POSTFIX_EXPRESSION + is type dependent, it can be pseudo-destructor-name or something else. + Try to parse it as pseudo-destructor-name first. */ + if ((scope && SCALAR_TYPE_P (scope)) || dependent_p) { tree s; tree type; @@ -4860,7 +4862,12 @@ cp_parser_postfix_dot_deref_expression ( /* Parse the pseudo-destructor-name. */ s = NULL_TREE; cp_parser_pseudo_destructor_name (parser, &s, &type); - if (cp_parser_parse_definitely (parser)) + if (dependent_p + && (cp_parser_error_occurred (parser) + || TREE_CODE (type) != TYPE_DECL + || !SCALAR_TYPE_P (TREE_TYPE (type)))) + cp_parser_abort_tentative_parse (parser); + else if (cp_parser_parse_definitely (parser)) { pseudo_destructor_p = true; postfix_expression @@ -5164,24 +5164,26 @@ cp_parser_pseudo_destructor_name (cp_par additional qualification. */ else if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMPL)) { + /* At this point, we're looking for "type-name :: ~". The type-name + must not be a class-name, since this is a pseudo-destructor. So, + it must be either an enum-name, or a typedef-name -- both of which + are just identifiers. So, we peek ahead to check that the "::" + and "~" tokens are present; if they are not, then we can avoid + calling type_name. */ + if (cp_lexer_peek_token (parser->lexer)->type != CPP_NAME + || cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_SCOPE + || cp_lexer_peek_nth_token (parser->lexer, 3)->type != CPP_COMPL) + { + cp_parser_error (parser, "non-scalar type"); + return; + } + /* Look for the type-name. */ *scope = TREE_TYPE (cp_parser_type_name (parser)); if (*scope == error_mark_node) return; - /* If we don't have ::~, then something has gone wrong. Since - the only caller of this function is looking for something - after `.' or `->' after a scalar type, most likely the - program is trying to get a member of a non-aggregate - type. */ - if (cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE) - || cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_COMPL) - { - cp_parser_error (parser, "request for member of non-aggregate type"); - return; - } - /* Look for the `::' token. */ cp_parser_require (parser, CPP_SCOPE, "`::'"); } --- gcc/testsuite/g++.dg/template/pseudodtor1.C (revision 0) +++ gcc/testsuite/g++.dg/template/pseudodtor1.C (revision 129836) @@ -0,0 +1,44 @@ +// PR c++/32384 +// { dg-do compile } + +struct A +{ + typedef int T; + T foo (); + + A () { foo ().~T (); } +}; + +template<typename> struct B +{ + typedef int T; + T foo (); + + B () { foo ().~T (); } +}; + +template<typename T> struct C +{ + T t; + C () { t.~T (); } +}; + +template<typename S> struct D +{ + typedef int T; + S foo (); + + D () { foo ().~T(); } +}; + +struct Z +{ + Z () {} + ~Z () {} +}; + +A a; +B<int> b; +C<int> c1; +C<Z> c2; +D<int> d; --- gcc/testsuite/g++.dg/template/pseudodtor2.C (revision 0) +++ gcc/testsuite/g++.dg/template/pseudodtor2.C (revision 129836) @@ -0,0 +1,18 @@ +// PR c++/32384 +// { dg-do compile } + +template<typename S> struct D +{ + typedef int T; + S foo (); + + D () { foo ().~T(); } // { dg-error "is not of type" } +}; + +struct Z +{ + Z () {} + ~Z () {} +}; + +D<Z> d; --- gcc/testsuite/g++.dg/template/member8.C (revision 0) +++ gcc/testsuite/g++.dg/template/member8.C (revision 132298) @@ -0,0 +1,25 @@ +// PR c++/35138 +// { dg-do compile } + +namespace N1 { struct A { }; } +namespace N2 { struct A { }; } +using namespace N1; +using namespace N2; + +template <typename T> int +foo (T const &t) +{ + return t.A; +} + +struct B +{ + int A; +}; + +int +main () +{ + B b; + foo (b); +}