Bug 17413 - [3.4 regression] local classes as template argument
Summary: [3.4 regression] local classes as template argument
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.4.2
: P3 normal
Target Milestone: 3.4.5
Assignee: Mark Mitchell
URL:
Keywords: accepts-invalid, diagnostic
Depends on:
Blocks:
 
Reported: 2004-09-11 04:32 UTC by Gabriel Dos Reis
Modified: 2005-07-28 10:24 UTC (History)
3 users (show)

See Also:
Host: platform independent
Target:
Build:
Known to work: 3.3.4 4.0.0
Known to fail: 3.4.2
Last reconfirmed: 2005-05-05 05:43:29


Attachments
smime.p7s (1.64 KB, application/pkcs7-signature)
2005-05-29 09:37 UTC, INCORRECT EMAIL ADDRESS!
Details
smime.p7s (1.63 KB, application/pkcs7-signature)
2005-05-30 15:48 UTC, Geoff Keating
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Gabriel Dos Reis 2004-09-11 04:32:57 UTC
Consider the following code

#include <algorithm>

int main()
{
   int a[10] = {0} ;

   struct T {
      void operator()(int) const { }
   };

   std::for_each(a, a + 10, T());
}

GCC-3.3.x used to say:

t.C: In function `int main()':
t.C:11: error: type `main()::T' composed from a local class is not a valid
   template-argument
t.C:11: error:   trying to instantiate `template<class _InputIter, class
   _Function> _Function std::for_each(_InputIter, _InputIter, _Function)'
t.C:11: error: no matching function for call to `for_each(int[10], int*,
   main()::T)'


Now, GCC-3.4.x says:

t.C: In function `int main()':
t.C:11: error: no matching function for call to `for_each(int[10], int*, main()\
::T)'


Notice that the most informative part of the diagnostic had been dropped,
leaving only the most cryptic, uninformative one.
Comment 1 Wolfgang Bangerth 2004-09-12 22:54:42 UTC
This is related to the substitution-failure-is-not-an-error thingy: we 
realize that a local class cannot be matched against a template argument, 
so we drop the template function std::for_each from the overload list -- 
and end up with an empty list, thus the error message. 
 
We probably need to special-case the overload resolution process to handle 
this case: when we end up with an empty overload list but there is a 
function that would match were it not for a local class, we should report 
so. Whether this kind of special-casing is desirable is another matter. 
 
Reduced testcase is this: 
------------------- 
template <typename T> void foo() {}; 
 
int main () { 
  struct S {}; 
  foo<S> (); 
} 
----------------- 
g/x> /home/bangerth/bin/gcc-3.3.4-pre/bin/c++ -c x.cc 
x.cc: In function `int main()': 
x.cc:5: error: template-argument `main()::S' uses local type `main()::S' 
x.cc:5: error: no matching function for call to `foo()' 
g/x>  
g/x> /home/bangerth/bin/gcc-3.4-pre/bin/c++ -c x.cc 
x.cc: In function `int main()': 
x.cc:5: error: no matching function for call to `foo()' 
g/x>  
g/x> /home/bangerth/bin/gcc-3.5-pre/bin/c++ -c x.cc 
x.cc: In function `int main()': 
x.cc:5: error: no matching function for call to `foo()' 
 
W. 
Comment 2 Gabriel Dos Reis 2004-09-12 23:15:28 UTC
Subject: Re:  [3.4/4.0 regression] local classes as template argument

"bangerth at dealii dot org" <gcc-bugzilla@gcc.gnu.org> writes:

| This is related to the substitution-failure-is-not-an-error thingy: we 
| realize that a local class cannot be matched against a template argument, 
| so we drop the template function std::for_each from the overload list -- 
| and end up with an empty list, thus the error message. 

Indeed, the whole problem is in pt.c:check_instantiated_args().  It
contains code for proper diagnostic

          tree nt = no_linkage_check (t, /*relaxed_p=*/false);

          if (nt)
            {
              if (!(complain & tf_error))
                /*OK*/;
              else if (TYPE_ANONYMOUS_P (nt))
                error ("`%T' uses anonymous type", t);
              else
                error ("`%T' uses local type `%T'", t, nt);
              result = true;
            }

