* 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
+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
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.
}
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))
{
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. */
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))
}
}
+ /* Now TYPE has the actual type. */
+
if (returned_attrs)
{
if (attrlist)
attrlist = &returned_attrs;
}
- /* Now TYPE has the actual type. */
-
/* Did array size calculations overflow? */
if (TREE_CODE (type) == ARRAY_TYPE
}
}
+/* 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. */
there were no definition, and vice versa. */
DECL_INITIAL (fn) = NULL_TREE;
duplicate_decls (spec, fn, is_friend);
+ check_specialization_namespace (fn);
return fn;
}
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))
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.
}
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,
return;
}
+ check_explicit_instantiation_namespace (TYPE_NAME (t));
mark_class_instantiated (t, extern_p);
if (nomem_p)
+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
--- /dev/null
+// 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" }
+}
--- /dev/null
+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" }
+}
--- /dev/null
+namespace N {
+ template <typename T>
+ struct S {
+ void f() {}
+ };
+}
+
+namespace K {
+ template <> void N::S<char>::f() {} // { dg-error "namespace|definition" }
+}
+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>
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;
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);
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