aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/parser.c13
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/template/pseudodtor1.C44
-rw-r--r--gcc/testsuite/g++.dg/template/pseudodtor2.C18
5 files changed, 82 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c7946ac..51f219b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
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.
+
PR c++/32260
* rtti.c (enum_tinfo_kind): Fix TK_TYPE_INFO_TYPE comment.
(typeid_ok_p): Use the same alias set for abi::__type_info_pseudo
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 2b73a85..7734cc1 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -4850,8 +4850,10 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
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 (cp_parser *parser,
/* 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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 74c7230..849f07e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2007-11-01 Jakub Jelinek <jakub@redhat.com>
+ PR c++/32384
+ * g++.dg/template/pseudodtor1.C: New test.
+ * g++.dg/template/pseudodtor2.C: New test.
+
PR c++/32260
* g++.dg/rtti/typeid7.C: New test.
diff --git a/gcc/testsuite/g++.dg/template/pseudodtor1.C b/gcc/testsuite/g++.dg/template/pseudodtor1.C
new file mode 100644
index 0000000..cf7c254
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pseudodtor1.C
@@ -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;
diff --git a/gcc/testsuite/g++.dg/template/pseudodtor2.C b/gcc/testsuite/g++.dg/template/pseudodtor2.C
new file mode 100644
index 0000000..796aff0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pseudodtor2.C
@@ -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;