diff options
author | Jason Merrill <jason@redhat.com> | 2011-09-25 23:56:10 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2011-09-25 23:56:10 -0400 |
commit | 382346e535ff0d18de34888258c948e908646fb6 (patch) | |
tree | 5dc91fef74bce55e6b16b338d7748374662af4fa /gcc | |
parent | 02aaf894b5992f67cd6cc9fd9a6364ab7cbef2ab (diff) | |
download | gcc-382346e535ff0d18de34888258c948e908646fb6.zip gcc-382346e535ff0d18de34888258c948e908646fb6.tar.gz gcc-382346e535ff0d18de34888258c948e908646fb6.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/parser.c | 37 | ||||
-rw-r--r-- | gcc/cp/tree.c | 7 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/nsdmi-defer4.C | 17 |
5 files changed, 67 insertions, 5 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8c25746..cd30904 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2011-09-25 Jason Merrill <jason@redhat.com> + + * 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 <jason@redhat.com> * except.c (expr_noexcept_p): Split out from finish_noexcept_expr. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 2dbe866..9600aa9 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 a9e1a26..f23b888 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 7bd46ae..1a39c28 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2011-09-25 Jason Merrill <jason@redhat.com> + + * g++.dg/cpp0x/nsdmi-defer4.C: New. + 2011-09-25 Eric Botcazou <ebotcazou@adacore.com> * 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 0000000..68c8380 --- /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(); +} |