Commit 3df70c62 by Jason Merrill Committed by Jason Merrill

Core 1586

	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
parent 3579964b
2013-04-22 Jason Merrill <jason@redhat.com> 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 * pt.c (fn_type_unification): Push tinst level around
type_unification_real if we aren't explaining. type_unification_real if we aren't explaining.
* cp-tree.h (TFF_NO_TEMPLATE_BINDINGS): New. * cp-tree.h (TFF_NO_TEMPLATE_BINDINGS): New.
......
...@@ -866,6 +866,12 @@ cp_lexer_next_token_is_keyword (cp_lexer* lexer, enum rid keyword) ...@@ -866,6 +866,12 @@ cp_lexer_next_token_is_keyword (cp_lexer* lexer, enum rid keyword)
return cp_lexer_peek_token (lexer)->keyword == 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. */ /* Return true if the next token is not the indicated KEYWORD. */
static inline bool static inline bool
...@@ -1860,7 +1866,7 @@ static vec<tree, va_gc> *cp_parser_parenthesized_expression_list ...@@ -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. */ /* Values for the second parameter of cp_parser_parenthesized_expression_list. */
enum { non_attr = 0, normal_attr = 1, id_attr = 2 }; enum { non_attr = 0, normal_attr = 1, id_attr = 2 };
static void cp_parser_pseudo_destructor_name static void cp_parser_pseudo_destructor_name
(cp_parser *, tree *, tree *); (cp_parser *, tree, tree *, tree *);
static tree cp_parser_unary_expression static tree cp_parser_unary_expression
(cp_parser *, bool, bool, cp_id_kind *); (cp_parser *, bool, bool, cp_id_kind *);
static enum tree_code cp_parser_unary_operator static enum tree_code cp_parser_unary_operator
...@@ -4821,6 +4827,17 @@ cp_parser_unqualified_id (cp_parser* parser, ...@@ -4821,6 +4827,17 @@ cp_parser_unqualified_id (cp_parser* parser,
return build_nt (BIT_NOT_EXPR, scope); 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 /* If there was an explicit qualification (S::~T), first look
in the scope given by the qualification (i.e., S). in the scope given by the qualification (i.e., S).
...@@ -6171,18 +6188,18 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, ...@@ -6171,18 +6188,18 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
cp_parser_parse_tentatively (parser); cp_parser_parse_tentatively (parser);
/* Parse the pseudo-destructor-name. */ /* Parse the pseudo-destructor-name. */
s = NULL_TREE; s = NULL_TREE;
cp_parser_pseudo_destructor_name (parser, &s, &type); cp_parser_pseudo_destructor_name (parser, postfix_expression,
&s, &type);
if (dependent_p if (dependent_p
&& (cp_parser_error_occurred (parser) && (cp_parser_error_occurred (parser)
|| TREE_CODE (type) != TYPE_DECL || !SCALAR_TYPE_P (type)))
|| !SCALAR_TYPE_P (TREE_TYPE (type))))
cp_parser_abort_tentative_parse (parser); cp_parser_abort_tentative_parse (parser);
else if (cp_parser_parse_definitely (parser)) else if (cp_parser_parse_definitely (parser))
{ {
pseudo_destructor_p = true; pseudo_destructor_p = true;
postfix_expression postfix_expression
= finish_pseudo_destructor_expr (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, ...@@ -6443,11 +6460,28 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
static void static void
cp_parser_pseudo_destructor_name (cp_parser* parser, cp_parser_pseudo_destructor_name (cp_parser* parser,
tree object,
tree* scope, tree* scope,
tree* type) tree* type)
{ {
bool nested_name_specifier_p; 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. */ /* Assume that things will not work out. */
*type = error_mark_node; *type = error_mark_node;
...@@ -6515,7 +6549,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser, ...@@ -6515,7 +6549,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
/* Look for the type-name again. We are not responsible for /* Look for the type-name again. We are not responsible for
checking that it matches the first type-name. */ 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. /* Parse a unary-expression.
......
...@@ -2373,6 +2373,8 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor) ...@@ -2373,6 +2373,8 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor)
error ("invalid qualifying scope in pseudo-destructor name"); error ("invalid qualifying scope in pseudo-destructor name");
return error_mark_node; return error_mark_node;
} }
if (is_auto (destructor))
destructor = TREE_TYPE (object);
if (scope && TYPE_P (scope) && !check_dtor_name (scope, destructor)) if (scope && TYPE_P (scope) && !check_dtor_name (scope, destructor))
{ {
error ("qualified type %qT does not match destructor name ~%qT", error ("qualified type %qT does not match destructor name ~%qT",
......
...@@ -2483,7 +2483,9 @@ lookup_destructor (tree object, tree scope, tree dtor_name, ...@@ -2483,7 +2483,9 @@ lookup_destructor (tree object, tree scope, tree dtor_name,
scope, dtor_type); scope, dtor_type);
return error_mark_node; 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 /* In a template, names we can't find a match for are still accepted
destructor names, and we check them here. */ destructor names, and we check them here. */
......
// 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();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment