From 235fe6b4497f0d110914461420ab3c91240988d8 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 24 May 2011 16:26:47 -0400 Subject: [PATCH] re PR c++/48884 (decltype's operand doesn't consider friend declaration) PR c++/48884 * class.c (pushclass): Accept NULL argument. (popclass): Deal with popping null class. * pt.c (push_access_scope, pop_access_scope): Use them rather than push_to_top_level/pop_from_top_level. (push_deduction_access_scope, pop_defarg_context): New. (fn_type_unification): Use them. * name-lookup.c (lookup_name_real_1): Check current_class_type. From-SVN: r174139 --- gcc/cp/ChangeLog | 11 ++++++++ gcc/cp/class.c | 20 ++++++++++++-- gcc/cp/name-lookup.c | 2 +- gcc/cp/pt.c | 35 ++++++++++++++++++++++-- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/g++.dg/template/access21.C | 23 ++++++++++++++++ gcc/testsuite/g++.dg/template/access22.C | 15 ++++++++++ 7 files changed, 104 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/access21.C create mode 100644 gcc/testsuite/g++.dg/template/access22.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 351b07260eb..c011c83959d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2011-05-24 Jason Merrill + + PR c++/48884 + * class.c (pushclass): Accept NULL argument. + (popclass): Deal with popping null class. + * pt.c (push_access_scope, pop_access_scope): Use them rather than + push_to_top_level/pop_from_top_level. + (push_deduction_access_scope, pop_defarg_context): New. + (fn_type_unification): Use them. + * name-lookup.c (lookup_name_real_1): Check current_class_type. + 2011-05-24 Paolo Carlini * decl.c (grokdeclarator): Use current_class_name. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 4e52b185488..69627cb6cb5 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -6082,6 +6082,9 @@ restore_class_cache (void) So that we may avoid calls to lookup_name, we cache the _TYPE nodes of local TYPE_DECLs in the TREE_TYPE field of the name. + For use by push_access_scope, we allow TYPE to be null to temporarily + push out of class scope. This does not actually change binding levels. + For multiple inheritance, we perform a two-pass depth-first search of the type lattice. */ @@ -6090,8 +6093,6 @@ pushclass (tree type) { class_stack_node_t csn; - type = TYPE_MAIN_VARIANT (type); - /* Make sure there is enough room for the new entry on the stack. */ if (current_class_depth + 1 >= current_class_stack_size) { @@ -6110,6 +6111,15 @@ pushclass (tree type) csn->hidden = 0; current_class_depth++; + if (type == NULL_TREE) + { + current_class_name = current_class_type = NULL_TREE; + csn->hidden = true; + return; + } + + type = TYPE_MAIN_VARIANT (type); + /* Now set up the new type. */ current_class_name = TYPE_NAME (type); if (TREE_CODE (current_class_name) == TYPE_DECL) @@ -6154,7 +6164,11 @@ invalidate_class_lookup_cache (void) void popclass (void) { - poplevel_class (); + if (current_class_type) + poplevel_class (); + else + gcc_assert (current_class_depth + && current_class_stack[current_class_depth - 1].hidden); current_class_depth--; current_class_name = current_class_stack[current_class_depth].name; diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 3d1c64d85cf..bb6d4b93472 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -4469,7 +4469,7 @@ lookup_name_real_1 (tree name, int prefer_type, int nonclass, bool block_p, /* Conversion operators are handled specially because ordinary unqualified name lookup will not find template conversion operators. */ - if (IDENTIFIER_TYPENAME_P (name)) + if (IDENTIFIER_TYPENAME_P (name) && current_class_type) { struct cp_binding_level *level; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index dbff91e617d..98844c37017 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -212,7 +212,7 @@ push_access_scope (tree t) else if (DECL_CLASS_SCOPE_P (t)) push_nested_class (DECL_CONTEXT (t)); else - push_to_top_level (); + pushclass (NULL_TREE); if (TREE_CODE (t) == FUNCTION_DECL) { @@ -237,7 +237,7 @@ pop_access_scope (tree t) if (DECL_FRIEND_CONTEXT (t) || DECL_CLASS_SCOPE_P (t)) pop_nested_class (); else - pop_from_top_level (); + popclass (); } /* Do any processing required when DECL (a member template @@ -13820,6 +13820,30 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain) return ret; } +/* We're going to do deduction substitution on the type of TMPL, a function + template. In C++11 mode, push into that access scope. In C++03 mode, + disable access checking. */ + +static void +push_deduction_access_scope (tree tmpl) +{ + if (cxx_dialect >= cxx0x) + push_access_scope (DECL_TEMPLATE_RESULT (tmpl)); + else + push_deferring_access_checks (dk_no_check); +} + +/* And pop back out. */ + +static void +pop_deduction_access_scope (tree tmpl) +{ + if (cxx_dialect >= cxx0x) + pop_access_scope (DECL_TEMPLATE_RESULT (tmpl)); + else + pop_deferring_access_checks (); +} + /* The FN is a TEMPLATE_DECL for a function. ARGS is an array with NARGS elements of the arguments that are being used when calling it. TARGS is a vector into which the deduced template arguments @@ -13958,7 +13982,9 @@ fn_type_unification (tree fn, incomplete = NUM_TMPL_ARGS (explicit_targs) != NUM_TMPL_ARGS (targs); processing_template_decl += incomplete; + push_deduction_access_scope (fn); fntype = deduction_tsubst_fntype (fn, converted_args); + pop_deduction_access_scope (fn); processing_template_decl -= incomplete; if (fntype == error_mark_node) @@ -14029,7 +14055,10 @@ fn_type_unification (tree fn, substitution results in an invalid type, as described above, type deduction fails. */ { - tree substed = deduction_tsubst_fntype (fn, targs); + tree substed; + push_deduction_access_scope (fn); + substed = deduction_tsubst_fntype (fn, targs); + pop_deduction_access_scope (fn); if (substed == error_mark_node) return 1; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index beee8a6fbd6..95ee33e39c3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-05-24 Jason Merrill + + * g++.dg/template/access21.C: New. + * g++.dg/template/access22.C: New. + 2011-05-24 Michael Matz PR rtl-optimization/48633 diff --git a/gcc/testsuite/g++.dg/template/access21.C b/gcc/testsuite/g++.dg/template/access21.C new file mode 100644 index 00000000000..8414c4371f4 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/access21.C @@ -0,0 +1,23 @@ +// PR c++/48884 + +class X +{ + static const int I = 42; + friend struct Y; +}; + +template struct A { }; + +struct Y +{ + template + static A f(T t) + { + return A(); + } +}; + +int main() +{ + Y::f(X()); +} diff --git a/gcc/testsuite/g++.dg/template/access22.C b/gcc/testsuite/g++.dg/template/access22.C new file mode 100644 index 00000000000..9ee28a2a08d --- /dev/null +++ b/gcc/testsuite/g++.dg/template/access22.C @@ -0,0 +1,15 @@ +template struct B { }; + +template +B f(); + +class A +{ + static const int I = 42; + template friend B f(); +}; + +int main() +{ + f(); +} -- 2.30.2