diff options
author | Jason Merrill <jason@redhat.com> | 2011-05-24 16:26:47 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2011-05-24 16:26:47 -0400 |
commit | 235fe6b4497f0d110914461420ab3c91240988d8 (patch) | |
tree | 9f67e894c2b9a4561659d96cfd45d31db665c22f /gcc | |
parent | 78be79d534fbcf2799c2c4e0b2c768134c9990d4 (diff) | |
download | gcc-235fe6b4497f0d110914461420ab3c91240988d8.zip gcc-235fe6b4497f0d110914461420ab3c91240988d8.tar.gz gcc-235fe6b4497f0d110914461420ab3c91240988d8.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/cp/class.c | 20 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 2 | ||||
-rw-r--r-- | gcc/cp/pt.c | 35 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/access21.C | 23 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/access22.C | 15 |
7 files changed, 104 insertions, 7 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 351b072..c011c83 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2011-05-24 Jason Merrill <jason@redhat.com> + + 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 <paolo.carlini@oracle.com> * decl.c (grokdeclarator): Use current_class_name. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 4e52b18..69627cb 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 3d1c64d..bb6d4b9 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 dbff91e..98844c3 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 beee8a6..95ee33e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-05-24 Jason Merrill <jason@redhat.com> + + * g++.dg/template/access21.C: New. + * g++.dg/template/access22.C: New. + 2011-05-24 Michael Matz <matz@gcc.gnu.org> 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 0000000..8414c43 --- /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 <int I> struct A { }; + +struct Y +{ + template <typename T> + static A<T::I> f(T t) + { + return A<T::I>(); + } +}; + +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 0000000..9ee28a2 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/access22.C @@ -0,0 +1,15 @@ +template <int I> struct B { }; + +template <class T> +B<T::I> f(); + +class A +{ + static const int I = 42; + template <class T> friend B<T::I> f(); +}; + +int main() +{ + f<A>(); +} |