From: mmitchel Date: Thu, 15 Sep 2005 16:03:32 +0000 (+0000) Subject: PR c++/13140 X-Git-Tag: upstream/4.9.2~58627 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9ed9d9ecaf4bb520f3f00256fb1b525ad82c19d9;p=platform%2Fupstream%2Flinaro-gcc.git PR c++/13140 * decl.c (check_class_member_definition_namespace): New function. (grokfndecl): Use it. (grokvardecl): Likewise. (grokdecl): Improve documentation. * pt.c (check_explicit_instantiation_namespace): New function. (register_specialization): Call check_specialization_namespace when replacing an implicitly instantiated function. (check_explicit_specialization): Ensure that DECL_CONTEXT is set correctly for namespace-scope specializations. (do_decl_instantiation): Use check_explicit_instantiation_namespace. (do_type_instantiation): Likewise. PR c++/13140 * g++.dg/parse/class2.C: New test. * g++.dg/template/explicit8.C: Likewise. * g++.dg/template/spec25.C: Likewise. * testsuite/testsuite_character.h: Specialize character<> templates in __gnu_cxx, not in __gnu_test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@104310 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7338b07..37588de 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +2005-09-15 Mark Mitchell + + PR c++/13140 + * decl.c (check_class_member_definition_namespace): New function. + (grokfndecl): Use it. + (grokvardecl): Likewise. + (grokdecl): Improve documentation. + * pt.c (check_explicit_instantiation_namespace): New function. + (register_specialization): Call check_specialization_namespace + when replacing an implicitly instantiated function. + (check_explicit_specialization): Ensure that DECL_CONTEXT is set + correctly for namespace-scope specializations. + (do_decl_instantiation): Use + check_explicit_instantiation_namespace. + (do_type_instantiation): Likewise. + 2005-09-15 Nathan Sidwell PR c++/23725 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 9907292..e3dbc83 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5584,6 +5584,41 @@ bad_specifiers (tree object, error ("%q+D declared with an exception specification", object); } +/* DECL is a member function or static data member and is presently + being defined. Check that the definition is taking place in a + valid namespace. */ + +static void +check_class_member_definition_namespace (tree decl) +{ + /* These checks only apply to member functions and static data + members. */ + gcc_assert (TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == VAR_DECL); + /* We check for problems with specializations in pt.c in + check_specialization_namespace, where we can issue better + diagnostics. */ + if (processing_specialization) + return; + /* There are no restrictions on the placement of + explicit instantiations. */ + if (processing_explicit_instantiation) + return; + /* [class.mfct] + + A member function definition that appears outside of the + class definition shall appear in a namespace scope enclosing + the class definition. + + [class.static.data] + + The definition for a static data member shall appear in a + namespace scope enclosing the member's class definition. */ + if (!is_ancestor (current_namespace, DECL_CONTEXT (decl))) + pedwarn ("definition of %qD is not in namespace enclosing %qT", + decl, DECL_CONTEXT (decl)); +} + /* CTYPE is class type, or null if non-class. TYPE is type this FUNCTION_DECL should have, either FUNCTION_TYPE or METHOD_TYPE. @@ -5662,7 +5697,11 @@ grokfndecl (tree ctype, } if (ctype) - DECL_CONTEXT (decl) = ctype; + { + DECL_CONTEXT (decl) = ctype; + if (funcdef_flag) + check_class_member_definition_namespace (decl); + } if (ctype == NULL_TREE && DECL_MAIN_P (decl)) { @@ -5994,6 +6033,7 @@ grokvardecl (tree type, set_linkage_for_static_data_member (decl); /* This function is only called with out-of-class definitions. */ DECL_EXTERNAL (decl) = 0; + check_class_member_definition_namespace (decl); } /* At top level, either `static' or no s.c. makes a definition (perhaps tentative), and absence of `static' makes it public. */ @@ -7483,8 +7523,13 @@ grokdeclarator (const cp_declarator *declarator, unqualified_id = dname; } - /* If DECLARATOR is non-NULL, we know it is a cdk_id declarator; - otherwise, we would not have exited the loop above. */ + /* If TYPE is a FUNCTION_TYPE, but the function name was explicitly + qualified with a class-name, turn it into a METHOD_TYPE, unless + we know that the function is static. We take advantage of this + opportunity to do other processing that pertains to entities + explicitly declared to be class members. Note that if DECLARATOR + is non-NULL, we know it is a cdk_id declarator; otherwise, we + would not have exited the loop above. */ if (declarator && declarator->u.id.qualifying_scope && TYPE_P (declarator->u.id.qualifying_scope)) @@ -7571,6 +7616,8 @@ grokdeclarator (const cp_declarator *declarator, } } + /* Now TYPE has the actual type. */ + if (returned_attrs) { if (attrlist) @@ -7579,8 +7626,6 @@ grokdeclarator (const cp_declarator *declarator, attrlist = &returned_attrs; } - /* Now TYPE has the actual type. */ - /* Did array size calculations overflow? */ if (TREE_CODE (type) == ARRAY_TYPE diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index bcff043..3fe3152 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -672,6 +672,23 @@ check_specialization_namespace (tree tmpl) } } +/* SPEC is an explicit instantiation. Check that it is valid to + perform this explicit instantiation in the current namespace. */ + +static void +check_explicit_instantiation_namespace (tree spec) +{ + tree ns; + + /* DR 275: An explicit instantiation shall appear in an enclosing + namespace of its template. */ + ns = decl_namespace_context (spec); + if (!is_ancestor (current_namespace, ns)) + pedwarn ("explicit instantiation of %qD in namespace %qD " + "(which does not enclose namespace %qD)" + spec, current_namespace, ns); +} + /* The TYPE is being declared. If it is a template type, that means it is a partial specialization. Do appropriate error-checking. */ @@ -1187,6 +1204,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend) there were no definition, and vice versa. */ DECL_INITIAL (fn) = NULL_TREE; duplicate_decls (spec, fn, is_friend); + check_specialization_namespace (fn); return fn; } @@ -2087,7 +2105,6 @@ check_explicit_specialization (tree declarator, template it specializes. */ TREE_PRIVATE (decl) = TREE_PRIVATE (gen_tmpl); TREE_PROTECTED (decl) = TREE_PROTECTED (gen_tmpl); - /* The specialization has the same visibility as the template it specializes. */ if (DECL_VISIBILITY_SPECIFIED (gen_tmpl)) @@ -2095,6 +2112,19 @@ check_explicit_specialization (tree declarator, DECL_VISIBILITY_SPECIFIED (decl) = 1; DECL_VISIBILITY (decl) = DECL_VISIBILITY (gen_tmpl); } + /* If DECL is a friend declaration, declared using an + unqualified name, the namespace associated with DECL may + have been set incorrectly. For example, in: + + template void f(T); + namespace N { + struct S { friend void f(int); } + } + + we will have set the DECL_CONTEXT for the friend + declaration to N, rather than to the global namespace. */ + if (DECL_NAMESPACE_SCOPE_P (decl)) + DECL_CONTEXT (decl) = DECL_CONTEXT (tmpl); if (is_friend && !have_def) /* This is not really a declaration of a specialization. @@ -10998,7 +11028,8 @@ do_decl_instantiation (tree decl, tree storage) } else error ("storage class %qD applied to template instantiation", storage); - + + check_explicit_instantiation_namespace (result); mark_decl_instantiated (result, extern_p); if (! extern_p) instantiate_decl (result, /*defer_ok=*/1, @@ -11130,6 +11161,7 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain) return; } + check_explicit_instantiation_namespace (TYPE_NAME (t)); mark_class_instantiated (t, extern_p); if (nomem_p) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c74bd24..fd27b78 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2005-09-15 Mark Mitchell + + PR c++/13140 + * g++.dg/parse/class2.C: New test. + * g++.dg/template/explicit8.C: Likewise. + * g++.dg/template/spec25.C: Likewise. + 2005-09-14 Josh Conner PR middle-end/23584 diff --git a/gcc/testsuite/g++.dg/parse/class2.C b/gcc/testsuite/g++.dg/parse/class2.C new file mode 100644 index 0000000..2014f9b --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/class2.C @@ -0,0 +1,14 @@ +// PR c++/13140 + +struct foo { + foo(); + void f(); + static int i; +}; + + +namespace bar { + foo::foo() {} // { dg-error "namespace" } + void foo::f() {} // { dg-error "namespace" } + int foo::i; // { dg-error "namespace" } +} diff --git a/gcc/testsuite/g++.dg/template/explicit8.C b/gcc/testsuite/g++.dg/template/explicit8.C new file mode 100644 index 0000000..4b92dbe --- /dev/null +++ b/gcc/testsuite/g++.dg/template/explicit8.C @@ -0,0 +1,13 @@ +namespace N { + template + struct S { + void f() {} + }; + namespace I { + template void S::f(); // { dg-error "namespace" } + } +} + +namespace K { + template void N::S::f(); // { dg-error "namespace" } +} diff --git a/gcc/testsuite/g++.dg/template/spec25.C b/gcc/testsuite/g++.dg/template/spec25.C new file mode 100644 index 0000000..3f641fe --- /dev/null +++ b/gcc/testsuite/g++.dg/template/spec25.C @@ -0,0 +1,10 @@ +namespace N { + template + struct S { + void f() {} + }; +} + +namespace K { + template <> void N::S::f() {} // { dg-error "namespace|definition" } +} diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 6c123bb..9585c6c 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,8 @@ +2005-09-15 Mark Mitchell + + * testsuite/testsuite_character.h: Specialize character<> + templates in __gnu_cxx, not in __gnu_test. + 2005-09-13 Jonathan Wakely Benjamin Kosnik diff --git a/libstdc++-v3/testsuite/testsuite_character.h b/libstdc++-v3/testsuite/testsuite_character.h index 44c5efd..3d6a3f2 100644 --- a/libstdc++-v3/testsuite/testsuite_character.h +++ b/libstdc++-v3/testsuite/testsuite_character.h @@ -72,13 +72,15 @@ namespace __gnu_test typedef character pod_uchar; typedef character pod_ushort; typedef character pod_uint; +} +namespace __gnu_cxx { // Specializations. // pod_char template<> template - inline pod_char::char_type - pod_char::char_type::from(const V2& v) + inline __gnu_test::pod_char::char_type + __gnu_test::pod_char::char_type::from(const V2& v) { char_type ret = { static_cast(v.value) }; return ret; @@ -87,17 +89,16 @@ namespace __gnu_test template<> template inline V2 - pod_char::char_type::to(const char_type& c) + __gnu_test::pod_char::char_type::to(const char_type& c) { V2 ret = { c.value }; return ret; } - // pod_uchar template<> template - inline pod_uchar::char_type - pod_uchar::char_type::from(const V2& v) + inline __gnu_test::pod_uchar::char_type + __gnu_test::pod_uchar::char_type::from(const V2& v) { char_type ret; ret.value = (v >> 5); @@ -107,7 +108,7 @@ namespace __gnu_test template<> template inline V2 - pod_uchar::char_type::to(const char_type& c) + __gnu_test::pod_uchar::char_type::to(const char_type& c) { return static_cast(c.value << 5); } }; // namespace __gnu_test