PR c++/13140
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 15 Sep 2005 16:03:32 +0000 (16:03 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 15 Sep 2005 16:03:32 +0000 (16:03 +0000)
* 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

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/class2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/explicit8.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/spec25.C [new file with mode: 0644]
libstdc++-v3/ChangeLog
libstdc++-v3/testsuite/testsuite_character.h

index 7338b07..37588de 100644 (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
index 9907292..e3dbc83 100644 (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
index bcff043..3fe3152 100644 (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)
index c74bd24..fd27b78 100644 (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
diff --git a/gcc/testsuite/g++.dg/parse/class2.C b/gcc/testsuite/g++.dg/parse/class2.C
new file mode 100644 (file)
index 0000000..2014f9b
--- /dev/null
@@ -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 (file)
index 0000000..4b92dbe
--- /dev/null
@@ -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 (file)
index 0000000..3f641fe
--- /dev/null
@@ -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" }
+}
index 6c123bb..9585c6c 100644 (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>
 
index 44c5efd..3d6a3f2 100644 (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