But the diagnostic is not emitted because tf_error is not set in
complain. 

| We probably need to special-case the overload resolution process to handle 
| this case: when we end up with an empty overload list but there is a 
| function that would match were it not for a local class, we should report 
| so. Whether this kind of special-casing is desirable is another matter. 

I would say it is a Suboptimal implementation of SFINAE. 
In the phase where the overload-set is constructed, indeed SFINAE
is applied -- if something is invalid, just bail out without spitting
any diagnostic.  However, once the overload-set is constructed, any
error is an error.

Notice that Comeau online really does give an informative diagnostic

   "ComeauTest.c", line 11: error: a template argument may not reference
   a local type
        std::for_each(a, a + 10, T());
        ^


-- Gaby
Comment 3 Wolfgang Bangerth 2004-09-12 23:31:30 UTC
I agree that an error would be nice. I just meant to point out the reason 
why we don't get one. 
W. 
Comment 4 Gabriel Dos Reis 2004-09-12 23:51:53 UTC
Subject: Re:  [3.4/4.0 regression] local classes as template argument

"bangerth at dealii dot org" <gcc-bugzilla@gcc.gnu.org> writes:

| I agree that an error would be nice. I just meant to point out the reason 
| why we don't get one. 

I did not mean to say you're wrong.  
I'm sorry if my rant gave you the impression that I was saying you're
wrong. 
GCC is giving me headaches these days :-/

-- Gaby
Comment 5 Mark Mitchell 2004-09-14 00:47:25 UTC
Will not be fixed in GCC 3.4.x; postponed until GCC 4.0, at least.
Comment 6 Mark Mitchell 2004-10-12 06:46:33 UTC
The bug here is that we are checking complain at all.

SFINAE does not say that when given a set of overload candidates you perform
type deduction and then discard any candiates for which an any error occurs. 
Instead, you perform type deduction and discard any candidates for which type
deduction fails, which is a defined term in [temp.deduct].  Type deduction fails
only under precise circumstances; using a local class as a template argument is
not a case in which type deduction fails.

It looks like people have been throwing around "complain & tf_error" checks too
freely in pt.c.

The question is then what happens after type deduction succeeds.  Should we emit
an error before doing overload resolution, or only if the invalid function is
selected from the overload set?  DR 415 is a related issue and the proposed
resolution suggests that errors about invalid substitutions may be issued before
overload resolution.
Comment 7 gdr@cs.tamu.edu 2004-10-12 09:55:04 UTC
Subject: Re:  [3.4/4.0 regression] local classes as template argument

"mmitchel at gcc dot gnu dot org" <gcc-bugzilla@gcc.gnu.org> writes:

| The bug here is that we are checking complain at all.
| 
| SFINAE does not say that when given a set of overload candidates you perform
| type deduction and then discard any candiates for which an any error occurs. 
| Instead, you perform type deduction and discard any candidates for which type
| deduction fails, which is a defined term in [temp.deduct].  Type
| deduction fails only under precise circumstances; using a local
| class as a template argument is not a case in which type deduction fails.

Absolutely.

| It looks like people have been throwing around "complain & tf_error"
| checks too freely in pt.c.

Amen.

| The question is then what happens after type deduction succeeds.
| Should we emit an error before doing overload resolution, or only if
| the invalid function is selected from the overload set?  DR 415 is a
| related issue and the proposed resolution suggests that errors about
| invalid substitutions may be issued before overload resolution.

My inclination is to emit the error only if the invalid function is
selected from the overload set.  I can see where DR 415 is heading,
and I think its general concern will no doubt be discussed in Redmond
or following as it affects large part of C++ evolution.

In the mean time, I would recommend we emit the error only if the
invalid function is selected.

