Core 1586
authorJason Merrill <jason@redhat.com>
Mon, 22 Apr 2013 20:59:02 +0000 (16:59 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 22 Apr 2013 20:59:02 +0000 (16:59 -0400)
Core 1586
* parser.c (cp_parser_unqualified_id): Handle ~auto.
(cp_parser_pseudo_destructor_name): Likewise.
(cp_parser_postfix_dot_deref_expression): Adjust.
(cp_lexer_nth_token_is_keyword): New.
* semantics.c (finish_pseudo_destructor_expr): Handle ~auto.
* typeck.c (lookup_destructor): Handle ~auto.

From-SVN: r198162

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/cp/semantics.c
gcc/cp/typeck.c
gcc/testsuite/g++.dg/cpp1y/auto-dtor1.C [new file with mode: 0644]

index 8b0225b..e41a079 100644 (file)
@@ -1,5 +1,13 @@
 2013-04-22  Jason Merrill  <jason@redhat.com>
 
+       Core 1586
+       * parser.c (cp_parser_unqualified_id): Handle ~auto.
+       (cp_parser_pseudo_destructor_name): Likewise.
+       (cp_parser_postfix_dot_deref_expression): Adjust.
+       (cp_lexer_nth_token_is_keyword): New.
+       * semantics.c (finish_pseudo_destructor_expr): Handle ~auto.
+       * typeck.c (lookup_destructor): Handle ~auto.
+
        * pt.c (fn_type_unification): Push tinst level around
        type_unification_real if we aren't explaining.
        * cp-tree.h (TFF_NO_TEMPLATE_BINDINGS): New.
index 1fbc9bd..0456dd2 100644 (file)
@@ -866,6 +866,12 @@ cp_lexer_next_token_is_keyword (cp_lexer* lexer, enum rid keyword)
   return cp_lexer_peek_token (lexer)->keyword == keyword;
 }
 
+static inline bool
+cp_lexer_nth_token_is_keyword (cp_lexer* lexer, size_t n, enum rid keyword)
+{
+  return cp_lexer_peek_nth_token (lexer, n)->keyword == keyword;
+}
+
 /* Return true if the next token is not the indicated KEYWORD.  */
 
 static inline bool
@@ -1860,7 +1866,7 @@ static vec<tree, va_gc> *cp_parser_parenthesized_expression_list
 /* Values for the second parameter of cp_parser_parenthesized_expression_list.  */
 enum { non_attr = 0, normal_attr = 1, id_attr = 2 };
 static void cp_parser_pseudo_destructor_name
-  (cp_parser *, tree *, tree *);
+  (cp_parser *, tree, tree *, tree *);
 static tree cp_parser_unary_expression
   (cp_parser *, bool, bool, cp_id_kind *);
 static enum tree_code cp_parser_unary_operator
@@ -4821,6 +4827,17 @@ cp_parser_unqualified_id (cp_parser* parser,
            return build_nt (BIT_NOT_EXPR, scope);
          }
 
+       /* ~auto means the destructor of whatever the object is.  */
+       if (cp_parser_is_keyword (token, RID_AUTO))
+         {
+           if (cxx_dialect < cxx1y)
+             pedwarn (input_location, 0,
+                      "%<~auto%> only available with "
+                      "-std=c++1y or -std=gnu++1y");
+           cp_lexer_consume_token (parser->lexer);
+           return build_nt (BIT_NOT_EXPR, make_auto ());
+         }
+
        /* If there was an explicit qualification (S::~T), first look
           in the scope given by the qualification (i.e., S).
 
@@ -6171,18 +6188,18 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
       cp_parser_parse_tentatively (parser);
       /* Parse the pseudo-destructor-name.  */
       s = NULL_TREE;
-      cp_parser_pseudo_destructor_name (parser, &s, &type);
+      cp_parser_pseudo_destructor_name (parser, postfix_expression,
+                                       &s, &type);
       if (dependent_p
          && (cp_parser_error_occurred (parser)
-             || TREE_CODE (type) != TYPE_DECL
-             || !SCALAR_TYPE_P (TREE_TYPE (type))))
+             || !SCALAR_TYPE_P (type)))
        cp_parser_abort_tentative_parse (parser);
       else if (cp_parser_parse_definitely (parser))
        {
          pseudo_destructor_p = true;
          postfix_expression
            = finish_pseudo_destructor_expr (postfix_expression,
-                                            s, TREE_TYPE (type));
+                                            s, type);
        }
     }
 
@@ -6443,11 +6460,28 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
 
 static void
 cp_parser_pseudo_destructor_name (cp_parser* parser,
+                                 tree object,
                                  tree* scope,
                                  tree* type)
 {
   bool nested_name_specifier_p;
 
+  /* Handle ~auto.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_COMPL)
+      && cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_AUTO)
+      && !type_dependent_expression_p (object))
+    {
+      if (cxx_dialect < cxx1y)
+       pedwarn (input_location, 0,
+                "%<~auto%> only available with "
+                "-std=c++1y or -std=gnu++1y");
+      cp_lexer_consume_token (parser->lexer);
+      cp_lexer_consume_token (parser->lexer);
+      *scope = NULL_TREE;
+      *type = TREE_TYPE (object);
+      return;
+    }
+
   /* Assume that things will not work out.  */
   *type = error_mark_node;
 
@@ -6515,7 +6549,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
 
   /* Look for the type-name again.  We are not responsible for
      checking that it matches the first type-name.  */
-  *type = cp_parser_nonclass_name (parser);
+  *type = TREE_TYPE (cp_parser_nonclass_name (parser));
 }
 
 /* Parse a unary-expression.
index 2b8ceb2..d4f0f82 100644 (file)
@@ -2373,6 +2373,8 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor)
          error ("invalid qualifying scope in pseudo-destructor name");
          return error_mark_node;
        }
+      if (is_auto (destructor))
+       destructor = TREE_TYPE (object);
       if (scope && TYPE_P (scope) && !check_dtor_name (scope, destructor))
        {
          error ("qualified type %qT does not match destructor name ~%qT",
index 50405c3..c0696e0 100644 (file)
@@ -2483,7 +2483,9 @@ lookup_destructor (tree object, tree scope, tree dtor_name,
               scope, dtor_type);
       return error_mark_node;
     }
-  if (identifier_p (dtor_type))
+  if (is_auto (dtor_type))
+    dtor_type = object_type;
+  else if (identifier_p (dtor_type))
     {
       /* In a template, names we can't find a match for are still accepted
         destructor names, and we check them here.  */
diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-dtor1.C b/gcc/testsuite/g++.dg/cpp1y/auto-dtor1.C
new file mode 100644 (file)
index 0000000..7105095
--- /dev/null
@@ -0,0 +1,22 @@
+// DR 1586
+// { dg-options "-std=c++1y" }
+// { dg-do run }
+
+template <class T>
+void f (T* p)
+{
+  p->~auto();
+}
+
+int d;
+struct A { ~A() { ++d; } };
+
+int main()
+{
+  f(new int(42));
+  f(new A);
+  if (d != 1)
+    throw;
+
+  (new int)->~auto();
+}