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

Reply via email to