https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78896
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Last reconfirmed| |2016-12-22 CC| |jakub at gcc dot gnu.org, | |jason at gcc dot gnu.org Summary|Segmentation fault occurs |[C++17] Segmentation fault |when use variable |occurs when use variable |initialized using |initialized using |structured binding with |structured binding with |capture-by-ref lambda |capture-by-ref lambda Ever confirmed|0 |1 --- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> --- This is interesting. In [dcl.decomp]/4, there doesn't seem to be enough restrictions: "Otherwise, all of E’s non-static data members shall be public direct members of E or of the same unambiguous public base class of E, E shall not have an anonymous union member, and the number of elements in the identifier-list shall be equal to the number of non-static data members of E. Designating the non-static data members of E as m 0 , m 1 , m 2 , ... (in declaration order), each v i is the name of an lvalue that refers to the member m i of e and whose type is cv T i , where T i is the declared type of that member; the referenced type is cv T i ." It doesn't even say that E must be a class type (but what else can have non-static data members). And a lambda-expression has a class type [expr.prim.lambda]/4 "The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type — called the closure type — whose properties are described below. This class type is not an aggregate type (8.6.1). The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression. [ Note: This determines the set of namespaces and classes associated with the closure type (3.4.2). The parameter types of a lambda-declarator do not affect these associated namespaces and classes. — end note ]" so this effectively allows taking apart the implementation defined non-static data members of the lambda type. Shall that be allowed? Does the standard say anything about the members of the lambda class type (i.e. can we e.g. declare all of them to be private and reject the testcase from this reason)? Other implementation defined types that could have similar weird effects are e.g. va_list. #include <stdarg.h> void foo (int x, ...) { va_list ap; va_start (ap, x); auto [b, c, d, e] { *ap }; va_end (ap); } On x86_64-linux with -m32, both g++ and clang++ correctly reject this, because type of *ap is char. With -m64, g++ rejects this with: pr78896-2.C: In function ‘void foo(int, ...)’: pr78896-2.C:5:8: error: cannot decompose non-array non-class type ‘__va_list_tag’ auto [b, c, d, e] { *ap }; ^~~~~~~~~~~~ because we do not consider __va_list_tag a class type, just an implementation created record type. clang++ actually accepts this with -m64.