I think the most clearcut example is: int main() { using T = int[]; T{1, 2} == nullptr; } This compiles fine with clang, and is supported by the standard: the == operator explicitly performs array-to-pointer conversion (https://eel.is/c++draft/expr#eq-1), and array-to-pointer conversion is explicitly defined for rvalue arrays (https://eel.is/c++draft/expr#conv.array). Other examples (which again all compile with clang) are: +T{1, 2}; Here the standard wording seems to have a minor bug, as unary "+" does not explicitly perform the array-to-pointer conversion, and the general rubric for applying it (https://eel.is/c++draft/expr#basic.lval-6) only applies to glvalues as written. T{1, 2} + 1; Ditto. *(T{1, 2} + 1); Interesting as T{1, 2}[1] should be equivalent to this (modulo the value category of the result, https://eel.is/c++draft/expr#sub), yet the former is rejected by gcc and the latter accepted.
cp_build_binary_op calls cp_default_conversion on its operands and that calls decay_conversion which has: 2153 /* Don't let an array compound literal decay to a pointer. It can 2154 still be used to initialize an array or bind to a reference. */ 2155 if (TREE_CODE (exp) == TARGET_EXPR) 2156 { 2157 if (complain & tf_error) 2158 error_at (loc, "taking address of temporary array"); 2159 return error_mark_node; 2160 } convert_like_real does + /* Take the address explicitly rather than via decay_conversion + to avoid the error about taking the address of a temporary. */ + array = cp_build_addr_expr (array, complain); + array = cp_convert (build_pointer_type (elttype), array); to avoid that error.
*** Bug 89931 has been marked as a duplicate of this bug. ***
*** Bug 102568 has been marked as a duplicate of this bug. ***
Related discussion: https://stackoverflow.com/q/77051011/7325599 And an example from it: int main() { using U = int(&&)[1]; (void) *U{}; //ok everywhere using T = int[1]; (void) *T{}; //error in GCC } Online demo: https://godbolt.org/z/4s8v9PPqT
Related: https://cplusplus.github.io/CWG/issues/2548.html
(In reply to Nick Krempel from comment #0) > T{1, 2} + 1; > Ditto. That is what clang's issue: https://github.com/llvm/llvm-project/issues/54016 is about even.
This is due to my PR53220 change to discourage use of compound-literals in ways that produce a dangling pointer when the C++ compiler treats them as prvalues, unlike C where they have variable lifetime. I think the change was always wrong, but wasn't really a problem until we added array prvalues in C++17.
The trunk branch has been updated by Jason Merrill <jason@gcc.gnu.org>: https://gcc.gnu.org/g:305a2686c99bf9b57490419f25c79f6fb3ae0feb commit r14-5941-g305a2686c99bf9b57490419f25c79f6fb3ae0feb Author: Jason Merrill <jason@redhat.com> Date: Tue Nov 28 13:54:47 2023 -0500 c++: prvalue array decay [PR94264] My change for PR53220 made array to pointer decay for prvalue arrays ill-formed to catch well-defined C code that produces a dangling pointer in C++ due to the shorter lifetime of compound literals. This wasn't really correct, but wasn't a problem until C++17 added prvalue arrays, at which point it started rejecting valid C++ code. I wanted to make sure that we still diagnose the problematic code; -Wdangling-pointer covers the array-lit.c case, but I needed to extend -Wreturn-local-addr to handle the return case. PR c++/94264 PR c++/53220 gcc/c/ChangeLog: * c-typeck.cc (array_to_pointer_conversion): Adjust -Wc++-compat diagnostic. gcc/cp/ChangeLog: * call.cc (convert_like_internal): Remove obsolete comment. * typeck.cc (decay_conversion): Allow array prvalue. (maybe_warn_about_returning_address_of_local): Check for returning pointer to temporary. gcc/testsuite/ChangeLog: * c-c++-common/array-lit.c: Adjust. * g++.dg/cpp1z/array-prvalue1.C: New test. * g++.dg/ext/complit17.C: New test.
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>: https://gcc.gnu.org/g:5764825aed613f201a8bc47e5b239027a39691f0 commit r14-6342-g5764825aed613f201a8bc47e5b239027a39691f0 Author: Patrick Palka <ppalka@redhat.com> Date: Fri Dec 8 13:33:55 2023 -0500 c++: undiagnosed error_mark_node from cp_build_c_cast [PR112658] When cp_build_c_cast commits to an erroneous const_cast, we neglect to replay errors from build_const_cast_1 which can lead to us incorrectly accepting (and "miscompiling") the cast, or triggering the assert in finish_expr_stmt. This patch fixes this oversight. This was the original fix for the ICE in PR112658 before r14-5941-g305a2686c99bf9 made us accept the testcase there after all. I wasn't able to come up with an alternate testcase for which this fix has an effect anymore, but below is a reduced version of the PR112658 testcase (accepted ever since r14-5941) for good measure. PR c++/112658 PR c++/94264 gcc/cp/ChangeLog: * typeck.cc (cp_build_c_cast): If we're committed to a const_cast and the result is erroneous, call build_const_cast_1 a second time to issue errors. Use complain=tf_none instead of =false. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/initlist-array20.C: New test.
Fixed for GCC 14.