[Bug libstdc++/115497] [15 Regression] __is_pointer doesn't compile with clang since 014879ea4c86b3b8ab6b61a1226ee5b31e816c8b
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115497 --- Comment #15 from Richard Smith --- (In reply to Jonathan Wakely from comment #14) > I assume clang doesn't have __is_arithmetic, __is_scalar and __is_void > built-ins yet, because also defines class templates > with those names. Clang has all of those (https://github.com/llvm/llvm-project/blob/12cf0dc685a9c3adfefc3a58f0b8ed4360be8b14/clang/include/clang/Basic/TokenKinds.def#L552), but it looks like happens to not use them in a way that breaks. The specific problem with __is_pointer in is that it's being used in a template argument: : public __bool_constant<__is_pointer(_Tp)> ... where it would be valid to parse a type. Clang's hack to treat `__is_pointer(T)` as the builtin (after we've seen a declaration using the same name) only applies in contexts where we know we're parsing an expression. (We can fix this, but I think the healthier thing long-term is to treat these as keywords everywhere.)
[Bug libstdc++/115497] [15 Regression] __is_pointer doesn't compile with clang since 014879ea4c86b3b8ab6b61a1226ee5b31e816c8b
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115497 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #13 from Richard Smith --- (In reply to Jonathan Wakely from comment #10) > The only foolproof fix would be to rename the __is_pointer class template. Yes, given that Clang treats this identifier as a keyword, the best solution would be for libstdc++ to stop using it as a type name. We have an awful hack in Clang to support libstdc++ doing this, and it'd be great to remove that eventually. (I apologize, we should have made this request years ago when we added the hack.) As is evidenced in this bug, this hack was only made to be good enough to support libstdc++ as it existed at the time. I'm not really sure what behavior one would expect from `__is_pointer(_Tp)`, given that it can parse as a type (treating `__is_pointer` as a placeholder for CTAD, which is semantically invalid in this context only because we can't perform CTAD here). We could extend our hack to support this too, but doing so is really a losing proposition. In general, we seem to have organically adopted the convention that `std::blah<...>` type traits correspond to `__blah` keywords, so it'd be great if libstdc++ didn't use any of those identifiers as type names.
[Bug c++/112455] New: befriending a lambda closure type doesn't grant access to the lambda body
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112455 Bug ID: 112455 Summary: befriending a lambda closure type doesn't grant access to the lambda body Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Target Milestone: --- Testcase: class C; auto x = [](MyC *p) { return p->n; }; class C { int n; friend decltype(x); } c; int k = x(&c); This appears to be valid, and Clang, MSVC, and EDG accept, but GCC reports an access error. The templated operator() of the lambda is a member function of a friend of C, so should have access to C::n.
[Bug c++/111923] default argument is not treated as a complete-class context of a class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923 --- Comment #9 from Richard Smith --- I don't think we intended for default arguments of class-scope lambdas to get the same complete-class context treatment as default argument of member functions, but the standard wording does currently seem to suggest that they do get that treatment. Filed https://github.com/cplusplus/CWG/issues/449 to suggest the standard wording be fixed to match the implementations.
[Bug c++/111633] New: __restrict on a member function is permitted in an inconsistent location relative to ref-qualifiers
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111633 Bug ID: 111633 Summary: __restrict on a member function is permitted in an inconsistent location relative to ref-qualifiers Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Target Milestone: --- GCC permits __restrict-qualified member functions. When combined with ref-qualifiers, the __restrict is written with the cv-qualifiers instead of after the ref-qualifier: struct A { // accepted void f() const __restrict &; // rejected void f() const & __restrict; }; This seems backwards to me. The `*this` parameter is of type `const &__restrict self`, so the latter syntax seems more appropriate. Perhaps it would make sense to accept the latter syntax, and possibly deprecate the former? (In the case of no ref-qualifier, it might make sense to also deprecate the case where the restrict qualifier is before or interleaved with cv-qualifiers.)
[Bug c++/110938] [11/12/13/14 Regression] miscompile if implicit special member is deleted and mutable
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110938 --- Comment #4 from Richard Smith --- Looks like the trait difference only happens if the templated constructor is not deleted, but the ABI mismatch happens regardless. Possibly there are two separate issues here?
[Bug c++/110938] New: miscompile if implicit special member is deleted in a subtle way
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110938 Bug ID: 110938 Summary: miscompile if implicit special member is deleted in a subtle way Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Target Milestone: --- Testcase: https://godbolt.org/z/rKG8c166f ``` template struct Error { //static_assert(false); using type = T; }; template using ArbitraryComputation = typename Error::type; struct X { template X(ArbitraryComputation &) = delete; X(const X&) = default; X(X&&) = delete; }; struct Y { #if 0 Y(const Y&) = default; Y(Y&&) = default; #endif mutable X x; int n; }; void print(int); Y f(); void g() { print(f().n); } ``` Uncommenting the `static_assert`, we can see that GCC never instantiates `Error` in this example. But it must! If `ArbitraryComputation` evaluates to `T`, then the non-trivial, templated constructor in `X` is used to copy the member `Y::x`, so `Y` is not trivially-copyable. This issue affects both type traits (GCC incorrectly evaluates `__is_trivially_copyable(Y)` to true) and code generation (GCC emits `f()` as returning in registers, which is both non-compliant with the ABI and doesn't follow the C++ language rules because `Y` has no trivial copy or move constructor). If the `#if 0` is changed to `#if 1`, the problem disappears.
[Bug c++/31584] [DR502] nested enum not considered dependent
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=31584 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #13 from Richard Smith --- (In reply to Andrew Pinski from comment #12) > GCC, ICC, clang and MSVC all accept the testcase in comment #11. I believe the testcase is valid. The instantiation of `C` looks like this: struct C { enum Inner { c }; template struct Dispatcher; template struct Dispatcher { }; }; ... and the template argument `c` here refers to the non-dependent enumeration constant `C::c`. The rule governing whether the original template `C` is valid is [temp.res.general]/6 (https://eel.is/c++draft/temp.res.general#6), and in particular: > no diagnostic shall be issued for a template for which a valid specialization > can be generated Because `C` has valid specializations, it's valid.
[Bug c++/110101] New: inconsistent behavior for array-to-pointer decay in constant evaluation in template argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110101 Bug ID: 110101 Summary: inconsistent behavior for array-to-pointer decay in constant evaluation in template argument Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Target Milestone: --- Testcase: template struct X {}; int arr[32]; constexpr void *id(void *p) { return p; } void f(X) {} // #1 void f(X) {} // #2 void f(X) {} // #3 Here, the three template arguments all represent the same address, but #1 and #3 point to the first array element whereas #2 points to the array itself. But GCC instead says that #1 and #2 are redefinitions, and that #1/#2 and #3 do not conflict -- and mangles #1 and #2 the same, but gives a different mangling to #3. It looks like the array-to-pointer conversion is not being properly handled here.
[Bug c++/109654] unnecessary "cannot bind packed field to reference" error when referenced type has aligned(1) attribute
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109654 --- Comment #2 from Richard Smith --- Hm, that doesn't explain why the second example I gave is accepted. But I suppose what's happening there is probably just that the `packed` attribute is ignored entirely for fields with alignment 1, so this behaves the same as ``` packed_int i; int &r = i; ``` ... which indeed doesn't produce an error or even a warning, presumably for the same reason (the alignment isn't part of the canonical type of i).
[Bug c++/109654] New: unnecessary "cannot bind packed field to reference" error when referenced type has aligned(1) attribute
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109654 Bug ID: 109654 Summary: unnecessary "cannot bind packed field to reference" error when referenced type has aligned(1) attribute Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Target Milestone: --- As a workaround for people hitting #36566, I think GCC should accept cases like this: typedef __attribute__((aligned(1))) int packed_int; struct __attribute__((packed)) Foo { int i; packed_int& get() { return i; } }; Unfortunately GCC rejects: :5:32: error: cannot bind packed field '((Foo*)this)->Foo::i' to 'packed_int&' {aka 'int&'} 5 | packed_int& get() { return i; } | And conversely, GCC accepts this code, which has a genuine misalignment issue: typedef __attribute__((aligned(1))) int packed_int; struct __attribute__((packed)) Foo { packed_int i; int& get() { return i; } }; I wonder if the check is mistakenly looking at the alignment of the source type instead of the alignment of the referent of the reference type?
[Bug libstdc++/109442] Dead local copy of std::vector not removed from function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109442 --- Comment #16 from Richard Smith --- (In reply to Richard Biener from comment #15) > I was specifically looking at C++20 7.6.2.7/10 to /14 (but maybe also > others and of course the relevant parts of the delete expression). In > particular the extra leeway the standard provides to new/delete _expressions_ > vs. calls of the global replaceable operators directly - do the > __builtin_operator_{new,delete} in this regard behave like new/delete > _expressions_ or like direct calls to the operators? They permit the same optimizations as new/delete expressions. The sections of the C++ standard that you referred to are what the documentation for the builtins means when it says: "[__builtin_operator_new] allows certain optimizations that the C++ standard does not permit for a direct function call to ::operator new (in particular, removing new / delete pairs and merging allocations)" > Do the builtins call one of the replaceable global new/delete operators > and thus users can reliably override them? If the implementation doesn't provide storage in some other way, optimize away the allocation, or merge it with another allocation, then yes, the storage is obtained by calling the corresponding replaceable global new/delete operators. Per the documentation: "A call to __builtin_operator_new(args) is exactly the same as a call to ::operator new(args), except that [text quoted above]" > How do the builtins behave during constexpr evaluation? new/delete > expressions have their behavior documented in the standard. They behave exactly like a direct call to the replaceable global allocation function. In Clang's implementation, direct calls to ::operator new and ::operator delete are permitted within calls to std::allocator::allocate and std::allocator::deallocate during constant evaluation, and are treated as allocating or deallocating arrays of T; consequently, calls to __builtin_operator_new and __builtin_operator_delete are permitted in the same contexts. In all other contexts, Clang rejects such calls, because the callee is not declared `constexpr`.
[Bug libstdc++/109442] Dead local copy of std::vector not removed from function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109442 --- Comment #14 from Richard Smith --- If I understand correctly, you're looking for documentation that __builtin_operator_new(size) has the exact same semantics and permits the same optimizations as `::new T` for a trivially-constructible non-array type `T` whose size is `size` and that __builtin_operator_delete(p) has the exact same semantics and permits the same optimizations as `::delete p` for a trivially-destructible non-array type `T` whose size is `size`, with `p` of type `T*` -- and similarly for the other (aligned, nothrow) variants? That is the intent; I can look into getting Clang's documentation updated to say that more explicitly if that's useful to you.
[Bug c++/100825] function signature constraints are not a part of mangled name
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100825 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #14 from Richard Smith --- I've proposed mangling rules on the ABI list: https://github.com/itanium-cxx-abi/cxx-abi/issues/24#issuecomment-1491130332 We're ready to land an implementation in Clang; I would appreciate feedback from GCC folks first, though.
[Bug c++/109422] wrong depth used for template parameter mangling for lambdas in function signatures
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109422 --- Comment #1 from Richard Smith --- > This should instead be mangled as T_TL__ Sorry, that's wrong; the rule we ended up with would mangle this as T_TL0__.
[Bug c++/109422] New: wrong depth used for template parameter mangling for lambdas in function signatures
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109422 Bug ID: 109422 Summary: wrong depth used for template parameter mangling for lambdas in function signatures Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Target Milestone: --- Testcase: struct C { template void f(decltype([](T, auto) { return 0; })) {} }; void g() { C().f({}); } GCC mangles f as _ZN1C1fIiEEvDTtlNS_UlT_T_E_EEE -- note that this is mangling / numbering the lambda directly within C, which is not permitted by http://itanium-cxx-abi.github.io/cxx-abi/abi.html#closure-types but seems like the best choice (see https://github.com/itanium-cxx-abi/cxx-abi/issues/165). But the mangling of the as T_T_ is definitely wrong -- two different template parameters should not be mangled the same. This should instead be mangled as T_TL__ under https://github.com/itanium-cxx-abi/cxx-abi/issues/31#issuecomment-528122117
[Bug c++/109337] c++2a test concepts4.C passes when it should fail
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109337 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #6 from Richard Smith --- (In reply to Andrew Pinski from comment #5) > (In reply to Christopher Di Bella from comment #3) > > This is apparently a Clang bug: the RHS of `R42c` isn't evaluated because of > > short-circuiting. Apologies for the noise and thanks for helping me work > > through it. > > No, clang and GCC disagree even on: > ``` > template concept A42b = true; > template concept R42c = A42b; > > static_assert (R42c); > ``` > > There is no short-circuting here. No substitution is performed into 'Tc&' here, because normalization of R42c produces the atomic constraint 'true' with an empty parameter mapping. So the type 'void&' is never formed.
[Bug c++/108090] New: pack expansion of using declarations doesn't properly handle dependent conversion function names
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108090 Bug ID: 108090 Summary: pack expansion of using declarations doesn't properly handle dependent conversion function names Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Target Milestone: --- Testcase, which I believe is valid, and other compilers accept: template struct As { operator T(); }; template struct AsAll : As... { using As::operator T...; }; AsAll x; But GCC rejects: :3:26: error: parameter packs not expanded with '...': 3 | using As::operator T...; | ^~~ :3:26: note: 'T'
[Bug c++/91292] Mangler incorrectly handles negative numbers in expressions
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91292 --- Comment #7 from Richard Smith --- (In reply to Patrick Palka from comment #3) > Hmm, but according to > http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling.literal the > mangling of a negative integer literal is prefixed with "n", There is no such thing as a negative integer literal. The ABI document says "negative integer *values* are preceded with "n""; this case is reached when mangling fully-resolved template arguments via the ::= production, not when mangling an instantiation-dependent expression. For example, given template struct X {}; template void f(X, X<-1>) {} template void f<1>(X<-1>, X<-1>); the proper mangling is _Z1fILi1EEv1XIXmlT_ngLi1EEES0_ILin1EE using ngLi1E for the instantiation-dependent expression -1 and Lin1E for the non-instantiation-dependent value -1. (In reply to Patrick Palka from comment #4) > And if -(1) is to be mangled the same as -1, then shouldn't > > template > typename std::enable_if<(int)sizeof(T) >= -(1), int>::type size1(T *t); > > template > typename std::enable_if<(int)sizeof(T) >= -1, int>::type size1(T *t); > > be considered two declarations of the same function? But IIUC that would > contradict [temp.over.link]p5, which says > > Two expressions involving template parameters are considered equivalent if > two function definitions containing the expressions would satisfy the > one-definition rule > > but IIUC the one-definition rule fails here because -1 is not the same > (token-wise) as -(1). These declarations are functionally-equivalent but not equivalent, so a program is not permitted to contain both. That language rule exists in order to allow implementations to do things like ignore parentheses in mangling, as the Itanium C++ ABI does. Note that parentheses are never mangled (except for a weird corner case involving pointers to members), so if your argument were correct it would apply very broadly. For example, that argument would imply that -1 and (-1) would need different manglings.
[Bug c++/102071] New: crash when combining -faligned-new=N with array cookie
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102071 Bug ID: 102071 Summary: crash when combining -faligned-new=N with array cookie Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Target Milestone: --- Testcase: struct X { ~X(); int c; }; extern int n; X *p = new X[n]; Compiling with -faligned-new=2 gives: :3:15: internal compiler error: tree check: expected class 'vl_exp', have 'unary' (nop_expr) in stabilize_call, at cp/tree.c:5739 3 | X *p = new X[n]; | ^ 0x1f2c1d9 internal_error(char const*, ...) ???:0 0x6baa59 tree_class_check_failed(tree_node const*, tree_code_class, char const*, int, char const*) ???:0 0xab0d8d stabilize_call(tree_node*, tree_node**) ???:0 0x8e0551 build_new(unsigned int, vec**, tree_node*, tree_node*, vec**, int, int) ???:0 0x9cffc5 c_parse_file() ???:0 0xb55092 c_common_parse_file() ???:0 FWIW, for this example, Clang passes align_val_t{max(alignof(size_t), alignof(X))} as the alignment argument to ensure the cookie is suitably aligned.
[Bug libstdc++/94295] use __builtin_operator_new and __builtin_operator_delete when available
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94295 --- Comment #8 from Richard Smith --- (In reply to Jonathan Wakely from comment #7) > Richard S., is there any reason to use the built-ins for the constant > evaluation case? No, Clang's constant evaluator treats the built-ins and calls to replaceable global [de]allocation functions identically. (The built-ins might be *marginally* more efficient, but it's not worth an #ifdef.)
[Bug c++/101370] New: miscompile of self-referential constexpr or constinit array initializer
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101370 Bug ID: 101370 Summary: miscompile of self-referential constexpr or constinit array initializer Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Target Milestone: --- Testcase (reduced from tcmalloc): struct Elem { Elem* next_ = this; Elem* prev_ = this; }; constinit Elem qs[3]; GCC generates a zero initializer for qs: qs: .zero 48 If the `constinit` is removed, GCC instead incorrectly generates a dynamic initializer, so presumably GCC knows that this variable *should* have a constant initializer but can't actually form one. The same problem can be observed without constinit: constexpr Elem rs[3]; const void *p = rs; ... again results in a zero-initialized global and no dynamic initializer.
[Bug c++/100640] New: GCC permits explicit instantiation of a constructor template with an explicit template argument list
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100640 Bug ID: 100640 Summary: GCC permits explicit instantiation of a constructor template with an explicit template argument list Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Target Milestone: --- Example: struct A { template A() {} }; template A::A(); GCC accepts this without even a warning under -std=c++20 -pedantic-errors, but this is not valid C++. If this is an intentional extension, it doesn't appear to be documented (and presumably should be rejected under -pedantic-errors).
[Bug c++/99534] New: bogus UDL diagnostic for header-name followed by macro
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99534 Bug ID: 99534 Summary: bogus UDL diagnostic for header-name followed by macro Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Target Milestone: --- Testcase: #define M #include "foo.h"M #include M This produces two warnings warning: invalid suffix on literal; C++11 requires a space between literal and string macro [-Wliteral-suffix] At least the second diagnostic appears to be incorrect: is not a string literal and lexically can't have a UDL suffix applied. The first diagnostic might also be incorrect (the header-name production for double-quoted strings also can't have a UDL suffix), but the max munch rule appears to require that we lex a string-literal rather than a header-name here! I think that's probably a wording bug, and the lexer should prefer to produce a header-name token whenever possible. (I'm taking that part to WG21 CWG; Clang also diagnoses this, but EDG does not.)
[Bug c++/99209] lambdas in function template signatures instantiated with wrong semantic context
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99209 --- Comment #1 from Richard Smith --- Here's a more interesting example: https://godbolt.org/z/83c36q #include constexpr char f(...) { return 'g'; } constexpr decltype(auto) f_adl(auto a) { return f(a); } namespace A { constexpr char f(auto) { return 'A'; } template void g(char FunctionParam = f_adl([]{})) { char Local = f_adl([]{}); std::cout << TemplateParam << FunctionParam << Local; } } namespace B { constexpr char f(auto) { return 'B'; } void call() { A::g(); } } int main() { B::call(); } This prints 'BgA', but should print 'AAA'. So the three lambdas actually exhibit three different behaviors, not two.
[Bug c++/99209] New: lambdas in function template signatures instantiated with wrong semantic context
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99209 Bug ID: 99209 Summary: lambdas in function template signatures instantiated with wrong semantic context Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Target Milestone: --- Testcase: constexpr decltype(auto) f_adl(auto a) { return f(a); } namespace A { constexpr int f(auto) { return 0; } template void g(int = f_adl([]{})) { f_adl([]{}); } } int main() { A::g(); } Here, the f_adl calls for the default template argument and default function argument incorrectly result in errors, because f can't be found by ADL. I suspect this is because the lambdas are being created in the wrong semantic context. (That is also visible in the output of __PRETTY_FUNCTION__ / std::source_location::current().function_name() in the lambda and in the mangling of the lambda closure type, but I think both of those are valid implementation choices -- the function name is implementation-defined and such instantiated lambdas appear to be numbered after those lambdas for which the ABI requires a numbering).
[Bug c++/99176] New: GCC rejects const_cast of null pointer in constant expressions
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99176 Bug ID: 99176 Summary: GCC rejects const_cast of null pointer in constant expressions Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Target Milestone: --- GCC rejects: constexpr const int *p = nullptr; constexpr int *q = const_cast(p); saying: :2:20: error: conversion of 'const int*' null pointer to 'int*' is not a constant expression 2 | constexpr int *q = const_cast(p); |^~~ I don't think any such rule exists, and other compilers accept. This only appears to affect const_casts of null pointers; non-null pointer const casts seem to work OK. Perhaps GCC thinks that this is a reinterpret_cast / cast from void* or something like that? It looks like this regressed between GCC 6 and GCC 7.
[Bug c++/55120] Inaccessible virtual base constructor does not prevent generation of default constructor
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55120 --- Comment #11 from Richard Smith --- (In reply to Jonathan Wakely from comment #10) > It looks like Clang has a bug with the inaccessible constructor too, and > strangely inconsistent handling of the inaccessible destructor. Access checks are performed on names and on derived-to-base conversions. On the constructor side, I think comment#4 is still relevant: it's not clear that a defaulted constructor does anything that would require an access check. I don't think it's clear that we perform a derived-to-base conversion, because constructing a base class doesn't perform a normal member function call. (We're not even *allowed* to perform a derived-to-virtual-base conversion until after the base is constructed per the 'period of construction' rules.) And I don't think it's reasonable to imagine that a defaulted constructor names its base classes via injected-class-names or something like that -- that name could be shadowed in the derived class with no effect on the validity of the defaulted constructor. Likewise, I don't think we can imagine that the default constructor for D names the default constructor of V as a member of D (which would be inaccessible), because the default constructor of V is not inherited into B and D by default, so we need to imagine it's named as a member of V, and it's accessible as a member of V. On the destructor side, I think [class.dtor]/7 is clear that only access to the destructor is considered, not access to the base subobject, and [class.dtor]/14 says the call is performed as if with a qualified name, so the fact that the destructor of the base is inaccessible as a member of the derived class is irrelevant -- it's accessible as a member of the base class, so the access check succeeds and the function is not deleted. However, I think the implicit definition of the destructor is ill-formed under [class.dtor]/14, because a derived-to-base conversion is presumably implied there. I think Clang follows the above interpretation (it accepts the construction side, does not treat the destructor as deleted, but rejects the implicit definition of the destructor), except that it never triggers the implicit definition of a trivial destructor, so it fails to diagnose the problem in the definition of D::~D() for the example in comment#0. (But does diagnose if ~V is non-trivial.) I think we should ask to have the core issue reopened, because I don't think the wording says anything sensible here. If we really want this case to be ill-formed, we need clarification on whether that applies only to the destruction side or also to construction, and presumably we should make the destructor be deleted in this case, not merely be ill-formed when implicitly defined.
[Bug c++/98859] New: pedantic error on use of __VA_OPT__ before C++20 is unnecessary and counterproductive
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98859 Bug ID: 98859 Summary: pedantic error on use of __VA_OPT__ before C++20 is unnecessary and counterproductive Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Target Milestone: --- There's no good way in ISO C or C++ to express what the GNU ,##__VA_ARGS__ extension does prior to the addition of __VA_OPT__. However, code targeting new compilers (that doesn't want to use GNU C / GNU C++) cannot reliably use __VA_OPT__ instead of the comma paste extension, because GCC's -pedantic-errors mode rejects it outside C++20. Such rejection is unnecessary: __VA_OPT__ is a reserved identifier in other language modes, so there is no conformance reason to issue a diagnostic on its use. I think it'd be useful for GCC to unconditionally allow using __VA_OPT__ in all language modes. (I'm changing Clang to do the same.)
[Bug c++/98804] GCC misparses template in pack expansion as comparison
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98804 --- Comment #1 from Richard Smith --- Somewhat more reduced: struct X { constexpr X(int&) {} }; template struct Y {}; int a; auto h(int b) -> Y; // #1 auto h(int b) -> Y; // #2 GCC accepts #1, but for #2 it produces seven (!) error messages: :6:21: error: template argument 1 is invalid 6 | auto h(int b) -> Y; | ^ :6:21: error: template argument 1 is invalid :6:21: error: template argument 1 is invalid :6:21: error: template argument 1 is invalid :6:18: error: invalid template-id 6 | auto h(int b) -> Y; | ^ :6:21: error: use of parameter outside function body before '>' token 6 | auto h(int b) -> Y; | ^ :6:6: error: deduced class type 'Y' in function return type 6 | auto h(int b) -> Y; | ^ :2:20: note: 'template > struct Y' declared here 2 | template struct Y {}; |^ As far as I'm aware, both #1 and #2 are valid. (I think the "use of parameter outside function body" restriction is referring to [dcl.fct.default]/9, but that refers only to uses of parameters within default arguments, not uses in other contexts in the function declaration.)
[Bug c/98217] Prefer a warning for when VLAs declared on stack
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98217 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #6 from Richard Smith --- Hi GCC folks! My preferred approach to take on the Clang side would be to change -Wvla to not warn on function parameter types, if GCC is prepared to make the same change. I don't think the current meaning of -Wvla is useful, and warning only in cases where there is a variably-modified type on the stack seems like the better meaning for -Wvla.
[Bug c++/97358] [8/9/10 Regression] ICE while building firefox since r8-2720
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97358 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #19 from Richard Smith --- (In reply to Jason Merrill from comment #10) > This doesn't look valid to me. In > > [x...] { x; }... > > we capture the entire pack, but then try to use only a single element. This > should be rejected because the use of x in the lambda body is not expanded The reference to 'x' is expanded within the scope of the parameter pack, though (which is the entire function template, because 'x' here refers to the parameter of the enclosing function template). So I think that case 2 is valid, and expands to foo( [x...] { return x.[0]; }, [x...] { return x.[1]; }, ... [x...] { return x.[N]; }, ); (That is, each lambda captures the entire pack and then uses only part of it.) More generally, I think cases such as foo([x...] { return f(x..., x); } ...); ... are valid, resulting in expansions such as foo( [x...] { return f(x.[0], x.[1], ..., x.[N], x.[0]; }, [x...] { return f(x.[0], x.[1], ..., x.[N], x.[1]; }, ... [x...] { return f(x.[0], x.[1], ..., x.[N], x.[N]; }, ); I think Case 3 is not valid because the reference to the pack y is not expanded *within the scope of that pack*, though it's not clear that the standard actually clearly says that anywhere.
[Bug c++/97256] auto function return different result
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97256 --- Comment #6 from Richard Smith --- My apologies, I misread the testcase. Yes, this is UB.
[Bug c++/97256] auto function return different result
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97256 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #4 from Richard Smith --- The reference to 'b' from within the lambda is not an odr-use, so is not transformed into a use of the lambda's capture. This program has defined behavior and is being miscompiled.
[Bug c++/97222] GCC discards attributes aligned and may_alias for typedefs passed as template arguments
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97222 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #3 from Richard Smith --- > would be interesting to see how ICC mangles the aligned case It doesn't, it just takes the properties from whichever instantiation happens to be performed first. On ICC, std::cout << alignof(typename identity::type) << std::endl; std::cout << alignof(typename identity::type) << std::endl; prints 4 4, and std::cout << alignof(typename identity::type) << std::endl; std::cout << alignof(typename identity::type) << std::endl; prints 16 16. The ICC behavior seems unsound, compared to the GCC / Clang behavior of (effectively) stripping the attribute from template arguments. > There is NO way defined at this point to mange for some attributes > including but not limited to may_alias and alignment. These can be mangled as s: http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.qualified-type Presumably the more problematic part from an ABI perspective is that this will change a bunch of existing manglings. Similarly from a source compatibility standpoint, making the alignment override part of the type would be a breaking change. It'd probably be better to add a new syntax for the new functionality (please, not based on an attributed typedef this time!) and deprecate the old way.