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:
parent
c629e611eb
commit
9c12301f5b
@ -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
|
||||
|
@ -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
|
||||
|
36
gcc/cp/pt.c
36
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)
|
||||
|
@ -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
|
||||
|
14
gcc/testsuite/g++.dg/parse/class2.C
Normal file
14
gcc/testsuite/g++.dg/parse/class2.C
Normal 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" }
|
||||
}
|
13
gcc/testsuite/g++.dg/template/explicit8.C
Normal file
13
gcc/testsuite/g++.dg/template/explicit8.C
Normal 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" }
|
||||
}
|
10
gcc/testsuite/g++.dg/template/spec25.C
Normal file
10
gcc/testsuite/g++.dg/template/spec25.C
Normal 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" }
|
||||
}
|
@ -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>
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user