-- Gaby
Comment 8 Mark Mitchell 2004-10-12 16:13:24 UTC
As in the discussion of DR 415, it's not feasible to postpone all error messages
until overload resolution has succeeded.  The example in DR 415 is that you
might need to instantiate a class type to do type deduction.  If the class has
an invalid member upon instantiation, it makes sense to complain then, not later
when the function that required that instantiation is selected.

The language (which John Spicer is trying to clarify) leads to another
complication.  [temp.over] says:

  template  argument  deduction  (_temp.deduct_)
  and  checking of any explicit template arguments (_temp.arg_) are per-
  formed for each function template to find the template argument values
  (if any) that can be used with that function template to instantiate a
  function template specialization that can be  invoked  with  the  call
  arguments.   For each function template, if the argument deduction and
  checking succeeds, the template-arguments  (deduced  and/or  explicit)
  are  used  to  instantiate  a  single function template specialization
  which is added to the candidate functions set to be used  in  overload
  resolution.   If,  for  a  given function template, argument deduction
  fails, no such function is added to the set of candidate functions for
  that  template.

This section does not clearly specify what happens if argument deduction
succeeds, but the checking of explict template arguments (as per [temp.arg]) fails.

Consider:

  template <typename T>
  void f(T *);

  void g() {
    struct S;
    S* p;
    f (p);     // #1
    f<S> (p);  // #2
  }

If we treated deduction and explicit arguments differently, then we would put
the template in the overload set at #1 (deduction succeeds) but not at #2
(checking of explicit arguments fails).  That's odd.

John (and I) think that "instantiate" is the wrong term in the passage quoted
above, in the sense that this should not be a point-of-instantiation, I do
think, however, that the compiler must generate a declaration of the function
template, after instantiation, for use during overload resolution.  That is the
natural time to issue errors about the function.  Otherwise, you must queue a
possibly arbitrary error or set of errors to issue later, iff the template is
instantiated.  It's not reasonable to ask that of the implementation.

For all these reasons, I intend to fix this by issuing an error message before
overload resolution.
Comment 9 gdr@cs.tamu.edu 2004-10-12 18:51:23 UTC
Subject: Re:  [3.4/4.0 regression] local classes as template argument

"mmitchel at gcc dot gnu dot org" <gcc-bugzilla@gcc.gnu.org> writes:

[...]

| Consider:
| 
|   template <typename T>
|   void f(T *);
| 
|   void g() {
|     struct S;
|     S* p;
|     f (p);     // #1
|     f<S> (p);  // #2
|   }
| 
| If we treated deduction and explicit arguments differently, then we would put
| the template in the overload set at #1 (deduction succeeds) but not at #2
| (checking of explicit arguments fails).  That's odd.

The difference between deduction and explicit arguments are already
deep; there is no thing odd about it.  They are just not the same
thing and they don't work the same way.
Explicit arguments in general constructs different overload sets
than deduction.  Furthermore, the former allows implicit conversion
and the later does not.  Consider

    template<class>  struct X { }
    template<class T> f(T*);
    template<class T> f(X<T>*);

     void g() {
        struct S : X<int> { };
        S* p;
        f(p);
        f<S>(p);
        f<int>(p);
     };

| John (and I) think that "instantiate" is the wrong term in the passage quoted
| above, in the sense that this should not be a point-of-instantiation, I do
| think, however, that the compiler must generate a declaration of the function
| template, after instantiation, for use during overload resolution.  That is the
| natural time to issue errors about the function.  Otherwise, you must queue a
| possibly arbitrary error or set of errors to issue later, iff the template is
| instantiated.  It's not reasonable to ask that of the implementation.
| 
| For all these reasons, I intend to fix this by issuing an error message before
| overload resolution.

I understand your point of view, but I don't think I agree with it.

I suppose we'll have plenty time to review this point in Redmond or
later.

-- Gaby
Comment 10 GCC Commits 2004-12-22 03:35:10 UTC
Subject: Bug 17413

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	mmitchel@gcc.gnu.org	2004-12-22 03:34:59

Modified files:
	gcc/cp         : ChangeLog call.c decl.c parser.c tree.c 
	gcc/testsuite  : ChangeLog 
