public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/18028] New: nested calls to template constructors generate incorrect result
@ 2004-10-15 21:51 bill at graysoft dot com
  2004-10-15 22:49 ` [Bug c++/18028] " pinskia at gcc dot gnu dot org
  2004-10-16 15:26 ` bangerth at dealii dot org
  0 siblings, 2 replies; 3+ messages in thread
From: bill at graysoft dot com @ 2004-10-15 21:51 UTC (permalink / raw)
  To: gcc-bugs

The included program does not appear to compile correctly
under gcc 3.4.2.

      The following statement, which does not appear to work, begins on
line 123 --

      seq t         /* sequence of size 1                              */
      (
         seq        /* sequence of size 2                              */
         (
           seq      /* sequence of size 2                              */
           (
              a,
              b
           ),
           c
         )
      );

where the struct seq has a number of constructors which are
generated using function templates.

      The computer used for this test is an Intel 686 running Red Hat
7.3.

      This bug report is intended to be specifically for gcc-3.4.2.
However, by way of information which may be of help or interest, I found
that neither gcc-2.96 nor gcc-3.3 were able to compile the program at
all.

      1.  Here is the compilation log for gcc-2.96 (installed by Red Hat)

+ g++ -v x1.cpp
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/2.96/specs
gcc version 2.96 20000731 (Red Hat Linux 7.3 2.96-110)
 /usr/lib/gcc-lib/i386-redhat-linux/2.96/cpp0 -lang-c++ -D__GNUG__=2 -
D__EXCEPTIONS -v -D__GNUC__=2 -D__GNUC_MINOR__=96 -D__GNUC_PATCHLEVEL__=0 -
D__ELF__ -Dunix -Dlinux -D__ELF__ -D__unix__ -D__linux__ -D__unix -D__linux -
Asystem(posix) -D__NO_INLINE__ -Acpu(i386) -Amachine(i386) -Di386 -D__i386 -
D__i386__ -D__tune_i386__ x1.cpp /tmp/ccWBU1FJ.ii
GNU CPP version 2.96 20000731 (Red Hat Linux 7.3 2.96-110) (cpplib) (i386 
Linux/ELF)
ignoring nonexistent directory "/usr/i386-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/include/g++-3
 /usr/local/include
 /usr/lib/gcc-lib/i386-redhat-linux/2.96/include
 /usr/include
End of search list.
 /usr/lib/gcc-lib/i386-redhat-linux/2.96/cc1plus /tmp/ccWBU1FJ.ii -quiet -
