https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69961

            Bug ID: 69961
           Summary: Segfault when calling constructor from variadic
                    template by referring to T::T
           Product: gcc
           Version: 4.8.4
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: chatelet.guillaume at gmail dot com
  Target Milestone: ---

Created attachment 37794
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=37794&action=edit
The preprocessed file

------------------------------------------------------------------------
- source code (test.cc)
- This is the reduced example that triggers the bug, the c
------------------------------------------------------------------------
#include <string>

using std::string;

class Format {
 public:
  explicit Format(string formatted) {}
  string buffer;
};

string StrCat(const string& a) {
  return "";
}

template <typename... AV>
Format Message(string msg, const AV&... args) {
  return Format::Format(StrCat(msg, args...));
}

int main(int, char**) {
  Message("msg");
}

------------------------------------------------------------------------
- Command line
------------------------------------------------------------------------
> g++ -std=c++11 test.cc && ./a.out
> segmentation fault (core dumped)  ./a.out

------------------------------------------------------------------------
- Description - credits to richard-gccbugzilla at metafoo dot co.uk
------------------------------------------------------------------------
"The relevant language rule was (depending on your interpretation of the old
rule) either clarified or changed by C++ core issue 1310:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1310

Format::Format is ambiguous: it either names a constructor of Format or it
names the type Format (the name of a class is implicitly injected into the
scope of that class, more or less as if it contained a "typedef ::Format
Format;"; this is called the injected-class-name). In a function-style explicit
cast expression, such as yours above, the name before the left paren must name
a type (you cannot explicitly call a constructor).

The new language rule says that T::T only names the injected-class-name if the
name appears in a context where functions would not even be considered --
specifically, in a nested-name-specifier (T::T::), in an
elaborated-type-specifier (class T::T), and in a base-specifier (class U : T::T
{...};). (As it happens, there are no other cases where function names are
ignored.)

Clang does not implement that (new?) rule yet, which is why it accepts the
program (and compiles it to working code). GCC *does* implement the rule.
However, it apparently has a bug when the call has dependent arguments, and
doesn't enforce it in that case. If I were to guess, my guess would be that GCC
decides that this must be a static member function call, but whatever the
reason, it doesn't pass in a 'this' pointer to the constructor, which seems to
be what causes the segfault."

------------------------------------------------------------------------
- gcc environment
------------------------------------------------------------------------
> g++ -v -save-temps -std=c++11 test.cc
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu
4.8.4-2ubuntu1~14.04.1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs
--enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr
--program-suffix=-4.8 --enable-shared --enable-linker-build-id
--libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
--with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls
--with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug
--enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap
--enable-plugin --with-system-zlib --disable-browser-plugin
--enable-java-awt=gtk --enable-gtk-cairo
--with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home
--with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64
--with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64
--with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar
--enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686
--with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic
--enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu
--target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.1)
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-std=c++11' '-shared-libgcc'
'-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/4.8/cc1plus -E -quiet -v -imultiarch
x86_64-linux-gnu -D_GNU_SOURCE test.cc -mtune=generic -march=x86-64 -std=c++11
-fpch-preprocess -fstack-protector -Wformat -Wformat-security -o test.ii
ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/4.8"
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory
"/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/include/c++/4.8
 /usr/include/x86_64-linux-gnu/c++/4.8
 /usr/include/c++/4.8/backward
 /usr/lib/gcc/x86_64-linux-gnu/4.8/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-std=c++11' '-shared-libgcc'
'-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/4.8/cc1plus -fpreprocessed test.ii -quiet
-dumpbase test.cc -mtune=generic -march=x86-64 -auxbase test -std=c++11
-version -fstack-protector -Wformat -Wformat-security -o test.s
GNU C++ (Ubuntu 4.8.4-2ubuntu1~14.04.1) version 4.8.4 (x86_64-linux-gnu)
        compiled by GNU C version 4.8.4, GMP version 5.1.3, MPFR version
3.1.2-p3, MPC version 1.0.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
GNU C++ (Ubuntu 4.8.4-2ubuntu1~14.04.1) version 4.8.4 (x86_64-linux-gnu)
        compiled by GNU C version 4.8.4, GMP version 5.1.3, MPFR version
3.1.2-p3, MPC version 1.0.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 83f8d9bb238019ed17000f1b7e141e5a
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-std=c++11' '-shared-libgcc'
'-mtune=generic' '-march=x86-64'
 as -v --64 -o test.o test.s
GNU assembler version 2.24 (x86_64-linux-gnu) using BFD version (GNU Binutils
for Ubuntu) 2.24
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-std=c++11' '-shared-libgcc'
'-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id
--eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker
/lib64/ld-linux-x86-64.so.2 -z relro
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o
/usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o
-L/usr/lib/gcc/x86_64-linux-gnu/4.8
-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu
-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu
-L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib
-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. test.o -lstdc++ -lm -lgcc_s -lgcc
-lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o


The bug is also triggered on more recent versions of g++ like this one:
g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: /build/gcc/src/gcc-5-20160209/configure --prefix=/usr
--libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man
--infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/
--enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared
--enable-threads=posix --enable-libmpx --with-system-zlib --with-isl
--enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu
--disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object
--enable-linker-build-id --enable-lto --enable-plugin
--enable-install-libiberty --with-linker-hash-style=gnu
--enable-gnu-indirect-function --disable-multilib --disable-werror
--enable-checking=release
Thread model: posix
gcc version 5.3.0 (GCC)

Reply via email to