Added files:
	gcc/testsuite/g++.dg/ext: packed8.C 
	gcc/testsuite/g++.dg/template: crash31.C crash30.C 

Log message:
	PR c++/18378
	* call.c (convert_like_real): Do not permit the use of a copy
	constructor to copy a packed field.
	
	PR c++/17413
	* decl.c (grokdeclarator): Return error_mark_node, not
	void_type_node, to indicate errors.
	* parser.c (cp_parser_template_parameter_list): Robustify.
	(cp_parser_template_parameter): Likewise.
	
	PR c++/19034
	* tree.c (cp_tree_equal): Handle OVERLOAD.
	
	PR c++/18378
	* g++.dg/ext/packed8.C: New test.
	
	PR c++/13268
	* g++.dg/template/crash31.C: New test.
	
	PR c++/19034
	* g++.dg/template/crash30.C: New test.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.4550&r2=1.4551
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/call.c.diff?cvsroot=gcc&r1=1.523&r2=1.524
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/decl.c.diff?cvsroot=gcc&r1=1.1345&r2=1.1346
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/parser.c.diff?cvsroot=gcc&r1=1.296&r2=1.297
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/tree.c.diff?cvsroot=gcc&r1=1.420&r2=1.421
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/ext/packed8.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/crash31.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/crash30.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.4796&r2=1.4797

Comment 11 Mark Mitchell 2004-12-23 18:25:24 UTC
The patch is the previous comment does not actually apply to this PR.
Comment 12 Mark Mitchell 2004-12-23 19:50:04 UTC
The code in the PR is clearly invalid, as it explicitly uses a local class as an
explicit template arugment.  However, the broader question is how to perform
overload resolution when argument deduction has deduced a local class as a
template argument.

The pluasible choices are one of (a) that function being excluded from the set
of overloaded function candidates, (b) an error when deduction is being
performed, or (c) an error only if that function is selected.

GCC presently implements (a), but that means that the set of overloaded
candidates considered changes depending merely on whether or not one of the
function arguments happens to be a local class.  That seems undesirable. 
Furthermore, it's a clear violation of the standard, which lists clearly the
cases in which SFINAE applies; using a local class as an argument is not one of
them.

Here is a test case that distinguishes (a) from the other other choices:

  struct A {};
  A* a;

  void f(A*);
  template <typename T>
  void f(T*);

  void g() {
    f(a); // Calls the non-template function.                                   

    struct B : public A {};
    B* b = 0;

    f(b); // Overload resolution will select f<B*>(B*) if the template          
          // candidate is included in the overload set.  As a local type        
          // cannot be a template argument, that will result in an error        
          // message.  If the template candidate is not included in the         
          // overload set, then the non-template function will be               
          // accepted.                                                          
  }

G++ presently accepts this code.

The previous debate has centered on whether (b) or (c) is a better choice. 
However, I do not think there is an actual difference between (b) or (c).  If
template argument deduction succeeds, overload resolution is guaranteed to find
that function to be a viable function.  So, the only question is whether it will
be the best.  It will be better than any non-template function, because
non-template functions cannot possibly involve local classes as argument types.
 And any template function which was more specialized would also have to involve
the local class in its argument types.  For example, I do not think there is any
other overload of "f" that can be added above that would be selected over the
template version, but which would not also involve a local class type.
Comment 13 GCC Commits 2004-12-23 19:54:16 UTC
Subject: Bug 17413

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	mmitchel@gcc.gnu.org	2004-12-23 19:54:09

Modified files:
	gcc/testsuite  : ChangeLog 
	gcc/cp         : ChangeLog pt.c 
	gcc/testsuite/g++.dg/template: crash19.C 
Added files:
	gcc/testsuite/g++.dg/template: local4.C 

Log message:
	PR c++/17413
	* pt.c (check_instantiated_args): Remove bogus SFINAE code.
	
	PR c++/17413
	* g++.dg/template/local4.C: New test.
	* g++.dg/template/crash19.C: Add dg-error marker.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.4808&r2=1.4809
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.4557&r2=1.4558
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/pt.c.diff?cvsroot=gcc&r1=1.961&r2=1.962
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/local4.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/crash19.C.diff?cvsroot=gcc&r1=1.2&r2=1.3

