re PR c++/14389 (Out-of-line of overloaded template rejected)
authorGiovanni Bajo <giovannibajo@gcc.gnu.org>
Mon, 3 May 2004 10:11:19 +0000 (10:11 +0000)
committerGiovanni Bajo <giovannibajo@gcc.gnu.org>
Mon, 3 May 2004 10:11:19 +0000 (10:11 +0000)
PR c++/14389
* decl2.c (check_classfn): For member templates, compare also the
template parameters to match the declaration.
* cp-tree.h: Adjust declaration of check_classfn.
* decl.c (start_decl, grokfndecl): Adjust callers of check_classfn.
* friend.c (do_friend): Likewise.
* pt.c (tsubst_friend_function): Likewise.

PR c++/14389
* g++.dg/template/member5.C: New test.

From-SVN: r81426

gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/friend.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/member5.C [new file with mode: 0644]

index c3c7c868e25f229ccb865e6bf938b93020c70456..37170e2ca71c678ce9cb18c3c837e5624244e13f 100644 (file)
@@ -3721,7 +3721,7 @@ extern void maybe_make_one_only   (tree);
 extern void grokclassfn        (tree, tree, enum overload_flags, tree);
 extern tree grok_array_decl (tree, tree);
 extern tree delete_sanity (tree, tree, bool, int);
-extern tree check_classfn (tree, tree, bool);
+extern tree check_classfn (tree, tree, tree);
 extern void check_member_template (tree);
 extern tree grokfield (tree, tree, tree, tree, tree);
 extern tree grokbitfield (tree, tree, tree);
index 1b788310ca3d00171824c921ede130847efa71dd..17b625f668cd4936dcd95a7557ae4e8c138a1b3f 100644 (file)
@@ -3727,8 +3727,10 @@ start_decl (tree declarator,
       else
        {
          tree field = check_classfn (context, decl,
-                                     processing_template_decl
-                                     > template_class_depth (context));
+                                     (processing_template_decl
+                                      > template_class_depth (context))
+                                     ? current_template_parms
+                                     : NULL_TREE);
          if (field && duplicate_decls (decl, field))
            decl = field;
        }
@@ -5691,8 +5693,10 @@ grokfndecl (tree ctype,
       tree old_decl;
 
       old_decl = check_classfn (ctype, decl,
-                               processing_template_decl
-                               > template_class_depth (ctype));
+                               (processing_template_decl
+                                > template_class_depth (ctype))
+                               ? current_template_parms
+                               : NULL_TREE);
 
       if (old_decl && TREE_CODE (old_decl) == TEMPLATE_DECL)
        /* Because grokfndecl is always supposed to return a
index e094493f988e773749cb92ef481f1b4324b5333e..5730d369efc41ad886d67bcb939c07fabf886fae 100644 (file)
@@ -612,15 +612,19 @@ check_java_method (tree method)
 
 /* Sanity check: report error if this function FUNCTION is not
    really a member of the class (CTYPE) it is supposed to belong to.
-   CNAME is the same here as it is for grokclassfn above.
-   TEMPLATE_HEADER_P is true when this declaration comes with a
-   template header.  */
+   TEMPLATE_PARMS is used to specifiy the template parameters of a member
+   template passed as FUNCTION_DECL. If the member template is passed as a 
+   TEMPLATE_DECL, it can be NULL since the parameters can be extracted
+   from the declaration. If the function is not a function template, it
+   must be NULL.
+   It returns the original declaration for the function, or NULL_TREE
+   if no declaration was found (and an error was emitted).  */
 
 tree
