First Last Prev Next    No search results available      Search page      Enter new bug
Bug#: 3784
Product:  
Component:  
Status: RESOLVED
Resolution: DUPLICATE of bug 45
Assigned To: Nathan Sidwell <nathan@gcc.gnu.org>
Host:
Reported against  
Priority:  
Severity:  
Target Milestone:  
 
 
Target:
Reporter: holt@gholt.net
Add CC:
CC:
Remove selected CCs
Build:
URL:
Summary:
Keywords:
Known to work:
Known to fail:

Attachment Description Type Created Size Actions
Create a New Attachment (proposed patch, testcase, etc.) View All

Bug 3784 depends on: Show dependency tree
Show dependency graph
Bug 3784 blocks:

Additional Comments:






View Bug Activity   |   Format For Printing   |   Clone This Bug


Description:   Last confirmed: 2003-01-02 00:00 Opened: 2001-07-23 20:36
 Organization: gholt.net
 Confidential: no
 Synopsis: function not found if integer template parameter declared as unsigned in a different function
 Severity: non-critical
 Priority: low
 Category: c++
 Class:  rejects-legal
 Release: 3.0

Release:
unknown

Environment:
System: Linux barth.pulsent.com 2.4.3 #5 SMP Thu May 24 15:10:10 PDT 2001 i686 unknown
Architecture: i686

 
host: i686-pc-linux-gnu
build: i686-pc-linux-gnu
target: i686-pc-linux-gnu
configured with: configure --prefix=/usr/local/stow/gcc-3.0
Description:

The following code sample produces the following compilation error:

g++ test.cpp
test.cpp: In function int main (int, const char **)':
test.cpp:24: no matching function for call to abc (SArray<float, 2> 
&)'

It took me about an hour to figure out what was going on with this problem.
Accidently, one function declared the template parameter as signed instead
of unsigned, and this caused subsequent functions not to be found.
Specifically, in this example the function xyz() is defined (but never used),
but depending on a detail of its definition, another function abc() may or
may not be found by the compiler.

Here is the complete code that causes the problem:

template <typename T, unsigned n_dims> class SArray { };

//#define COMPILES_PROPERLY
#ifdef COMPILES_PROPERLY
template <typename T, unsigned n_dims>
#else
template <typename T, int n_dims>
#endif
T xyz(const SArray<T, n_dims> & arr) { }

template <typename T, unsigned n_dims>
void abc(const SArray<T, n_dims> & arr) { }
// Note that the definition of this function does not change--the definition
// of the xyz() function affects whether the abc() function is found.

int main(int argc, const char ** argv)
{
  SArray<float, 2> arr;
  abc(arr);     // This line causes an error if xyz's template parameter is
                // int, but no error if xyz's template parameter is unsigned.
}


How-To-Repeat:

  Compile the above code as is.

Fix:

  Workaround is to do what is shown when COMPILES_PROPERLY is defined.  The
  above code really shouldn't change the sign of the template parameter, but
  the mistake should not cause such an obscure error message.  And defining
  one function which does not overload any other functions should never
  mess up the definition of other functions.

------- Comment #1 From Nathan Sidwell 2001-12-15 11:53 -------
*** This bug has been marked as a duplicate of 45 ***

------- Comment #2 From Nathan Sidwell 2001-12-15 11:53 -------
State-Changed-From-To: open->analyzed
State-Changed-Why: Yup

------- Comment #3 From Wolfgang Bangerth 2002-11-05 14:30 -------
From: Wolfgang Bangerth <bangerth@ticam.utexas.edu>
To: gcc-bugs@gcc.gnu.org, <gcc-gnats@gcc.gnu.org>
Cc:  
Subject: Re: c++/3784: function not found if integer template parameter
 declared as unsigned in a different function
Date: Tue, 5 Nov 2002 14:30:31 -0600 (CST)

 There's definitely going on something fishy here:
 -------------------------------------------------
 template <typename T, unsigned N> class X { };
 
 template <typename T, int N>       void foo1(X<T,N>);
 template <typename T, unsigned N>  void foo2(X<T,N>);
 
 int main() {
   X<float, 2> x;
   foo2(x);
 }
 -------------------------------------------------
 
 This compiles fine if I remove the foo1 function that is not referenced at 
 all. If I leave it in, I get this:
 
 tmp/g> /home/bangerth/bin/gcc-3.3x-pre/bin/c++ test.cc
 test.cc: In function `int main()':
 test.cc:9: error: no matching function for call to `foo2(X<float, 2>&)'
 
 Seems as if on the definition of foo1, something's erroneously 
 overwritten.
 
 Regards
   Wolfgang
 
 -------------------------------------------------------------------------
 Wolfgang Bangerth              email:           bangerth@ticam.utexas.edu
                                www: http://www.ticam.utexas.edu/~bangerth
 
 


------- Comment #4 From Nathanael C. Nerode 2003-01-03 00:21 -------
From: Nathanael Nerode <neroden@twcny.rr.com>
To: gcc-gnats@gcc.gnu.org, holt@gholt.net, nathan@gcc.gnu.org,
   gcc-bugs@gcc.gnu.org
