From: Jason Merrill Date: Mon, 26 Sep 2011 03:56:10 +0000 (-0400) Subject: parser.c (inject_this_parameter): Split out from cp_parser_late_return_type_opt. X-Git-Tag: releases/gcc-4.7.0~3580 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=382346e535ff0d18de34888258c948e908646fb6;p=thirdparty%2Fgcc.git parser.c (inject_this_parameter): Split out from cp_parser_late_return_type_opt. * parser.c (inject_this_parameter): Split out from cp_parser_late_return_type_opt. (cp_parser_class_specifier_1): Use it for NSDMIs. * tree.c (bot_replace): Replace NSDMI 'this' with real 'this'. From-SVN: r179179 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8c25746f0cb4..cd309042f876 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2011-09-25 Jason Merrill + + * parser.c (inject_this_parameter): Split out from + cp_parser_late_return_type_opt. + (cp_parser_class_specifier_1): Use it for NSDMIs. + * tree.c (bot_replace): Replace NSDMI 'this' with real 'this'. + 2011-09-24 Jason Merrill * except.c (expr_noexcept_p): Split out from finish_noexcept_expr. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 2dbe86613c4b..9600aa954384 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -15690,6 +15690,31 @@ cp_parser_virt_specifier_seq_opt (cp_parser* parser) return virt_specifiers; } +/* Used by handling of trailing-return-types and NSDMI, in which 'this' + is in scope even though it isn't real. */ + +static void +inject_this_parameter (tree ctype, cp_cv_quals quals) +{ + tree this_parm; + + if (current_class_ptr) + { + /* We don't clear this between NSDMIs. Is it already what we want? */ + tree type = TREE_TYPE (TREE_TYPE (current_class_ptr)); + if (same_type_ignoring_top_level_qualifiers_p (ctype, type) + && cp_type_quals (type) == quals) + return; + } + + this_parm = build_this_parm (ctype, quals); + /* Clear this first to avoid shortcut in cp_build_indirect_ref. */ + current_class_ptr = NULL_TREE; + current_class_ref + = cp_build_indirect_ref (this_parm, RO_NULL, tf_warning_or_error); + current_class_ptr = this_parm; +} + /* Parse a late-specified return type, if any. This is not a separate non-terminal, but part of a function declarator, which looks like @@ -15718,12 +15743,8 @@ cp_parser_late_return_type_opt (cp_parser* parser, cp_cv_quals quals) if (quals >= 0) { /* DR 1207: 'this' is in scope in the trailing return type. */ - tree this_parm = build_this_parm (current_class_type, quals); gcc_assert (current_class_ptr == NULL_TREE); - current_class_ref - = cp_build_indirect_ref (this_parm, RO_NULL, tf_warning_or_error); - /* Set this second to avoid shortcut in cp_build_indirect_ref. */ - current_class_ptr = this_parm; + inject_this_parameter (current_class_type, quals); } type = cp_parser_trailing_type_id (parser); @@ -17274,6 +17295,7 @@ cp_parser_class_specifier_1 (cp_parser* parser) tree pushed_scope = NULL_TREE; unsigned ix; cp_default_arg_entry *e; + tree save_ccp, save_ccr; /* In a first pass, parse default arguments to the functions. Then, in a second pass, parse the bodies of the functions. @@ -17307,6 +17329,8 @@ cp_parser_class_specifier_1 (cp_parser* parser) } VEC_truncate (cp_default_arg_entry, unparsed_funs_with_default_args, 0); /* Now parse any NSDMIs. */ + save_ccp = current_class_ptr; + save_ccr = current_class_ref; FOR_EACH_VEC_ELT (tree, unparsed_nsdmis, ix, decl) { if (class_type != DECL_CONTEXT (decl)) @@ -17316,9 +17340,12 @@ cp_parser_class_specifier_1 (cp_parser* parser) class_type = DECL_CONTEXT (decl); pushed_scope = push_scope (class_type); } + inject_this_parameter (class_type, TYPE_UNQUALIFIED); cp_parser_late_parsing_nsdmi (parser, decl); } VEC_truncate (tree, unparsed_nsdmis, 0); + current_class_ptr = save_ccp; + current_class_ref = save_ccr; if (pushed_scope) pop_scope (pushed_scope); /* Now parse the body of the functions. */ diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index a9e1a26200ee..f23b888f3762 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1926,6 +1926,13 @@ bot_replace (tree* t, if (n) *t = (tree) n->value; } + else if (TREE_CODE (*t) == PARM_DECL + && DECL_NAME (*t) == this_identifier) + { + /* In an NSDMI we need to replace the 'this' parameter we used for + parsing with the real one for this function. */ + *t = current_class_ptr; + } return NULL_TREE; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7bd46ae17b53..1a39c28f03ad 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2011-09-25 Jason Merrill + + * g++.dg/cpp0x/nsdmi-defer4.C: New. + 2011-09-25 Eric Botcazou * gnat.dg/frame_overflow.ads: New. diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer4.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer4.C new file mode 100644 index 000000000000..68c8380eed2a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer4.C @@ -0,0 +1,17 @@ +// { dg-options -std=c++0x } + +struct A +{ + int i = 42; + int j = f(); + int k = this->f(); + int f() { return i++; } +}; + +A a; + +int main() +{ + if (a.j != 42 || a.k != 43 || a.i != 44) + __builtin_abort(); +}