-check_classfn (tree ctype, tree function, bool template_header_p)
+check_classfn (tree ctype, tree function, tree template_parms)
 {
   int ix;
-  int is_template;
+  bool is_template;
   
   if (DECL_USE_TEMPLATE (function)
       && !(TREE_CODE (function) == TEMPLATE_DECL
@@ -638,9 +642,20 @@ check_classfn (tree ctype, tree function, bool template_header_p)
        find the method, but we don't complain.  */
     return NULL_TREE;
 
+  /* Basic sanity check: for a template function, the template parameters
+     either were not passed, or they are the same of DECL_TEMPLATE_PARMS.  */
+  if (TREE_CODE (function) == TEMPLATE_DECL)
+    {
+      my_friendly_assert (!template_parms 
+                         || comp_template_parms 
+                             (template_parms, 
+                              DECL_TEMPLATE_PARMS (function)),
+                         20040303);
+      template_parms = DECL_TEMPLATE_PARMS (function);
+    }
+
   /* OK, is this a definition of a member template?  */
-  is_template = (TREE_CODE (function) == TEMPLATE_DECL
-                || template_header_p);
+  is_template = (template_parms != NULL_TREE);
 
   ix = lookup_fnfields_1 (complete_type (ctype),
                          DECL_CONSTRUCTOR_P (function) ? ctor_identifier :
@@ -684,6 +699,9 @@ check_classfn (tree ctype, tree function, bool template_header_p)
          if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
                           TREE_TYPE (TREE_TYPE (fndecl)))
              && compparms (p1, p2)
+             && (!is_template
+                 || comp_template_parms (template_parms, 
+                                         DECL_TEMPLATE_PARMS (fndecl)))
              && (DECL_TEMPLATE_SPECIALIZATION (function)
                  == DECL_TEMPLATE_SPECIALIZATION (fndecl))
              && (!DECL_TEMPLATE_SPECIALIZATION (function)
index c81bd934e0aad199a8b5c41e765035a7a9a5cda8..e55adaa8bc0cfb7704e789599b60084bf68fe7f3 100644 (file)
@@ -397,7 +397,10 @@ do_friend (tree ctype, tree declarator, tree decl,
               validity of the declaration later.  */
            decl = push_template_decl_real (decl, /*is_friend=*/1);
          else
-           decl = check_classfn (ctype, decl, template_member_p);
+           decl = check_classfn (ctype, decl, 
+                                 template_member_p 
+                                 ? current_template_parms
+                                 : NULL_TREE);
 
          if (template_member_p && decl && TREE_CODE (decl) == FUNCTION_DECL)
            decl = DECL_TI_TEMPLATE (decl);
index 5d2c95ac155f1aac4f94409f613994f76bf159fa..96ee6875a56252ebd5fed49fd85c860daea94312 100644 (file)
@@ -5142,8 +5142,8 @@ tsubst_friend_function (tree decl, tree args)
     {
       /* Check to see that the declaration is really present, and,
         possibly obtain an improved declaration.  */
-      tree fn = check_classfn (DECL_CONTEXT (new_friend),
-                              new_friend, false);
+      tree fn = check_classfn (DECL_CONTEXT (new_friend), 
+                              new_friend, NULL_TREE);
       
       if (fn)
        new_friend = fn;
index 5735a6c55483a2b52ec894ad977a70c4ecc7fc22..df01d26d23e56406e2c9a7a2581722b1cf2fcc49 100644 (file)
@@ -1,6 +1,11 @@
+2004-05-03  Giovanni Bajo  <giovannibajo@gcc.gnu.org>
+
+       PR c++/14389
+       * g++.dg/template/member5.C: New test.
+
 2004-05-03  Uros Bizjak  <uros@kss-loka.si>
 
-        * gcc.dg/builtins-34.c: Also check expm1*.
+       * gcc.dg/builtins-34.c: Also check expm1*.
 
 2004-05-01  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
diff --git a/gcc/testsuite/g++.dg/template/member5.C b/gcc/testsuite/g++.dg/template/member5.C
new file mode 100644 (file)
index 0000000..45dcd6c
--- /dev/null
@@ -0,0 +1,32 @@
+// { dg-do compile }
+// Contributed by: <fasbjx at free dot fr>
+// PR c++/14389: Disambiguate overloaded member templates which differ only
+//  in the template argument list.
+
+namespace N1 {
+
+struct S { 
+    template< typename B, typename A > void foo(); 
+    template< typename A >             void foo(); 
+}; 
+template< typename A >             void S::foo() {} 
+template< typename B, typename A > void S::foo() {} 
+template void S::foo<void> (); 
+template void S::foo<void,void> (); 
+
+}
+
+namespace N2 {
+
+struct S { 
+  template< typename _A > void foo(); 
+  template< int _i >      void foo(); 
+}; 
+
+template< typename _A > void S::foo() {} 
+
+template void S::foo< 0 >();    // { dg-error "no definition available|instantiated from here" }
+
+}