[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(); 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 = 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.
[Bug c++/96876] New: missing check for destructibility of base classes in aggregate initialization
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96876 Bug ID: 96876 Summary: missing check for destructibility of base classes in aggregate initialization 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 accepts this invalid code (which is ill-formed because [dcl.init.aggr]/8 says it potentially-invokes the destructor for B, which [class.dtor]/15 says requires the destructor to be accessible): struct B { protected: ~B() {} }; struct C : B { int n; }; int f(); void g() { C c{{}, f()}; } ... and generates wrong code for this similar example: #include struct B { public: ~B() { puts("destroyed"); } }; struct C : B { int n; }; int f() { throw "hello"; } int main() { try { C c{{}, f()}; } catch (const char*) { } } ... which is required to print "destroyed" (when the B base class subobject is destroyed during stack unwinding), but with GCC does not.
[Bug c/96788] "integer constant is so large that it is unsigned" warning is incorrect
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96788 --- Comment #4 from Richard Smith --- (In reply to Richard Smith from comment #3) > such a literal "has no type" in C, which presumably results in undefined > behavior Ah, no, C11 6.4.4/2 makes this a constraint violation. But either way I think there's room for a vendor extension here.
[Bug c/96788] "integer constant is so large that it is unsigned" warning is incorrect
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96788 --- Comment #3 from Richard Smith --- In the mean time, what is GCC's intent here? Clang is following the behavior described by GCC's diagnostic text, treating decimal integer literals that don't fit in 'long long' but do fit in 'unsigned long long' as the latter type (I've not checked back far enough to tell if this is what GCC ever actually did, or if we got this by looking at the diagnostics and didn't check the behavior). If that's not what GCC intends to do any more, that'd be useful for us to know, and we can switch to following GCC's actual behavior. (It'd also make sense to update the diagnostic text in that case!) It looks like both the Clang behavior (treat the literal as 'unsigned long long') and the GCC behavior (treat the literal as '__int128' where available and 'long long' otherwise) are conforming extensions in both C and C++, even though __int128 isn't (yet) an extended integer type: such a literal "has no type" in C, which presumably results in undefined behavior, and makes the program ill-formed in C++, so it seems there is room for a vendor extension in both languages.
[Bug c/96788] New: "integer constant is so large that it is unsigned" warning is incorrect
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96788 Bug ID: 96788 Summary: "integer constant is so large that it is unsigned" warning is incorrect 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: typedef __typeof(9223372036854775808LL) T; produces the warning: :1:18: warning: integer constant is so large that it is unsigned for both C and C++ compilations, whether or not __int128 is available for the target. What actually appears to happen is that T is __int128 if __int128 is available, and T is otherwise 'long long'.
[Bug c++/96719] New: non-standard handling of alias templates used as template template arguments
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96719 Bug ID: 96719 Summary: non-standard handling of alias templates used as template template arguments 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: --- template struct A { using type = U; }; template using B = A; template class Z> struct Q { using type = typename Z::type; }; Here, Q::type should be float, but GCC believes it's int. I think this is due to GCC implementing the (non-standard at this time) rule in CWG1286. This is also reflected in incorrect manglings: void f(Q) {} ... is mangled as if it were written as `f(Q)`, and other rejects-valids, such as for: void f(Q) {} void f(Q) {}
[Bug c++/96604] New: rejects-valid on befriending specialization of conversion function template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96604 Bug ID: 96604 Summary: rejects-valid on befriending specialization of conversion function template 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: struct A { template operator T(); }; struct X {}; struct B { friend A::operator X(); }; Per [temp.mem]/5 and /6, I think this is supposed to perform template argument deduction against the conversion function template and befriend operator T with T = B. Clang, EDG, and MSVC accept.
[Bug c++/96223] DR 1787 and indeterminate values in constexpr context
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96223 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #2 from Richard Smith --- P1331R2 explicitly disallows in a constant evaluation: "- an lvalue-to-rvalue conversion that is applied to an object with indeterminate value ([basic.indet]);" so GCC is correct to reject such cases.
[Bug c++/59978] C++11 Non-Type-Template-Parameter Pack Expansion not working according to standard
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59978 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #1 from Richard Smith --- This appears to have been fixed in GCC 5.2 onwards.
[Bug c++/95349] Using std::launder(p) produces unexpected behavior where (p) produces expected behavior
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95349 --- Comment #37 from Richard Smith --- (In reply to Richard Biener from comment #36) > The main issue I see is that this differing expectations of C and C++ are > impossible to get correct at the same time. That is a rather bold claim. I think you can satisfy both rule sets by using the C++ rule even in C. It is conservatively correct to discard the effective / dynamic type when you see a memcpy, and the C++ semantics require you to do so. The C semantics also appear to require the same thing, if you cannot track the destination back to either an object with a declared type or to a heap allocation; as described in comment#35, GCC gets this wrong and presumably miscompiles C code in some cases as a result. It seems to me that all you're allowed to do within the bounds of conformance is: #1 if you can track the destination back to an object with declared type in C code, then use its type as the effective type of the result #2 if you can track the destination back to a heap allocation in C code, then copy the effective type from source to destination #3 otherwise (in either C or C++) erase the effective type of the destination (#1 and #3 will presumably result in memcpy being replaced by some operation that updates the effective type, rather than being eliminated entirely.)
[Bug c/95630] New: rejects-valid on comparison of pointers to complete vs incomplete types in C11 mode
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95630 Bug ID: 95630 Summary: rejects-valid on comparison of pointers to complete vs incomplete types in C11 mode 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: int f(int (*p)[], int (*q)[3]) { return p < q; } This is a constraint violation in C99, but the relevant rule was removed in C11. GCC still rejects in -std=c11 mode under -pedantic-errors.
[Bug c++/95536] New: tag name injection doesn't happen for return type of a friend
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95536 Bug ID: 95536 Summary: tag name injection doesn't happen for return type of a friend 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 A { friend struct B *f(); }; B *p; GCC rejects this saying that 'B' is not declared, which is incorrect -- the 'struct B' introduces the name 'B' into the enclosing non-class scope. GCC gets this right for struct A { friend void f(struct B *); }; B *p; so I'd guess that GCC is incorrectly applying the rules for friend class declarations (eg, 'friend struct B;' does not make 'B' visible outside the class).
[Bug c++/95349] Using std::launder(p) produces unexpected behavior where (p) produces expected behavior
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95349 --- Comment #20 from Richard Smith --- (In reply to Andrew Downing from comment #19) > Not that it would make a difference in this particular situation, but is the > intent of P0593R6 to only allow implicitly creating an object in the > relevant storage location where one hasn't already been implicitly or > explicitly created? No, the new objects are allowed to replace existing objects. For example, this implementation would also be correct: std::uint64_t* s3(double* p) { std::memmove(p, p, sizeof(double)); return std::launder(reinterpret_cast(p)); } ... on the basis that it has defined behavior if the memmove implicitly creates an 'uint64_t' object in the underlying storage after it (notionally) copies the contents elsewhere and before it (notionally) copies the contents back again. (The 'launder' is necessary in order to form a pointer to the implicitly-created uint64_t object, because p doesn't point to that object.)
[Bug c++/95349] Using std::launder(p) produces unexpected behavior where (p) produces expected behavior
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95349 --- Comment #18 from Richard Smith --- (In reply to Andrew Downing from comment #17) > Also none of the behavior described in p0593 is required for this C++ > program to be well defined. All objects that are required to exists here are > created explicitly. It's not relying on the implicit creation of any > objects. This is valid C++17 code. I agree, for what it's worth. I think the only thing that might suggest otherwise is the wording in the C standard that says that memcpy copies the effective type, but that doesn't mean anything in C++ (and it's also specified in the language section of C, not the library section, so isn't part of the wording that C++ incorporates by reference). C++ doesn't have any wording that says what value an object has after you memcpy the representation of a value of a different type over it, but there isn't any provision for memcpy to change the dynamic type of the object prior to P0593 (and after P0593, memcpy is only allowed to change the dynamic type if doing so makes the program's behavior more defined).
[Bug c++/95349] Using std::launder(p) produces unexpected behavior where (p) produces expected behavior
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95349 --- Comment #16 from Richard Smith --- Per p0593, memcpy implicitly creates objects (of any implicit lifetime type) in the destination. It does not propagate the objects in the source memory to the destination memory, and can therefore be used to perform a bit cast. (This is different from C, where memcpy either preserves or copies the effective type depending on whether the destination has a declared type.) The s3 function in comment#1 looks correct to me (with or without the launder). Optimizing it to { return (uint64t *)p; } is incorrect, because it loses the erasure of dynamic type information that p0593 requires from memcpy in C++.
[Bug c++/94676] New: constexpr destructors run too late for temporaries created inside __builtin_constant_p
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94676 Bug ID: 94676 Summary: constexpr destructors run too late for temporaries created inside __builtin_constant_p 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 A { int *p; constexpr ~A() { *p = 0; } }; static_assert(!__builtin_constant_p((A{}, 123))); I think this testcase should be accepted. The way I see it, there are two ways one could approach this: 1) Run the destructor for the A temporary after evaluating __builtin_constant_p's operand, notice the operand is non-constant, and evaluate the __bcp call to 0. 2) Notice that the __bcp call's operand has a side-effect on the enclosing evaluation (registering a non-trivial destructor for a temporary) and evaluate the call to 0 due to that side-effect. [This is what Clang currently does.] I was considering changing Clang's behavior from option 2 to option 1, but I noticed that GCC actually appears to do a third thing: 3) Run the destructor at the end of the entire static-assert condition and reject the program because the destructor (run outside of the protection of __builtin_constant_p) has a side-effect. I don't think there's an obvious correct answer here, but (3) doesn't seem right to me.
[Bug c++/94569] alignas(object) with a weaker (smaller) alignment than the alignas(type) of it's type compiles, inconsistent with the C++ standard
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94569 --- Comment #4 from Richard Smith --- (In reply to Richard Biener from comment #3) > But isn't the alignas(32) also "appertaining to that entity"? No. The alignas(32) appertains to the struct. This is specified in [class]/2: "The optional attribute-specifier-seq appertains to the class".
[Bug c++/94569] alignas(object) with a weaker (smaller) alignment than the alignas(type) of it's type compiles, inconsistent with the C++ standard
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94569 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #1 from Richard Smith --- I believe the particular rule that is violated by this example is [dcl.align]p5: "The combined effect of all alignment-specifiers in a declaration shall not specify an alignment that is less strict than the alignment that would be required for the entity being declared if all alignment-specifiers appertaining to that entity were omitted."
[Bug libstdc++/94295] use __builtin_operator_new and __builtin_operator_delete when available
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94295 --- Comment #6 from Richard Smith --- (In reply to Marc Glisse from comment #5) > Ah, since you are here, and you appeared as an author of N3664 but not N3537 > (precisely when this subtlety happened), could you explain why? It isn't > discussed in the paper, complicates the design, and I cannot think of any > use for this distinction It isn't discussed in the paper because it wasn't part of the original plan / design, but was added due to committee push-back. People want some guarantees: * If they write a test for their global 'operator new' (particularly, testing failure cases, mallinfo, the effect of configuration parameters on its behavior, ...), that test should still work in the presence of the language change. * A direct function call to a user-defined function should behave as a direct function call to that user-defined function. Even if it has a non-identifier name. In the end, the language and user model we found to be most satisfying, given the above, is: new-expressions, like std::allocator, may obtain storage by calling 'operator new', but it's unspecified how often it's called and with what arguments. And the language rules are an approximation of that idea. (In reply to Marc Glisse from comment #5) > This of course doesn't at all prevent from adding a __builtin_operator_new > option in std::allocator, it only affects how motivated we should be to fix > the non-conformance. Well, in case it helps your analysis, LLVM once did what GCC does now (before there were standard rules in place), and in practice we saw it break some stuff (largely, tests for allocators, but also weird things like using 'operator new((size_t)-1)' as a way to throw bad_alloc from code that can't '#include ').
[Bug libstdc++/94295] use __builtin_operator_new and __builtin_operator_delete when available
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94295 --- Comment #4 from Richard Smith --- (In reply to Andrew Pinski from comment #3) > PR 23383 is where part of the discussion was done. > > In fact GCC implements the optimization without the builtin: > https://gcc.gnu.org/legacy-ml/gcc-patches/2019-07/msg00136.html Yep, looks like GCC miscompiles direct calls to operator new / operator delete since that patch landed: https://godbolt.org/z/dK99Rz
[Bug libstdc++/94295] use __builtin_operator_new and __builtin_operator_delete when available
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94295 --- Comment #2 from Richard Smith --- (In reply to Marc Glisse from comment #1) > (In reply to Richard Smith from comment #0) > > The C++ language rules do not permit optimization (eg, deletion) of direct > > calls to 'operator new' and 'operator delete'. > > I thought that was considered a bug? No, it's intentional: if the user directly calls '::operator new(42)' and they've replaced that function, the replacement function is guaranteed to be called. In this regard, 'operator new' is just a regular function with a funny name. To be clear, the implicit call to 'operator new' produced by, say, 'new int' *is* optimizable, but a direct explicit call to 'operator new(sizeof(int))' is not. > Gcc does optimize those, like it does malloc/free... That sounds like non-conforming behavior. > > This bug requests that libstdc++ uses these builtins when available. > > So just in std::allocator, or are there other places? std::allocator's specification has an explicit provision to permit these optimizations, see [allocator.members]/4: "The storage for the array is obtained by calling ::operator new (17.6.2), but it is unspecified when or how often this function is called." In Clang + libc++ at least, we interpret that as meaning we can call '::operator new' zero times if we don't need the storage, just like for a new-expression, and the LWG members I've talked to about this have agreed that that's in line with the intent.
[Bug libstdc++/94295] New: use __builtin_operator_new and __builtin_operator_delete when available
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94295 Bug ID: 94295 Summary: use __builtin_operator_new and __builtin_operator_delete when available Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Target Milestone: --- See https://bugs.llvm.org/show_bug.cgi?id=45287 for some background. The C++ language rules do not permit optimization (eg, deletion) of direct calls to 'operator new' and 'operator delete'. libstdc++ uses such calls to implement std::allocator: https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/ext/new_allocator.h#L112 As a consequence, allocations performed by libstdc++'s containers are not optimizable. Clang provides a pair of builtin functions to work around this issue: https://clang.llvm.org/docs/LanguageExtensions.html#builtin-operator-new-and-builtin-operator-delete __builtin_operator_new(args) is equivalent to ::operator new(args) except that it permits optimizations. __builtin_operator_delete(args) is equivalent to ::operator delete(args) except that it permits optimizations. You can detect support for these builtins with #ifdef __has_builtin #if __has_builtin(__builtin_operator_new) >= 201802L // ... #endif #endif (Note that __has_builtin(...) returned 1 for an older version of the builtins that didn't support placement forms, and so couldn't be used for aligned allocation and sized delete. It's probably not worth your time dealing with those.) This bug requests that libstdc++ uses these builtins when available. (Separately, it'd be great if GCC considered supporting them too.)
[Bug c++/94227] New: ambiguous lookup for nested-name-specifier in using-declaration is not diagnosed
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94227 Bug ID: 94227 Summary: ambiguous lookup for nested-name-specifier in using-declaration is not diagnosed 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: --- GCC accepts this invalid code: namespace N1 { int (); } namespace N2 { struct N1 { float (); }; } using namespace N2; int = N1::f(); This should be rejected due to ambiguity: the name N1 on the final line is looked up by unqualified lookup, and that lookup is ambiguous between ::N1 and ::N2::N1. But GCC accepts and selects ::N1. (Originally filed as a Clang rejects-valid here: https://llvm.org/PR45216)
[Bug c++/92169] crash on referring to a local class member by unqualified name from outside the enclosing function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92169 --- Comment #4 from Richard Smith --- Aha! godbolt.org implicitly adds -g to its command line. Try that; that causes a crash for this testcase for me with GCC 9.2.1.
[Bug c++/92169] crash on referring to a local class member by unqualified name from outside the enclosing function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92169 --- Comment #2 from Richard Smith --- Still crashes GCC trunk from today: https://godbolt.org/z/zWvT4w
[Bug c++/92271] New: for consistency, __is_same_as should be named __is_same
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92271 Bug ID: 92271 Summary: for consistency, __is_same_as should be named __is_same 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: --- The convention for type trait builtins adopted by essentially every C++ compiler vendor is to expose std::SOME_TRAIT::value as __SOME_TRAIT(A, B, C). GCC violates this convention in one case: std::is_same::value is exposed as __is_same_as(A, B) rather than as __is_same(A, B). For consistency and code portability, I suggest that GCC accepts __is_same as a synonym for __is_same_as. (FWIW, Clang uses the name __is_same here, but will soon accept __is_same_as for GCC compatibility.)
[Bug c++/92169] New: crash on referring to a local class member by unqualified name from outside the enclosing function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92169 Bug ID: 92169 Summary: crash on referring to a local class member by unqualified name from outside the enclosing function 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: --- [Probably no-one will ever write code like this outside a compiler test case, but filing just in case this affects non-contrived situations.] This code crashes every version of g++ that supports deduced return types: auto f() { static int n; struct Y { static int () { return n; } struct X { int (); }; }; return Y::X(); }; using X = decltype(f()); int ::get() { return g(); }
[Bug c++/87150] [8 Regression] move ctor wrongly chosen in return stmt (derived vs. base)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87150 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #22 from Richard Smith --- (In reply to Marek Polacek from comment #20) > (In reply to Jason Merrill from comment #19) > > And now P1155/P1825 removes that text, so in C++20 mode the original > > testcase needs to call the move constructor again. Marek, I don't see > > P1825R0 in cxx-status.html, was there a reason not to add it? > > No, I followed clang's table but they're missing that one. I'll fix that & > open a PR for P1825R0. FYI, it is in Clang's table, but I put it in the C++11 features list since it's a DR and we're considering it to retroactively apply to C++11's addition of move semantics.
[Bug c++/67898] rejects-valid on overloaded function as non-type template argument of dependent type
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67898 --- Comment #2 from Richard Smith --- (Clang trunk now accepts both testcases.)
[Bug c++/86501] shadow template parameter
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86501 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #2 from Richard Smith --- I think EDG and Clang are wrong here and GCC is right. The template friend declaration introduces V into the global namespace, so it is not "redeclared within its scope" (per [temp.local]p6).
[Bug c++/90792] incorrect mangling for beginning with an
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90792 --- Comment #3 from Richard Smith --- (In reply to Andrew Pinski from comment #2) > Related to the upstream ABI issue: > https://github.com/itanium-cxx-abi/cxx-abi/issues/38 I don't think so, except that they're both about the 'sr' mangling in general. These two issues seem to have been muddled up repeatedly on the issues you cited. ABI issue 38 is about whether we mangle the original syntax or some resolved form of it. This issue (and PR88413) is about whether an 'E' is required to terminate the nested-name-specifier in certain 'sr' productions. I think the two questions are independent, and the ABI is currently clear that the 'E' is required in the example in comment#0.
[Bug c++/90792] New: incorrect mangling for beginning with an
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90792 Bug ID: 90792 Summary: incorrect mangling for beginning with an 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: --- Imported from https://llvm.org/PR14117 template struct IsConvertible { static const bool value =true; }; template struct EnableIf { typedef int Type; }; template void Handle(S x, typename EnableIf::value>::Type dummy) { } template void Handle( int x, typename EnableIf::value>::Type dummy ); gcc produces _Z6HandleIiEvT_N8EnableIfIXsr13IsConvertibleIS0_E5valueEE4TypeE and clang produces _Z6HandleIiEvT_N8EnableIfIXsr13IsConvertibleIS0_EE5valueEE4TypeE. Per the Itanium ABI, http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.unresolved-name there are two rules that can produce an 'sr' mangling: ::= sr ::= [gs] sr + E ::= [ ] ::= ::= ::= ::= [ ] Here, 13IsConvertible is an , not an , so an E must be inserted after the qualifiers even if there's only one of them. The demangler has a matching bug; it can demangle the incorrect mangling but not the correct one.
[Bug libstdc++/90266] missing or broken check for vector::size() exceeding max_size()
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90266 Richard Smith changed: What|Removed |Added Version|unknown |8.3.0 --- Comment #3 from Richard Smith --- (In reply to Jonathan Wakely from comment #1) > Which version are you using? (You didn't say) Sorry for leaving that out! I was using "clang (trunk)" on godbolt, which is apparently 8.3.0. Sounds like this was fixed in the interim?
[Bug libstdc++/90266] New: missing or broken check for vector::size() exceeding max_size()
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90266 Bug ID: 90266 Summary: missing or broken check for vector::size() exceeding max_size() Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Target Milestone: --- Testcase: #include using T = int; size_t e() { std::vector vb; return vb.max_size(); } size_t f() { std::vector vb(e()); vb.push_back({}); return vb.size(); } size_t g() { std::vector vb(e()); vb.push_back({}); vb.push_back({}); return vb.size(); } Compiled using -m32, I find: * e() returns 0x3fff (good) * f() invokes operator new(-4) and returns 0 (wrong; should throw length_error) * g() invokes operator new(-4) twice (?!) and returns 1 It looks like the check for size() exceeding max_size() is missing. [For a compiler that deletes unused new/delete pairs, f() otherwise could incorrectly compile to just "return 0;" with no exception thrown. Presumably the same would happen under -m64 with an allocator that has a 32-bit max_size().]
[Bug c++/90107] New: rejects-valid on global-namespace-qualified variable declared after class definition
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90107 Bug ID: 90107 Summary: rejects-valid on global-namespace-qualified variable declared after class definition Product: gcc Version: unknown Status: UNCONFIRMED Keywords: rejects-valid 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 these valid examples, producing a bogus "expected ';' after struct definition" diagnostic: struct A; namespace N { extern A a; } struct A {} ::N::a; struct A; struct B { static A a; }; struct A {} ::B::a; (I just fixed a rejects-valid on the same cases in Clang.)
[Bug c++/58074] [C++11][DR 1333] __is_trivial intrinsic fails for deleted members and for non-trivial copy-c'tors
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58074 --- Comment #11 from Richard Smith --- The point of trivial (as distinguished from trivially-copyable) is that an instance of type T can be created and "properly" initialized (albeit left with an indeterminate value) without executing any code. (The notion of a trivial type is not used by the core language, and is used in the library only to constrain things like the template parameters of basic_string and aligned_storage, where it is intentional that objects of type T can be created by allocating suitable storage and performing no further initialization.) So I think the language rule after the application of the relevant DRs is approximately right: a type with a deleted default constructor should not be considered trivial. (It's arguable that a type with multiple default constructors should perhaps also not be considered trivial. Or maybe we should decide that the language notion of "trivial" is a useless relic of "POD" and should be removed from the core language, and that the library should be looking for types that are trivially default-constructible and trivially-copyable in the places where it currently looks for "trivial" types.)
[Bug c++/89600] New: rejects-valid on dependent block-scope using declaration
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89600 Bug ID: 89600 Summary: rejects-valid on dependent block-scope using declaration 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: --- GCC rejects this valid code: template T f() { using T::Bar; return Bar; } As follows: : In function 'T f()': :2:39: error: 'T' is not a namespace or unscoped enum 2 | template T f() { using T::Bar; return Bar; } | ^~~ ... which is wrong; T could be an unscoped enumeration: enum E { Bar }; E e = f();
[Bug c++/89001] New: g++ uses wrong mangling for lifetime-extended temporaries
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89001 Bug ID: 89001 Summary: g++ uses wrong mangling for lifetime-extended temporaries 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: --- Consider: inline int & = 0; int *p = GCC mangles the lifetime-extended temporary as _ZGR1r0, which doesn't match the ABI mangling rule (http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-special-temporaries). The mangling required by the ABI (and produced by Clang) is _ZGR1r_
[Bug c++/86049] Array bindings are not const when initializer is
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86049 --- Comment #5 from Richard Smith --- This was just reported as http://lists.isocpp.org/core/2018/12/5320.php; I don't believe it's on the core issues list yet. [@Tomalak, I think the standard is clear here: "If the assignment-expression in the initializer has array type A and no ref-qualifier is present, e has type cv A" Here, A is the array type 'const int[1]' and cv is empty, so e has type 'const int[1]'. But, as noted in comment#2, that seems like the wrong outcome. It also contradicts the non-normative note in [dcl.struct.bind]p3, which further suggests that this outcome was probably not the intent of the wording.]
[Bug c/88382] New: undocumented GNU C extension: C++ raw string literals permitted in GNU C
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88382 Bug ID: 88382 Summary: undocumented GNU C extension: C++ raw string literals permitted in GNU C 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: --- GCC's documentation of GNU C extensions appears not to mention allowing raw string literals in C, which GCC has permitted in -std=gnu* since GCC 5.
[Bug middle-end/87237] __atomic_load on 4-byte-sized, 1-byte-aligned struct is not atomic
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87237 --- Comment #4 from Richard Smith --- (In reply to Alexander Monakov from comment #3) > With GCC size/align are 3/1 while with Clang it's 4/4 as you said Oh sorry, you're right, I'd forgotten about this ABI discrepancy. We really need to get the psABI fixed to say one way or the other! :)
[Bug middle-end/87237] __atomic_load on 4-byte-sized, 1-byte-aligned struct is not atomic
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87237 --- Comment #2 from Richard Smith --- (In reply to Alexander Monakov from comment #1) > GCC assumes the access is sufficiently aligned for an atomic object of > corresponding type I think that's only true for objects whose size corresponds to that of a fundamental type. Consider: struct B { char c[3]; }; Here, an atomic object of type B (eg, _Atomic(B) or std::atomic) would have size=4, align=4, and yet GCC treats B as having an alignment of 1 for the purpose of atomic accesses. Rather, GCC appears (from its external behavior) to consider only the object size and not the alignment for atomic accesses, and assumes power-of-2-sized objects to be aligned to their size (or to the maximum alignment of a fundamental type, whichever is lower). There exists code that assumes that GCC behaves as documented in this regard. For example, libc++'s std::atomic makes this assumption, and as a result, std::atomic is not atomic when using gcc with libc++. For that reason, changing GCC to avoid the unwarranted alignment assumption seems superior to me to updating the documentation to match the behavior. (For what it's worth, I recently fixed Clang to behave per the GCC documentation in this regard; Clang used to fall back to a libcall for the underaligned case, but would mistakenly call the "optimized" library routines that assume the object is sufficiently aligned.)
[Bug c++/59372] accepts-invalid with constexpr function pointer variable as non-type template argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59372 Richard Smith changed: What|Removed |Added Status|UNCONFIRMED |RESOLVED Resolution|--- |FIXED --- Comment #3 from Richard Smith --- Confirmed fixed.
[Bug c/87237] New: __atomic_load on 8-byte-sized, 1-byte-aligned struct is not atomic
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87237 Bug ID: 87237 Summary: __atomic_load on 8-byte-sized, 1-byte-aligned struct is not atomic 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: --- It's my understanding that __atomic_load is supposed to work for an essentially arbitrary TYPE, including the case where alignof(TYPE) < sizeof(TYPE). (From the documentation, "The four non-arithmetic functions (load, store, exchange, and compare_exchange) all have a generic version as well. This generic version works on any data type.") However: struct A { char c[4]; } *p, *q; void f() { __atomic_load(p, q, 5); } On x86_64, GCC emits f as a 'movl' from *p. That is not atomic if *p straddles two cache lines. libatomic's __atomic_load implementation gets this right, and falls back on a mutex in the case where the source straddles two cache lines, but GCC doesn't seem to realize it needs to call it.
[Bug c++/87097] New: value-initialization of an array of more than 1 element not treated as a constant initializer
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87097 Bug ID: 87097 Summary: value-initialization of an array of more than 1 element not treated as a constant initializer 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: --- Live testcase: https://godbolt.org/z/1JYWJS For posterity: struct A { constexpr A() : data() {} struct X { int n; }; X data[2]; }; static_assert((A(), true)); static_assert(A().data[0].n == 0); static_assert(A().data[1].n == 0); constexpr A x; GCC rejects this valid code with: :9:29: error: non-constant condition for static assertion 9 | static_assert(A().data[1].n == 0); | ~~^~~~ :9:29: error: accessing uninitialized member 'A::X::n' :10:13: error: 'A{A::X [2]{A::X{0}, A::X()}}' is not a constant expression 10 | constexpr A x; | Looks like GCC fails to evaluate the initializer of the second and subsequent elements of a value-initialized array during constant evaluation.
[Bug c/86983] New: documentation inconsistent with always_inline diagnostics for computed goto
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86983 Bug ID: 86983 Summary: documentation inconsistent with always_inline diagnostics for computed goto 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: --- Per https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html a function containing a computed goto can be inlined (so long as no label within it is used to initialize a static variable): > The & expressions for the same label might have different values if the > containing function is inlined or cloned. If a program relies on them being > always the same, __attribute__((__noinline__,__noclone__)) should be used to > prevent inlining and cloning. If & is used in a static variable > initializer, inlining and cloning is forbidden. However, applying __attribute__((__always_inline__)) to a function containing a computed goto produces this diagnostic: > error: function 'void* f(void*)' can never be inlined because it contains a > computed goto ... which claims that a computed goto prevents inlining. (See https://godbolt.org/g/XFhwQq) Also, GCC warns on returning the address of a label from a function, which makes sense if different invocations of the same function can have different addresses for their labels (through inlining / cloning), but is a false positive on an example such as the one at that godbolt.org link otherwise. So, which is it? Is GCC reserving the right to inline functions containing computed gotos in some future version? (In which case, the always_inline diagnostic is somewhere between misleading and wrong, and should probably be weakened from "can never be inlined" to something like "was not inlined".) Or has the computed goto rule been changed to "functions containing computed goto will never be inlined or cloned"? (In which case the documentation is wrong, and the warning on returning the address of a label seems questionable, at least for an enabled-by-default warning, since it warns on reasonable code and there doesn't seem to be a simple syntactic way to suppress the warning.)
[Bug c++/86849] g++ applies guaranteed copy elision to delegating construction, resulting in miscompiles
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86849 --- Comment #1 from Richard Smith --- Interestingly, GCC does appear to suppress guaranteed copy elision if the class has virtual base classes. Perhaps GCC's approach to this problem is to assume that a function returning a T by value cannot touch the tail padding of the T object if T is POD for the purpose of layout, and so the tail padding cannot be modified in the case where it's reusable by the enclosing object? (So we only have a problem in the case where a complete-object constructor and a base-subobject constructor would do different things, namely when the class has virtual base classes.) The trouble with that approach is that other compilers do store to the tail padding of T in a function returning T by value: https://godbolt.org/g/MM7Wvb ... and indeed the standard requires this behavior: http://eel.is/c++draft/dcl.init#6.2 "To zero-initialize an object or reference of type T means [...] if T is a (possibly cv-qualified) non-union class type, its padding bits (6.7) are initialized to zero bits [...]" (so arguably that's another bug in GCC's behavior: it should zero-initialize A's tail padding in the new example, but does not).
[Bug c++/86849] New: g++ applies guaranteed copy elision to delegating construction, resulting in miscompiles
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86849 Bug ID: 86849 Summary: g++ applies guaranteed copy elision to delegating construction, resulting in miscompiles 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: --- Live testcase: https://godbolt.org/g/AKn7j7 For posterity: #include struct A { A() {} A(int); ~A() {} int n; char k; }; A f(); A::A(int) : A(f()) {} A f() { A result; std::memset(, 0, sizeof(A)); return result; // (nrvo) } struct B { char x, y, z; }; struct X : A, virtual B { // B is in A's tail padding X() : B{1, 2, 3}, A(4) {} }; char test() { X x; return x.x; // should return 1 } Here, GCC uses f() to directly construct the A base class of the X object, and that tramples over A's tail padding (which contains the B virtual base class of X, which has already been initialized). It's not correct to apply guaranteed copy elision to a delegating construction, just like it's not correct to apply it to a base class construction -- not even in the C1 constructor variant, due to [[no_unique_address]].
[Bug c++/86769] g++ destroys condition variable in for statement too early
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86769 --- Comment #1 from Richard Smith --- For easy reproduction: https://godbolt.org/g/dfZFxz This does not appear to be a regression: this example appears to be miscompiled by every version of GCC back to at least 4.1.
[Bug c++/86769] New: g++ destroys condition variable in for statement too early
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86769 Bug ID: 86769 Summary: g++ destroys condition variable in for statement too early 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 X { ~X(); operator bool(); }; void f(X &); void g() { for (; X x = X(); f(x)); } GCC miscompiles this by destroying the 'x' variable before the call to 'f(x)'. Per C++ [stmt.for]p1, the above is equivalent to while (X x = X()) { f(x); } So the 'x' variable should be destroyed *after* the third operand of the for-statement is evaluated, not before.
[Bug c++/86049] Array bindings are not const when initializer is
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86049 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #2 from Richard Smith --- I think this is a bug in the standard. The cv-qualifiers of the array type should be discarded, as they would be for any normal auto deduction.
[Bug c++/76995] type-id/expression in cstyle-cast are disambiguated incorrectly
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=76995 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #2 from Richard Smith --- This code is valid, and GCC is incorrect to reject it (as is Clang and EDG, of course). The expression context (T()) is ambiguous: it could either be a C-style cast to the function type 'T()' or a parenthesized functional cast expression constructing an object of type 'T'. A correct parser is required to look at what follows the construct to figure out which of these two cases we're in: if the following tokens form a valid cast-expression, then it's an (ill-formed) cast to a function type. Otherwise, it's a parenthesized functional cast. The following tokens are (args...), which do not form a valid cast-expression, so the overall expression unambiguously parses the same as 'mytype()(args...)', rather than as a type cast. And for the record: I think this language rule is ridiculous. As far as I can determine, the only cases that result in this ambiguity involve a choice between a cast to a function type and something else; since a cast to a function type is not meaningful, we could -- and arguably should -- change the grammar to treat such cases as the non-cast interpretation. But I think that argues even more strongly that GCC is wrong to reject this.
[Bug c++/84414] miscompile due to assuming that object returned by value cannot alias its own member pointer values
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84414 --- Comment #2 from Richard Smith --- > Where does the scope of object A inside Foo begin and end? There is formally only one object. The object constructed in the return statement of Foo is simply the same object that is named 'a' within Bar. > Maybe it is time to file a DR to the C++ language folks about this case > if there is not one already. Hmm, the [class.temporary]/3 rule already gets very close to allowing this: "When an object of class type X is passed to or returned from a function, if each copy constructor, move constructor, and destructor of X is either trivial or deleted, and X has at least one non-deleted copy or move constructor, implementations are permitted to create a temporary object to hold the function parameter or result object. The temporary object is constructed from the function argument or return value, respectively, and the function’s parameter or return object is initialized as if by using the non-deleted trivial constructor to copy the temporary (even if that constructor is inaccessible or would not be selected by overload resolution to perform a copy or move of the object). [ Note: This latitude is granted to allow objects of class type to be passed to or returned from functions in registers. — end note ]" In fact, I think the *only* problem here is that the above rule does not allow the caller and the callee to observe the objects having the same address. I'll take this to the committee and see whether we can get that rule relaxed slightly. Would you be OK with this optimization only being permitted for the above class types (those that can be passed/returned in registers)?
[Bug c++/84414] New: miscompile due to assuming that object returned by value cannot alias its own member pointer values
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84414 Bug ID: 84414 Summary: miscompile due to assuming that object returned by value cannot alias its own member pointer values 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 CC: timshen at gcc dot gnu.org Target Milestone: --- GCC (all versions) miscompiles this code: struct A { A *children; long long arr[100]; A() : children() {} A(int) : children(this) {} }; __attribute__((noinline)) A Foo() { return A(0); } A x[3] = {}; void Bar(int n) { A a = Foo(); for (int i = 0; i < n; i++) { a.children[i].children = x; } } int main() { Bar(3); return x[0].children || !x[1].children || !x[2].children; } A correct compilation must return 0 from main, but GCC at -O2 returns 1. The reason is that it fails to reload 'a.children' on each iteration of the loop in 'Bar', reasoning (incorrectly) that the store to 'a.children[i].children' cannot alias 'a.children' because 'a' has not escaped. The above code has defined behavior in C++17, where the 'guaranteed copy elision' rules mean that the 'this' pointer inside the A::A(int) constructor points to the 'a' object inside 'Bar'. But since GCC chooses to perform copy elision on this code in all language modes (and always has done so), and the fact that it performed copy-elision is observable, this is not a C++17-specific bug. (The same miscompile can also be observed via NRVO.)
[Bug c++/60352] [C++11] Bogus "error: conflicting declaration 'auto i'"
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60352 --- Comment #3 from Richard Smith --- This bug still exists in GCC trunk.
[Bug c++/59930] template friend declarations, namespaces, and explicit instantiations don't mix
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59930 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #1 from Richard Smith --- Another example, without the explicit instantiation: namespace N { template class A { template friend struct B; private: int n; }; } template struct B { int f(N::A ai) { return ai.n; } }; int k = B().f({}); // incorrectly accepted It looks like when GCC instantiates a friend class template declaration, it incorrectly injects it into the global namespace (rather than the innermost enclosing namespace) if redeclaration lookup doesn't find some prior declaration of the class template to befriend. That would make at least bug#64816, bug#78724, and bug#81347 duplicates of this.
[Bug c++/81347] g++ confused by namespaces and friend classes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81347 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #4 from Richard Smith --- Duplicate of bug#59930 (friend class templates in class templates get injected into the global namespace instead of the innermost enclosing namespace)?
[Bug c++/64816] gcc claims that constructor is private when it should be accessible
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64816 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #5 from Richard Smith --- Possibly a duplicate of bug#59930? (It looks like class-scope friend class template declarations sometimes inject the class template into the wrong namespace, specifically if the template containing the friend is instantiated before the befriended template is declared.)
[Bug c++/78724] Incorrect ambiguous reference error when template class was forward declarated as a friend
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78724 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #1 from Richard Smith --- Probable duplicate of bug#59930 (friend class templates injected into wrong namespace).
[Bug c++/65157] Unable to define a static template member function of a nested class as a friend of a sibling class.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65157 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #2 from Richard Smith --- Clang is wrong; lookup for B::Create should fail because B is a dependent type, which is what happens in GCC and EDG. Adding this before 'main' crashes Clang: template<> class A::B {}; A::C c; (Internally, Clang is marking the friend declaration as invalid, but failing to actually produce a corresponding diagnostic.) Filed as bugs.llvm.org/PR35377.
[Bug c++/52130] missing check for matching underlying type during instantiation of enum member of class template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52130 --- Comment #3 from Richard Smith --- The diagnostic in #1 is not only wrong for this case, it's also a rejects-valid in the case where the underlying types match. I've filed https://gcc.gnu.org/PR81895 for that.
[Bug c++/81895] New: gcc rejects out-of-line definition of enum member of class template under -pedantic-errors
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81895 Bug ID: 81895 Summary: gcc rejects out-of-line definition of enum member of class template under -pedantic-errors Product: gcc Version: 7.2.1 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: --- g++ -std=c++11 -pedantic-errors has a rejects-valid on this: template struct S { enum class E : int; }; template enum class S::E : int { e }; S::E x = S::E::e; The bogus error is: error: 'enum S::E' is an enumeration template [-Wpedantic]
[Bug c++/81145] bogus "dereferencing type-punned pointer will break strict-aliasing rules" diagnostic with incomplete class type
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81145 --- Comment #5 from Richard Smith --- Yes, according to godbolt this occurs in GCC 4.4 - 7.1, but not in trunk. Unlike PR80593, it does not appear to be a GCC 7 regression, but it sure seems plausible that that change fixed it =)
[Bug c++/81145] bogus "dereferencing type-punned pointer will break strict-aliasing rules" diagnostic with incomplete class type
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81145 --- Comment #2 from Richard Smith --- I've tried a few things and not found any way to get wrong code. I think you're right that this is just a diagnostic issue.
[Bug c++/81145] New: bogus "dereferencing type-punned pointer will break strict-aliasing rules" diagnostic with incomplete class type
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81145 Bug ID: 81145 Summary: bogus "dereferencing type-punned pointer will break strict-aliasing rules" diagnostic with incomplete class type Product: gcc Version: 7.0.1 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 B { int n; }; struct A #ifndef BUG { B b; } #endif ; extern A a; int n = reinterpret_cast<B*>()->n; This produces a bogus "dereferencing type-punned pointer will break strict-aliasing rules" diagnostic with -DBUG, but correctly suppresses the warning when the definition of A is visible. Note that under C++ P0137R1 / DR1776, the A object is pointer-interconvertible with its b member, so the reinterpret_cast produces a usable pointer to a.b, regardless of whether the definition of A is visible. Perhaps GCC's TBAA should be less aggressive when comparing an incomplete type against (at least) a standard-layout type?
[Bug demangler/80513] demangler walks past trailing nul in mangled name in a bunch of cases
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80513 --- Comment #1 from Richard Smith --- While we're here, this check for overflow in consume_count is nonsense, and any decent optimising compiler is going to optimise away the overflow check: https://github.com/gcc-mirror/gcc/blob/master/libiberty/cplus-dem.c#L525 Testcase: $ echo '_Z4294967297x' | c++filt x Oops. It looks like item 2 in comment#0 was fixed recently (https://github.com/gcc-mirror/gcc/commit/b2dcfe3da47412480529c8591ba0433cd495fbe3) but item 1 is still live.
[Bug demangler/80513] New: demangler walks past trailing nul in mangled name in a bunch of cases
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80513 Bug ID: 80513 Summary: demangler walks past trailing nul in mangled name in a bunch of cases Product: gcc Version: 7.0.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: demangler Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Target Milestone: --- Example mangled name where demangler walks past two nuls: $ echo '__thunk_16\0_\0_3foo' | c++filt virtual function thunk (delta:-16) for foo::~foo(void) These are two separate bugs: 1) The gnu_special __thunk_ handling blindly assumes (without checking) that the byte after __thunk_ is an underscore, and skips it: else if (strncmp (*mangled, "__thunk_", 8) == 0) { int delta; (*mangled) += 8; delta = consume_count (mangled); if (delta == -1) success = 0; else { char *method = internal_cplus_demangle (work, ++*mangled); 2) The calls to "strchr (some_chars, mangled[i]) != NULL" throughout cplus-dem.c are all wrong, as they do not properly handle the case where mangled[i] is 0. (In that case, strchr returns a *non-null* pointer to the nul terminator of some_chars.)
[Bug c++/79668] New: [c++1z] inconsistent handling of parameter matching in template template arguments
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79668 Bug ID: 79668 Summary: [c++1z] inconsistent handling of parameter matching in template template arguments Product: gcc Version: 7.0.1 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: --- Consider the following: template<template typename> struct A; template typename> struct B; template struct C; A *ac; B<short, C> *bc; It should hopefully be clear that the type 'A' is valid if and only if the type 'B<short, C>' is valid. However, under -std=c++1z, GCC accepts 'A' but rejects 'B<short, C>': :5:11: error: type/value mismatch at argument 2 in template parameter list for 'template class > struct B' B<short, C> *bc; ^ :5:11: note: expected a template of type 'template class', got 'template struct C' Compiler exited with result code 1 Note that the above error is also the one produced outside C++1z mode, so perhaps whatever special handling is engaged for P0522R0 is missed in the case where the template template parameter is dependent? FWIW, Clang's implementation of P0522R0 accepts both cases.