diff options
author | Mark Mitchell <mark@codesourcery.com> | 2005-09-15 16:03:32 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2005-09-15 16:03:32 +0000 |
commit | 9c12301f5b2d91a5b6ccdaf7d323d7ca3a09e041 (patch) | |
tree | afc83bbd1a00cee91c0be29bdd545cafdb20f9d9 /gcc | |
parent | c629e611eb78853f8ccd85173b758cabbdc0e56b (diff) | |
download | gcc-9c12301f5b2d91a5b6ccdaf7d323d7ca3a09e041.zip gcc-9c12301f5b2d91a5b6ccdaf7d323d7ca3a09e041.tar.gz gcc-9c12301f5b2d91a5b6ccdaf7d323d7ca3a09e041.tar.bz2 |
re PR c++/13140 (declaration in global namespace, definition inside named or anon namespace)
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.
From-SVN: r104310
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/cp/decl.c | 55 | ||||
-rw-r--r-- | gcc/cp/pt.c | 36 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/class2.C | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/explicit8.C | 13 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/spec25.C | 10 |
7 files changed, 144 insertions, 7 deletions
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 <mark@codesourcery.com> + + 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 <nathan@codesourcery.com> 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 <typename T> void f(T); + namespace N { + struct S { friend void f<int>(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 <mark@codesourcery.com> + + 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 <jconner@apple.com> 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 <typename T> + struct S { + void f() {} + }; + namespace I { + template void S<double>::f(); // { dg-error "namespace" } + } +} + +namespace K { + template void N::S<int>::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 <typename T> + struct S { + void f() {} + }; +} + +namespace K { + template <> void N::S<char>::f() {} // { dg-error "namespace|definition" } +} |