Comment 14 Mark Mitchell 2004-12-23 20:00:47 UTC
Fixed in G++ 4.0.
Comment 15 Gabriel Dos Reis 2004-12-23 20:30:50 UTC
Subject: Re:  [3.4/4.0 regression] local classes as template argument


I agree with your analysis.  Thanks for the time you put into this.
I record it for future references in EWG.

-- Gaby
 
Comment 16 GCC Commits 2005-02-02 21:59:21 UTC
Subject: Bug 17413

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	reichelt@gcc.gnu.org	2005-02-02 21:58:46

Modified files:
	gcc/cp         : ChangeLog pt.c 
	gcc/testsuite  : ChangeLog 
	gcc/testsuite/g++.dg/template: local4.C 

Log message:
	PR c++/17413
	* pt.c (check_instantiated_args): Improve error message.
	Fix logic when to print its second part.
	
	PR c++/17413
	* g++.dg/template/local4.C: Tweak.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.4612&r2=1.4613
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/pt.c.diff?cvsroot=gcc&r1=1.971&r2=1.972
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.4984&r2=1.4985
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/local4.C.diff?cvsroot=gcc&r1=1.1&r2=1.2

Comment 17 INCORRECT EMAIL ADDRESS! 2005-05-29 09:37:21 UTC
Subject:  [3.4 regression] local classes as template argument

Hi Mark,

Consider this code:

struct Attribute { };
template <class T> void fun (const Attribute &attr, const T &value);
extern void fun (int attr, int value);
enum { anon = 666 };

void test(int foo)
{ fun (foo, anon); }

I believe this is valid C++.  Template argument deduction will fail  
when it compares the type of the *first* parameter of fun(), since no  
value of T can be found that will make the first parameter match.

Unfortunately, this code produces an error:

/Users/geoffk/Desktop/test.cpp:8: error: '<anonymous enum>' is/uses  
anonymous type
/Users/geoffk/Desktop/test.cpp:8: error:   trying to instantiate  
'template<class T> void fun(const Attribute&, const T&)'

I think the problem is this code in type_unification_real:

           if (strict == DEDUCE_EXACT)
             {
               if (same_type_p (parm, type))
                 continue;
             }
           else
             /* It might work; we shouldn't check now, because we might
                get into infinite recursion.  Overload resolution will
                handle it.  */
             continue;

I will see what happens if I just try to say '== DEDUCE_EXACT ||  
strict == DEDUCE_CALL'.  I'm not hopeful, though...

Comment 18 INCORRECT EMAIL ADDRESS! 2005-05-29 09:37:23 UTC
Created attachment 8986 [details]
smime.p7s
Comment 19 Mark Mitchell 2005-05-29 17:18:29 UTC
Subject: Re:  [3.4 regression] local classes as template argument

Geoffrey Keating wrote:
> Hi Mark,
> 
> Consider this code:
> 
> struct Attribute { };
> template <class T> void fun (const Attribute &attr, const T &value);
> extern void fun (int attr, int value);
> enum { anon = 666 };
> 
> void test(int foo)
> { fun (foo, anon); }
> 
> I believe this is valid C++.  Template argument deduction will fail  
> when it compares the type of the *first* parameter of fun(), since no  
> value of T can be found that will make the first parameter match.

As you've discovered, we don't perform template argument deduction on 
arguments that do not involve template types.  I agree that there's 
nothing in the standard to support that behavior.  However, there are a 
lot of DRs in this area, and we should check the behavior of other 
compilers before making any changes here.  Those checks should be done 
without using anonymous enums, since there's additional controversy 
around that particular issue; instead, some way to isolate what set of 
template functions can be deduced is required.

I don't remember the origin of the comment in the code that refers to 
infinite recursion.  I don't think adding DEDUCE_CALL to the condition 
makes sense, though; either we should always do the comparsion, or only 
when DEDUCE_EXACT.  Furthermore, your change is not correct, in that 
deduction permits non-exact matches for calls; see [temp.deduct.call].

