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/cp/pt.c | |
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/cp/pt.c')
-rw-r--r-- | gcc/cp/pt.c | 36 |
1 files changed, 34 insertions, 2 deletions
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) |