aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2013-04-22 16:59:02 -0400
committerJason Merrill <jason@gcc.gnu.org>2013-04-22 16:59:02 -0400
commit3df70c625ab2c90d70b65ae7e88acff6c45e507b (patch)
treea7ee80a1d1e803b9195fad27f8abc76c6a7fab2c /gcc/cp
parent3579964bee6f4b621322d367de1fa6ce4b36befc (diff)
downloadgcc-3df70c625ab2c90d70b65ae7e88acff6c45e507b.zip
gcc-3df70c625ab2c90d70b65ae7e88acff6c45e507b.tar.gz
gcc-3df70c625ab2c90d70b65ae7e88acff6c45e507b.tar.bz2
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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/parser.c46
-rw-r--r--gcc/cp/semantics.c2
-rw-r--r--gcc/cp/typeck.c4
4 files changed, 53 insertions, 7 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8b0225b..e41a079 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 1fbc9bd..0456dd2 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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.
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 2b8ceb2..d4f0f82 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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",
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 50405c3..c0696e0 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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. */