Comment 20 Geoff Keating 2005-05-30 15:48:43 UTC
Subject: Re:  [3.4 regression] local classes as template argument


On 29/05/2005, at 10:18 AM, mark at codesourcery dot com wrote:

>
> ------- Additional Comments From mark at codesourcery dot com   
> 2005-05-29 17:18 -------
> Subject: Re:  [3.4 regression] local classes as template argument
>
> Geoffrey Keating wrote:
>
>> Hi Mark,
>>
>> Consider this code:
>>
>> struct Attribute { };
>> template <class T> void fun (const Attribute &attr, const T &value);
>> extern void fun (int attr, int value);
>> enum { anon = 666 };
>>
>> void test(int foo)
>> { fun (foo, anon); }
>>
>> I believe this is valid C++.  Template argument deduction will fail
>> when it compares the type of the *first* parameter of fun(), since no
>> value of T can be found that will make the first parameter match.
>>
>
> As you've discovered, we don't perform template argument deduction on
> arguments that do not involve template types.  I agree that there's
> nothing in the standard to support that behavior.  However, there  
> are a
> lot of DRs in this area, and we should check the behavior of other
> compilers before making any changes here.  Those checks should be done
> without using anonymous enums, since there's additional controversy
> around that particular issue; instead, some way to isolate what set of
> template functions can be deduced is required.

I don't think there's any way to separate this from anonymous enums.   
The only reason we can tell that template argument deduction is being  
performed is because of the interpretation we've chosen for when  
error messages are emitted with anonymous enums.  If there was no  
error message being emitted, it wouldn't matter; even if a template  
function was added to the list of candidates, it would be considered  
non-viable by function overloading.

I do think that this code ought to be valid C++.  The original  
example had 'fun' actually being 'operator =='; it seems unreasonable  
that if someone defines a template 'operator ==' you suddenly can't  
compare integers and anonymous enumeration constants any more.

> I don't remember the origin of the comment in the code that refers to
> infinite recursion.  I don't think adding DEDUCE_CALL to the condition
> makes sense, though; either we should always do the comparsion, or  
> only
> when DEDUCE_EXACT.  Furthermore, your change is not correct, in that
> deduction permits non-exact matches for calls; see [temp.deduct.call].

Yes, I noticed that pretty quickly; the patch I'm testing now looks  
like:

--- pt.c        27 May 2005 23:17:17 -0000      1.1000
+++ pt.c        29 May 2005 21:17:18 -0000
@@ -9344,17 +9344,12 @@ type_unification_real (tree tparms,
           else
             type = arg;

-         if (strict == DEDUCE_EXACT)
-           {
-             if (same_type_p (parm, type))
-               continue;
-           }
-         else
-           /* It might work; we shouldn't check now, because we might
-              get into infinite recursion.  Overload resolution will
-              handle it.  */
+         if (same_type_p (parm, type))
             continue;
-
+         if (strict != DEDUCE_EXACT
+             && can_convert_arg (parm, type, TYPE_P (arg) ?  
NULL_TREE : arg))
+           continue;
+
           return 1;
         }

A previous test of a similar patch but with only DEDUCE_CALL being  
changed didn't trigger infinite recursion anywhere in the C++  
testsuite.  I think the only way you can get recursion is if  
can_convert_arg tries to instantiate a template to make a conversion  
and that feeds back into this code, which I am not sure is possible--- 
what kinds of conversion functions are template functions but have  
non-dependent arguments?
Comment 21 Geoff Keating 2005-05-30 15:48:47 UTC
Created attachment 8996 [details]
smime.p7s
Comment 22 GCC Commits 2005-06-17 22:13:57 UTC
Subject: Bug 17413

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	geoffk@gcc.gnu.org	2005-06-17 22:13:36

Modified files:
	gcc/testsuite  : ChangeLog 
	gcc/cp         : ChangeLog pt.c 