Cc:  
Subject: Re: c++/3784: function not found...
Date: Fri, 3 Jan 2003 00:21:12 -0500

 I started to track this down. The failure comes from call.c in 
 build_new_function_call somewhere around line 2717, when the call to 
 add_template_candidate fails to add anything.
 
 I put in a dump_node(t,0,stdout) just before the call.
 
 In the working cases, the first node is the template_decl for foo2.  It's 
 chained to the template_decl for X.
 
 In the broken case, it's chained to the template_decl for foo1, which is
 chained to the template_decl for X.
 @4      template_decl    name: @10      type: @3       srcp: test.cxx:3
                          chan: @11      rslt: @12      prms: @13
 @10     identifier_node  strg: foo1     lngt: 4
 
 I'm pretty sure this is wrong.  The tree we're looking at here is, I believe, 
 supposed to be for one overloaded function (foo2).  What does this have to do 
 with foo1?  Nothing.
 
 (Of course it's also possible that add_template_candidate should be able to 
 deal with this properly; I don't think that's the origin of the bug, though.)
 
 First working case:
 --
 template <typename T, unsigned N> class X { };
 
 // template <typename T, int N>       void foo1(X<T,N>);
 template <typename T, unsigned N>  void foo2(X<T,N>);
 
 int main() {
   X<float, 2> x;
   foo2(x);
 }
 --
 
 Second working case:
 --
 template <typename T, unsigned N> class X { };
 
 
 template <typename T, unsigned N>  void foo2(X<T,N>);
 template <typename T, int N>       void foo1(X<T,N>);
 
 int main() {
   X<float, 2> x;
   foo2(x);
 }
 --
 Note that this second case gives *exactly* the same tree dump as the first 
 working case, with no mention of foo1 at all.  Interesting, no?  Whether foo1 
 should be in this tree or not, it should be the same regardless of order of 
 declaration.  This example is why I suspect foo1 shouldn't be in this tree 
 (of course, I could be wrong, and this could be a case of one bug hiding 
 another).
 
 The broken case:
 --
 template <typename T, unsigned N> class X { };
 
 template <typename T, int N>       void foo1(X<T,N>);
 template <typename T, unsigned N>  void foo2(X<T,N>);
 
 
 int main() {
   X<float, 2> x;
   foo2(x);
 }
 --
 
 Next step is to try to figure out why this tree includes foo1 when it 
 shouldn't...


------- Comment #5 From Nathanael C. Nerode 2003-01-03 05:22 -------
From: Nathanael Nerode <neroden@twcny.rr.com>
To: gcc-gnats@gcc.gnu.org, gcc-prs@gcc.gnu.org, holt@gholt.net,
   nathan@gcc.gnu.org, gcc-bugs@gcc.gnu.org
Cc:  
Subject: Re: c++/3784:  function not found if...
Date: Fri, 3 Jan 2003 05:22:14 -0500

 I did some further work on this.  The binding for foo2 is created at the 
 bottom of binding_for_name, and as soon as it's created, it's wrong.  It 
 somehow thinks that foo2 is an OVERLOAD with two pieces: the real foo2, and 
 foo1.  This is clearly wrong.
 
 However, I haven't been able to figure out where this inaccurate overload is 
 created.  Both functions come out of the parser correctly.
 
 --Nathanael


------- Comment #6 From Nathanael C. Nerode 2003-01-03 06:03 -------
From: Nathanael Nerode <neroden@twcny.rr.com>
To: gcc-gnats@gcc.gnu.org, gcc-prs@gcc.gnu.org, holt@gholt.net,
   nathan@gcc.gnu.org, gcc-bugs@gcc.gnu.org
Cc:  
Subject: Re: c++/3784: evil bug from hell
Date: Fri, 3 Jan 2003 06:03:16 -0500

 Even simpler test case.
 
 --
 template <int N> class X {} ;
 
 template <long P> void foo(X<P>) ; // this is the killer line
 template <int N> void bar(X<N>) {return;};
 
 int main() {
   X<2> x;
   bar(x);
 }
 --
 
 Note that deleting the killer line or moving it below the other template 
 makes everything work.
 
 This is really, really, broken.


------- Comment #7 From Nathanael C. Nerode 2003-01-03 06:29 -------
From: Nathanael Nerode <neroden@twcny.rr.com>
To: gcc-gnats@gcc.gnu.org, gcc-prs@gcc.gnu.org, holt@gholt.net,
   nathan@gcc.gnu.org, gcc-bugs@gcc.gnu.org
Cc:  
Subject: Re: c++/3784: ...
Date: Fri, 3 Jan 2003 06:29:53 -0500

 Note that a call such as
  int main() {
    X<2> x;
    bar<2>(x);
  }
 
 or
  int main() {
    X<2> x;
    foo<2>(x);
  }
 
 works as expected. So it's an issue with the binding of the name 'bar', but 
 not with the binding of the names 'bar<...>'.  Dunno if this helps.

------- Comment #8 From Nathan Sidwell 2003-01-03 09:25 -------
State-Changed-From-To: analyzed->closed
State-Changed-Why: 2002-12-26  Nathan Sidwell  <nathan@codesourcery.com>
    
    	PR c++/45, c++/3784
    	* tree.c (cp_tree_equal, TEMPLATE_PARM_INDEX): The types must be
    	the same too.

First Last Prev Next    No search results available      Search page      Enter new bug