From: Jason Merrill Date: Wed, 29 Jun 2011 21:19:31 +0000 (-0400) Subject: DR 1207 PR c++/49003 X-Git-Tag: releases/gcc-4.7.0~5691 X-Git-Url: https://gcc.gnu.org/git/?a=commitdiff_plain;h=417ae187142e16f8c697d68495614ca07e947636;p=gcc.git DR 1207 PR c++/49003 DR 1207 PR c++/49003 * cp-tree.h (struct saved_scope): Add x_current_class_ptr, x_current_class_ref. (current_class_ptr, current_class_ref): Use them. * decl.c (build_this_parm): Handle getting the class type. * parser.c (cp_parser_late_return_type_opt): Set up 'this' for use within the trailing return type. From-SVN: r175671 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f06c257796f5..c5751bd1a415 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,14 @@ 2011-06-29 Jason Merrill + DR 1207 + PR c++/49003 + * cp-tree.h (struct saved_scope): Add x_current_class_ptr, + x_current_class_ref. + (current_class_ptr, current_class_ref): Use them. + * decl.c (build_this_parm): Handle getting the class type. + * parser.c (cp_parser_late_return_type_opt): Set up 'this' + for use within the trailing return type. + * pt.c (tsubst_decl) [VAR_DECL]: In unevaluated operand, don't tsubst DECL_INITIAL unless our type use auto. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 55c88e384821..ef25c97aafbf 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -953,6 +953,10 @@ struct GTY(()) saved_scope { struct cp_binding_level *x_previous_class_level; tree x_saved_tree; + /* Only used for uses of this in trailing return type. */ + tree x_current_class_ptr; + tree x_current_class_ref; + int x_processing_template_decl; int x_processing_specialization; BOOL_BITFIELD x_processing_explicit_instantiation : 1; @@ -1070,12 +1074,14 @@ struct GTY(()) language_function { PARM_DECL for the `this' pointer. The current_class_ref is an expression for `*this'. */ -#define current_class_ptr \ - (cfun && cp_function_chain \ - ? cp_function_chain->x_current_class_ptr : NULL_TREE) -#define current_class_ref \ - ((cfun && cp_function_chain) \ - ? cp_function_chain->x_current_class_ref : NULL_TREE) +#define current_class_ptr \ + (*(cfun && cp_function_chain \ + ? &cp_function_chain->x_current_class_ptr \ + : &scope_chain->x_current_class_ptr)) +#define current_class_ref \ + (*(cfun && cp_function_chain \ + ? &cp_function_chain->x_current_class_ref \ + : &scope_chain->x_current_class_ref)) /* The EH_SPEC_BLOCK for the exception-specifiers for the current function, if any. */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index b8435a6ddaa2..94d686d3aefc 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -7001,7 +7001,14 @@ build_this_parm (tree type, cp_cv_quals quals) tree parm; cp_cv_quals this_quals; - this_type = type_of_this_parm (type); + if (CLASS_TYPE_P (type)) + { + this_type + = cp_build_qualified_type (type, quals & ~TYPE_QUAL_RESTRICT); + this_type = build_pointer_type (this_type); + } + else + this_type = type_of_this_parm (type); /* The `this' parameter is implicitly `const'; it cannot be assigned to. */ this_quals = (quals & TYPE_QUAL_RESTRICT) | TYPE_QUAL_CONST; @@ -12675,6 +12682,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) cp_function_chain->x_current_class_ref = cp_build_indirect_ref (t, RO_NULL, tf_warning_or_error); + /* Set this second to avoid shortcut in cp_build_indirect_ref. */ cp_function_chain->x_current_class_ptr = t; /* Constructors and destructors need to know whether they're "in diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index f1b79761b8c7..d79326d2808b 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1696,7 +1696,7 @@ static cp_cv_quals cp_parser_cv_qualifier_seq_opt static cp_virt_specifiers cp_parser_virt_specifier_seq_opt (cp_parser *); static tree cp_parser_late_return_type_opt - (cp_parser *); + (cp_parser *, cp_cv_quals); static tree cp_parser_declarator_id (cp_parser *, bool); static tree cp_parser_type_id @@ -14968,7 +14968,7 @@ cp_parser_direct_declarator (cp_parser* parser, virt_specifiers = cp_parser_virt_specifier_seq_opt (parser); late_return - = cp_parser_late_return_type_opt (parser); + = cp_parser_late_return_type_opt (parser, cv_quals); /* Create the function-declarator. */ declarator = make_call_declarator (declarator, @@ -15537,9 +15537,10 @@ cp_parser_virt_specifier_seq_opt (cp_parser* parser) Returns the type indicated by the type-id. */ static tree -cp_parser_late_return_type_opt (cp_parser* parser) +cp_parser_late_return_type_opt (cp_parser* parser, cp_cv_quals quals) { cp_token *token; + tree type; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); @@ -15550,7 +15551,23 @@ cp_parser_late_return_type_opt (cp_parser* parser) /* Consume the ->. */ cp_lexer_consume_token (parser->lexer); - return cp_parser_trailing_type_id (parser); + if (current_class_type) + { + /* 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; + } + + type = cp_parser_trailing_type_id (parser); + + if (current_class_type) + current_class_ptr = current_class_ref = NULL_TREE; + + return type; } /* Parse a declarator-id. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a4ccb073b8f1..da5b817620da 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2011-06-29 Jason Merrill + PR c++/49003 + * g++.dg/cpp0x/trailing6.C: New. + * g++.dg/cpp0x/pr45908.C: No error. + PR c++/49272 * g++.old-deja/g++.jason/rfg10.C: Accept other overflow error too. diff --git a/gcc/testsuite/g++.dg/cpp0x/pr45908.C b/gcc/testsuite/g++.dg/cpp0x/pr45908.C index 3a8508890ee1..45399b5395fb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr45908.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr45908.C @@ -14,5 +14,5 @@ struct vector { class block { vector v; auto end() const -> decltype(v.begin()) - { return v.begin(); } // { dg-error "could not convert" } + { return v.begin(); } }; diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing6.C b/gcc/testsuite/g++.dg/cpp0x/trailing6.C new file mode 100644 index 000000000000..3476e90e5805 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/trailing6.C @@ -0,0 +1,6 @@ +// PR c++/49003 +// { dg-options -std=c++0x } + +struct A { + auto a() const -> decltype(this) { return this; } +};