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
This commit is contained in:
Mark Mitchell 2005-09-15 16:03:32 +00:00 committed by Mark Mitchell
parent c629e611eb
commit 9c12301f5b
9 changed files with 157 additions and 14 deletions

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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" }
}

View File

@ -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" }
}

View File

@ -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" }
}

View File

@ -1,3 +1,8 @@
2005-09-15 Mark Mitchell <mark@codesourcery.com>
* testsuite/testsuite_character.h: Specialize character<>
templates in __gnu_cxx, not in __gnu_test.
2005-09-13 Jonathan Wakely <cow@compsoc.man.ac.uk>
Benjamin Kosnik <bkoz@redhat.com>

View File

@ -72,13 +72,15 @@ namespace __gnu_test
typedef character<unsigned char, unsigned int, pod_state> pod_uchar;
typedef character<unsigned short, unsigned int> pod_ushort;
typedef character<unsigned int, unsigned long> pod_uint;
}
namespace __gnu_cxx {
// Specializations.
// pod_char
template<>
template<typename V2>
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<value_type>(v.value) };
return ret;
@ -87,17 +89,16 @@ namespace __gnu_test
template<>
template<typename V2>
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<typename V2>
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<typename V2>
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<V2>(c.value << 5); }
}; // namespace __gnu_test