Added files:
	gcc/testsuite/g++.dg/template: local5.C 

Log message:
	2005-06-17  Geoffrey Keating  <geoffk@apple.com>
	
	PR c++/17413
	* pt.c (type_unification_real): Apply template type deduction even
	to procedure parameters that are not dependent on a template
	parameter.
	
	Index: testsuite/ChangeLog
	2005-06-17  Geoffrey Keating  <geoffk@apple.com>
	
	PR c++/17413
	* g++.dg/template/local5.C: New.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.5649&r2=1.5650
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/local5.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.4794&r2=1.4795
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/pt.c.diff?cvsroot=gcc&r1=1.1007&r2=1.1008

Comment 23 GCC Commits 2005-07-28 10:23:16 UTC
Subject: Bug 17413

CVSROOT:	/cvs/gcc
Module name:	gcc
Branch: 	gcc-3_4-branch
Changes by:	giovannibajo@gcc.gnu.org	2005-07-28 10:22:23

Modified files:
	gcc/testsuite  : ChangeLog 
	gcc/cp         : ChangeLog call.c parser.c pt.c 
	gcc/testsuite/g++.dg/parse: crash11.C crash13.C 
Added files:
	gcc/testsuite/g++.dg/ext: packed8.C 
	gcc/testsuite/g++.dg/parse: error18.C 
	gcc/testsuite/g++.dg/template: crash25.C local5.C typedef2.C 

Log message:
	Backport:
	
	2004-09-16  Mark Mitchell  <mark@codesourcery.com>
	PR c++/16002
	* parser.c (cp_parser_simple_declaration): Commit to tentative
	parses after seeing a decl-specifier.
	(cp_parser_simple_declaration): Eliminate spurious message.
	(cp_parser_init_declarator): Adjust error message.
	
	2005-06-17  Geoffrey Keating  <geoffk@apple.com>
	PR c++/17413
	* pt.c (type_unification_real): Apply template type deduction even
	to procedure parameters that are not dependent on a template
	parameter.
	
	2004-11-02  Mark Mitchell  <mark@codesourcery.com>
	PR c++/18124
	* parser.c (cp_parser_type_parameter): Robustify.
	PR c++/18155
	* parser.c (cp_parser_single_declaration): Disallow template
	typedefs.
	(cp_parser_typedef_p): New function.
	
	2004-12-21  Mark Mitchell  <mark@codesourcery.com>
	PR c++/18378
	* call.c (convert_like_real): Do not permit the use of a copy
	constructor to copy a packed field.
	
	Backport:
	
	2004-09-16  Mark Mitchell  <mark@codesourcery.com>
	PR c++/16002
	* g++.dg/parse/error18.C: New test.
	* g++.dg/parse/crash11.C: Adjust error markers.
	
	2005-06-17  Geoffrey Keating  <geoffk@apple.com>
	PR c++/17413
	* g++.dg/template/local5.C: New.
	
	2004-11-02  Mark Mitchell  <mark@codesourcery.com>
	PR c++/18124
	* g++.dg/template/crash25.C: New test.
	PR c++/18155
	* g++.dg/template/typedef2.C: New test.
	* g++.dg/parse/crash13.C: Adjust error markers.
	
	2004-12-21  Mark Mitchell  <mark@codesourcery.com>
	PR c++/18378
	* g++.dg/ext/packed8.C: New test.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.3389.2.411&r2=1.3389.2.412
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.3892.2.228&r2=1.3892.2.229
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/call.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.452.2.26&r2=1.452.2.27
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/parser.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.157.2.57&r2=1.157.2.58
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/pt.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.816.2.56&r2=1.816.2.57
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/ext/packed8.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.1.42.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/parse/error18.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.1.12.3&r2=1.1.12.4
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/parse/crash11.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.2&r2=1.2.24.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/parse/crash13.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.1&r2=1.1.14.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/crash25.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.1.38.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/local5.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.1.14.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/typedef2.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.1.38.1

Comment 24 Giovanni Bajo 2005-07-28 10:24:53 UTC
Fixed also for GCC 3.4.5.