dumpbase x1.cpp -version -o /tmp/ccmC63RA.s
GNU C++ version 2.96 20000731 (Red Hat Linux 7.3 2.96-110) (i386-redhat-linux) 
compiled by GNU C version 2.96 20000731 (Red Hat Linux 7.3 2.96-110).
x1.cpp: In function `int main ()':
x1.cpp:131: parse error before `,'
x1.cpp:146: request for member `u' in `t', which is of non-aggregate
type `seq () (...)'

      A similar result was obtained using gcc-3.3.


      2. Here is the compilation log for gcc-3.4.2 --

+ g++ -v x1.cpp
Reading specs from /usr/local/lib/gcc/i686-pc-linux-gnu/3.4.2/specs
Configured with: ../gcc-3.4.2/configure --enable-__cxa_atexit
Thread model: posix
gcc version 3.4.2
 /usr/local/libexec/gcc/i686-pc-linux-gnu/3.4.2/cc1plus -quiet -v -D_GNU_SOURCE 
x1.cpp -quiet -dumpbase x1.cpp -mtune=pentiumpro -auxbase x1 -version -
o /tmp/ccM4JlhE.s
ignoring nonexistent directory "NONE/include"
ignoring nonexistent directory "/usr/local/lib/gcc/i686-pc-linux-
gnu/3.4.2/../../../../i686-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/lib/gcc/i686-pc-linux-gnu/3.4.2/../../../../include/c++/3.4.2
 /usr/local/lib/gcc/i686-pc-linux-gnu/3.4.2/../../../../include/c++/3.4.2/i686-
pc-linux-gnu
 /usr/local/lib/gcc/i686-pc-linux-
gnu/3.4.2/../../../../include/c++/3.4.2/backward
 /usr/local/include
 /usr/local/lib/gcc/i686-pc-linux-gnu/3.4.2/include
 /usr/include
End of search list.
GNU C++ version 3.4.2 (i686-pc-linux-gnu)
	compiled by GNU C version 3.4.2.
GGC heuristics: --param ggc-min-expand=47 --param ggc-min-heapsize=31978
 /usr/local/lib/gcc/i686-pc-linux-gnu/3.4.2/../../../../i686-pc-linux-
gnu/bin/as -V -Qy -o /tmp/ccvsdtHy.o /tmp/ccM4JlhE.s
GNU assembler version 2.13.2.1 (i686-pc-linux-gnu) using BFD version 2.13.2.1
 /usr/local/libexec/gcc/i686-pc-linux-gnu/3.4.2/collect2 --eh-frame-hdr -m 
elf_i386 -dynamic-linker /lib/ld-
linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o /usr/local/lib/gcc/i686-pc-linux-
gnu/3.4.2/crtbegin.o -L/usr/local/lib/gcc/i686-pc-linux-gnu/3.4.2 -
L/usr/local/lib/gcc/i686-pc-linux-gnu/3.4.2/../../../../i686-pc-linux-gnu/lib -
L/usr/local/lib/gcc/i686-pc-linux-gnu/3.4.2/../../.. /tmp/ccvsdtHy.o -lstdc++ -
lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/local/lib/gcc/i686-pc-linux-
gnu/3.4.2/crtend.o /usr/lib/crtn.o

      This compile was apparently successful.  But the program did not
function as expected.


      3. Here is the program x1.cpp which includes further discussion
of its purpose and the problem encountered in its comments --


#include <iostream>
#include <vector>

using namespace std;

/* This program implements a small variable length (up to 3 elements)  */
/* polymorphic sequence called seq.                                    */

/* The idea is that                                                    */

/*    seq x(1);             /* causes x to contain the int 1           */

/*    seq y(1, 2.6);        /* causes y to contain the int and double  */

/*    seq z(1, 2.3, "hi");  /* causes z to contain the int, double     */
/*                          /* and const char *                        */

/* The program is based on the usual approach of using a container     */
/* (std::vector) to hold pointers to a common base class, here U.      */

struct U {virtual ~U() {}};

/* What the common base class is the base of is the following template */
/* class, V, which is a shallow wrapper for the various values in the  */
/* sequence.                                                           */

/* Note that this implementation is quite rudimentary and direct.      */
/* All needed values are simply copied.  There is no attempt at        */
/* data sharing or memory management.                                  */

template <class T>
struct V : U
{
      T v;                    /* contained value                       */

      V(T v) : v(v) {}        /* copy construcor                       */
};

/* The polymorphic container is not itself a template but it does      */
/* have three template constructors: one for a single argument, one    */
/* for two arguments, and one for three arguments.  The idea is        */
/* that these arguments can be objects of any type.                    */

/* Each constructor makes an instance of the wrapper V of the          */
/* approriate type in dynamic memory for each of its arguments,        */
/* This instance is initialized using the value of the corresponding   */
/* argument. The location of each V is upcast to a U *,                */
/* pointer to the base class of V, and pushed into the vector u        */
/* which defines the sequence.                                         */

/* Note that because these constructors are function templates the     */
/* types of the various aruments are being deduced from the call.      */

struct seq
{
      vector<U *> u;          /* elements                              */

      seq ()
      {
         cout << "0 arg default constructor called" << endl;
      }

      template <class A> seq(A a)
      {
         cout << "1 arg template constructor called" << endl;

         u.push_back(dynamic_cast<U *>(new V<A>(a)));
      }

      template <class A, class B> seq(A a, B b)
      {
         cout << "2 arg template constructor called" << endl;

         u.push_back(dynamic_cast<U *>(new V<A>(a)));
         u.push_back(dynamic_cast<U *>(new V<B>(b)));
      }

      template <class A, class B, class C> seq(A a, B b, C c)
      {
         cout << "3 arg template constructor called" << endl;

         u.push_back(dynamic_cast<U *>(new V<A>(a)));
         u.push_back(dynamic_cast<U *>(new V<B>(b)));
         u.push_back(dynamic_cast<U *>(new V<C>(c)));
      }
};

/* Scratch types for testing seq                                       */

struct A {};
struct B {};
struct C {};

/* It is hard to imagine a simpler polymorphic container. Here is      */
/* the test.                                                           */

main()
{
/* First, a test of scalars                                            */

      seq z(1, 2.3, "hi");

/* This works perfectly. The following output statements print         */
/* the correct values:                                                 */

/*    1                                                                */
/*    2.3                                                              */
/*    hi                                                               */

      cout << dynamic_cast<V<int>          *>(z.u[0])->v << endl;
      cout << dynamic_cast<V<double>       *>(z.u[1])->v << endl;
      cout << dynamic_cast<V<const char *> *>(z.u[2])->v << endl;

/* Test of recursive structure                                         */

      A a;
      B b;
      C c;

/* The following statement will not compile using either gcc 2.96 or   */
/* 3.3. It does compile using gcc 3.4.2.                               */

      seq t         /* sequence of size 1                              */
      (
         seq        /* sequence of size 2                              */
         (
           seq      /* sequence of size 2                              */
           (
              a,
              b
           ),
           c
         )
      );

/* However, the resulting code does not appear to be correct since,    */
/* as a result of executing this statement, which calls three seq      */
/* constructors, the program prints only the following two lines --    */

/*  2 arg template constructor called                                  */
/*  2 arg template constructor called                                  */

/* indicating that, somehow, the outtermost constructor, the one       */
/* with only one argument, is not being called. Then, executing        */

      cout << "t.u.size() = " << t.u.size() << endl;

/* prints                                                              */

/*  t.u.size() = 2                                                     */

/* but the size of t.u should be 1.                                    */

}

-- 
           Summary: nested calls to template constructors generate incorrect
                    result
           Product: gcc
           Version: 3.4.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: bill at graysoft dot com
                CC: gcc-bugs at gcc dot gnu dot org
  GCC host triplet: i686-pc-linux-gnu


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18028


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [Bug c++/18028] nested calls to template constructors generate incorrect result
  2004-10-15 21:51 [Bug c++/18028] New: nested calls to template constructors generate incorrect result bill at graysoft dot com
@ 2004-10-15 22:49 ` pinskia at gcc dot gnu dot org
  2004-10-16 15:26 ` bangerth at dealii dot org
  1 sibling, 0 replies; 3+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2004-10-15 22:49 UTC (permalink / raw)
  To: gcc-bugs


------- Additional Comments From pinskia at gcc dot gnu dot org  2004-10-15 22:49 -------
Invalid as seq(seq (t)) is considered to call the copy constructor which is defined ___not___ to match 
templates (by the standard).  The 3.3 and before bug (is a different bug and is a dup of one of the most 
reported bugs to GCC).

-- 
           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|                            |INVALID


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18028


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [Bug c++/18028] nested calls to template constructors generate incorrect result
  2004-10-15 21:51 [Bug c++/18028] New: nested calls to template constructors generate incorrect result bill at graysoft dot com
  2004-10-15 22:49 ` [Bug c++/18028] " pinskia at gcc dot gnu dot org
@ 2004-10-16 15:26 ` bangerth at dealii dot org
  1 sibling, 0 replies; 3+ messages in thread
From: bangerth at dealii dot org @ 2004-10-16 15:26 UTC (permalink / raw)
  To: gcc-bugs


------- Additional Comments From bangerth at dealii dot org  2004-10-16 15:26 -------
Yes, to be more specific: in this situation 
------------- 
struct X { 
  template <typename T> X(T t); 
}; 
 
int main () { 
  X x; 
  X y(x); 
} 
------------- 
the compiler has to generate a copy constructor itself, the template 
copy constructor is only used for arguments T which are not of type 
X. You will want to have an additional, non-template constructor. 
 
W. 

-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18028


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2004-10-16 15:26 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-10-15 21:51 [Bug c++/18028] New: nested calls to template constructors generate incorrect result bill at graysoft dot com
2004-10-15 22:49 ` [Bug c++/18028] " pinskia at gcc dot gnu dot org
2004-10-16 15:26 ` bangerth at dealii dot org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).