[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 &f(); } namespace N2 { struct N1 { float &f(); }; } using namespace N2; int &r = 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 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 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] 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 #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 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 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++/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++/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++/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 #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++/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/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++/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++/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++/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++/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++/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/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/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] "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++/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++/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 &g() { return n; } struct X { int &get(); }; }; return Y::X(); }; using X = decltype(f()); int &X::get() { return g(); }
[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] 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++/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/56528] New: __attribute__((visibility)) ignored for a function declaration with an asm label
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56528 Bug #: 56528 Summary: __attribute__((visibility)) ignored for a function declaration with an asm label Classification: Unclassified Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassig...@gcc.gnu.org ReportedBy: richard-gccbugzi...@metafoo.co.uk Adding an asm label attribute to a function declaration with a visibility attribute causes the visibility attribute to be ignored: $ echo 'void f() __attribute__((visibility("hidden"))); void g() { f(); }' | gcc -x c - -S -o - | grep hidden .hidden f $ echo 'void f() __asm__("f") __attribute__((visibility("hidden"))); void g() { f(); }' | gcc -x c - -S -o - | grep hidden $
[Bug c++/56582] New: ICE on negative array index in C++11 constant expression evaluation
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56582 Bug #: 56582 Summary: ICE on negative array index in C++11 constant expression evaluation Classification: Unclassified Product: gcc Version: 4.8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: richard-gccbugzi...@metafoo.co.uk The C++ expression evaluator is not checking for negative array indices when indexing string literals. This leads to ICEs and reading arbitrary memory within the GCC process: // Reliable ICE constexpr int n[3] = {}; constexpr int k = n[-1]; // Some random byte constexpr char c = "foo"[-1000];
[Bug c++/54526] [C++11] <:: is incorrectly treated as digraph <: followed by colon
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54526 --- Comment #4 from Richard Smith 2012-10-28 05:21:40 UTC --- The fix does not appear to be correct. C++11 changed the lexing rules, not the parsing rules for template argument lists. For instance, this is valid in C++11: int a; bool b = 0<::a;
[Bug c++/36486] g++ accepts code with ambiguous overloading
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36486 Richard Smith changed: What|Removed |Added Status|UNCONFIRMED |RESOLVED Resolution|--- |INVALID --- Comment #5 from Richard Smith --- N3281 changed the rules such that g++ is now correct.
[Bug c++/57346] New: g++ prematurely rejects references to local variables that are not odr-uses from local classes inside templates
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57346 Bug ID: 57346 Summary: g++ prematurely rejects references to local variables that are not odr-uses from local classes inside templates Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk g++ has a rejects-valid on this: template int f() { T n = 0; struct X { int get() { return n; } } x; return x.get(); } This template definition is valid: instantiation should succeed with T=const int, for instance.
[Bug c++/57319] [4.8 Regression]: bogus "defaulted move assignment for ... calls a non-trivial move assignment operator for virtual base ..."
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57319 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #5 from Richard Smith --- (In reply to Jason Merrill from comment #1) > (In reply to Paul Pluzhnikov from comment #0) > > However, this particular case *isn't* the problematic case, because > > (a) this sample code should not trigger the definition of C's move > > assignment operator, and > > True, the warning is given at declaration time; it would be possible to move > the warning to when the move assignment is used, but that might mean design > errors don't get caught until later. OK, that makes sense. However, delaying the check until the operator= is lazily declared does not fully achieve this goal. Could the check be performed at the end of the definition of class C (rather than, presumably, when looking for a virtual C::operator= for D::operator= to override)? > > (b) there is only one inheritance path from C to B, so it won't be > > move-assigned multiple times, and > > True, the warning is given at the point of first virtual derivation rather > than when it appears in a diamond-shaped hierarchy. But the purpose of > virtual derivation is to support diamond-shaped hierarchies, so again it > seems appropriate to warn sooner rather than later. OK. The class which brings together the diamond may provide a move assignment operator which does not blindly call the move assignment operators on the base classes, so this can still have some false positives even if every virtual base is involved in diamond inheritance.
[Bug c++/57566] New: [C++11][constexpr] static temporaries bound recursively in reference constant expressions don't get initialized
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57566 Bug ID: 57566 Summary: [C++11][constexpr] static temporaries bound recursively in reference constant expressions don't get initialized Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk If a temporary is lifetime-extended by being bound to a reference within a lifetime-extended temporary, and the complete initializer is a constant expression, the outer temporary does not get initialized and the inner temporary does not get emitted. Example: struct S { int &&a; int b; }; S &&s = { 123, 456 }; GCC emits: .local _ZGR1s0 .comm _ZGR1s0,16,16 .globl s .bss .align 8 .type s, @object .size s, 8 s: .zero 8 GCC emits code to dynamically initialize 's.a' to the address of _ZGR1s0. GCC does not emit any code to initialize _ZGR1s0 itself, nor to initialize s.b. Both s and the temporaries should be emitted as constants.
[Bug c++/57745] New: missing recursive lifetime extension within std::initializer_list
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57745 Bug ID: 57745 Summary: missing recursive lifetime extension within std::initializer_list Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Consider: #include struct A { A() { std::cout << " A()" << std::endl; } ~A() { std::cout << "~A()" << std::endl; } }; struct B { const A &a; ~B() { std::cout << "~B()" << std::endl; } }; struct C { std::initializer_list b; ~C() { std::cout << "~C()" << std::endl; } }; int main() { const C &c = C{ { { A() }, { A() } } }; std::cout << "-" << std::endl; } This should print: A() A() - ~C() ~B() ~A() ~B() ~A() ... but g++ destroys the two A temporaries at the end of the full-expression. They are lifetime-extended because they are bound to B::a references in the aggregate-initialization of the B subobjects of the underlying array of the initializer_list, which is itself lifetime-extended.
[Bug c++/55425] constexpr does not work in many situations (both built-in and user supplied literals)
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55425 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #6 from Richard Smith --- (In reply to Jonathan Wakely from comment #1) > The standard says __func__ is a function-local variable, defined as if by > > constexpr const char* x() { > static const char __func__[] = "function-name "; > return __func__; > } > > Clearly this is not a valid constexpr function. > Changing this would be an extension. I disagree with this. The standard doesn't say __func__ is only predefined if it is used, so if this argument held then all constexpr functions would be invalid.
[Bug c++/57588] [C++11] static constexpr in class fails to link
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57588 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #7 from Richard Smith --- (In reply to Jonathan Wakely from comment #6) > (In reply to Daniel Krügler from comment #4) > > I don't think that this correct here (In C++11 the rules became relaxed). > > It was post-C++11, but as a DR we should implement it, and I see you're > right, the initialization of int_ uses the lvalue-to-rvalue conversion > immediately so it isn't odr-used. The mem-initializer in question is "int_(kLiteral)", or after performing overload resolution, "int_(kLiteral.operator int())". This is an odr-use of kLiteral, therefore a definition is required. There is no lvalue-to-rvalue conversion here; 'Literal::operator int' returns an rvalue (and in any case, kLiteral is not in the set of potential results of the expression).
[Bug c++/57942] g++-4.8.1 tries to instantiate wrong constructor (C++11)
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57942 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #1 from Richard Smith --- Reduced to: template struct S { typename T::error type; }; struct X {}; void f(S *); void f(...); void g() { f((X*)0); } It looks like, when considering a conversion from A* to B*, where A is a class type, gcc attempts to complete B. There seems to be no obvious justification for this (it doesn't help in determining whether B is a base class of A, which seems like the most likely explanation for this behavior).
[Bug c++/58102] New: rejects valid initialization of constexpr object with mutable member
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58102 Bug ID: 58102 Summary: rejects valid initialization of constexpr object with mutable member Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Given struct S { mutable int n; constexpr S() : n() {} }; GCC correctly accepts: constexpr S s {}; but incorrectly rejects: constexpr S s = {}; saying: : At global scope: :5:20: error: ‘const S’ cannot be the type of a complete constant expression because it has mutable sub-objects Per core issue 1405, both the above cases are valid.
[Bug c++/52036] C++11 allows template parameters to have internal linkage
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52036 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #8 from Richard Smith --- C++11 [temp.arg.nontype]p2 has another similar testcase, which GCC fails on: template class X { /* ... */ }; X x1; // error: string literal as template-argument const char p[] = "Vivisectionist"; X x2; // OK
[Bug c++/58328] [C++11] bogus: error: constructor required before non-static data member for
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58328 Richard Smith changed: What|Removed |Added CC||jason at gcc dot gnu.org, ||richard-gccbugzilla@metafoo ||.co.uk --- Comment #3 from Richard Smith --- This is in the area of a core language defect, and IIRC CWG hasn't really decided which cases should be valid. Clang accepts the code in comment#2 but rejects the code in comment#0 because, in comment#0, 'A::B::B()' is constexpr, so Clang triggers the computation of the implicit exception specification of 'A::B::B()' earlier (before the default initializer for 'A::B::y' is parsed). It seems that g++ more eagerly computes the exception specification for 'A::B::B()'. That seems more in line with the resolution of core issue 1330, which suggests to me that we should trigger the computation of the exception specification when we parse the 'B()' expression, so I'm inclined to say that Clang is in error in accepting the code in comment#2.
[Bug c++/32534] gcc fails to initialize template's static data members before their use in some cases
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=32534 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla at ||metafoo dot co.uk --- Comment #5 from Richard Smith 2011-11-03 18:26:57 UTC --- This does not look like a valid bug: static data members of class template instantiations have unordered initialization, so gcc is permitted to initialize B::a after it initializes c.
[Bug c++/50986] New: weak static data members with constant initializers emitted in .rodata, leading to segfault on startup
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50986 Bug #: 50986 Summary: weak static data members with constant initializers emitted in .rodata, leading to segfault on startup Classification: Unclassified Product: gcc Version: 4.6.3 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: richard-gccbugzi...@metafoo.co.uk It's possible for a weak variable K (either a static data member of a class template or a static variable in an inline function) to have a constant initializer in one translation unit (call it TU1) and a non-constant initializer in another translation unit (call it TU2), without an ODR violation. This can happen, for instance, if the initializer for an extern const int X whose value is used in K's initializer is visible in one TU but not the other. In this case, in TU1, g++ uses static initialization and puts the variable in .rodata. In TU2, it uses dynamic initialization. If these TUs are linked together in the wrong order, the linker will put the variable in .rodata but the binary will still try to dynamically initialize it. This causes the program to segfault on startup (trying to write to read-only memory). Testcase: $ cat repro.cpp struct S { static const int x; }; template struct U { static const int k; }; #ifdef TU1 const int S::x = 42; #endif template const int U::k = T::x; #ifdef TU1 extern const int *f(); const int *g() { return &U::k; } int main() { return *f() + U::k; } #endif #ifdef TU2 const int *f() { return &U::k; } #endif $ g++ repro.cpp -DTU1 -c -o tu1.o $ g++ repro.cpp -DTU2 -c -o tu2.o $ g++ tu1.o tu2.o $ ./a.out Segmentation fault clang has the same issue (which is how this was discovered), and the current proposed solution there is to never put weak constants in .rodata.
[Bug libstdc++/53578] New: include/ext/concurrence.h relies on ill-formed narrowing conversions
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53578 Bug #: 53578 Summary: include/ext/concurrence.h relies on ill-formed narrowing conversions Classification: Unclassified Product: gcc Version: 4.7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: richard-gccbugzi...@metafoo.co.uk >From around line 271 of ext/concurrence.h: // matches a gthr-win32.h recursive mutex template static typename __enable_if::__type _S_destroy(_Rm* __mx) This SFINAE device doesn't work in Clang in C++11 mode, because the sizeof expression evaluates to a value greater than one, and thus the implicit conversion to bool for the first template parameter is a narrowing conversion. I assume g++ will hit this too once it adds support for the narrowing check in converted constant expressions.
[Bug c++/50986] weak static data members with constant initializers emitted in .rodata, leading to segfault on startup
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50986 --- Comment #2 from Richard Smith 2012-02-01 21:14:35 UTC --- As noted in comment#0, I believe there is no ODR violation here. Each definition of U::k consists of the same sequence of tokens, every name refers to the same entity in both definitions, and none of the other provisions of [basic.def.odr]p5 applies. After some discussion, the proposed approach in clang is (roughly) to always generate a guard variable (initialized to 1 for a statically-initialized variable), and to put the variable and its guard variable in the same COMDAT group. Full details are in this thread: http://lists.cs.uiuc.edu/pipermail/cfe-dev/2011-November/018816.html
[Bug libstdc++/52119] numeric_limits::min() is not a constant expression
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52119 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla at ||metafoo dot co.uk --- Comment #1 from Richard Smith 2012-02-04 02:12:41 UTC --- In more detail: Under the C++11 FDIS, this is not a (core) constant expression due to the "— a result that is not mathematically defined or not in the range of representable values for its type;" bullet in [expr.const]p2. Under DR1313, that rule is generalized to all undefined behavior. And a constexpr function which can't produce a constant expression is ill-formed by [dcl.constexpr]p5.
[Bug c++/52130] New: missing check for matching underlying type during instantiation of enum member of class template
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52130 Bug #: 52130 Summary: missing check for matching underlying type during instantiation of enum member of class template Classification: Unclassified Product: gcc Version: 4.7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: richard-gccbugzi...@metafoo.co.uk g++ incorrectly accepts this code in c++11 mode: template struct S { enum E : int; }; template enum S::E : T { e }; S::E x = S::e;
[Bug c++/52119] numeric_limits::min() is not a constant expression
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52119 --- Comment #8 from Richard Smith 2012-02-13 22:17:27 UTC --- Signed left shift which overflows the corresponding unsigned type is still undefined, so g++ should reject this: constexpr int n = 2 << 31;
[Bug c++/58752] [C++11] Bogus error: ambiguous class template instantiation
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58752 --- Comment #7 from Richard Smith --- (In reply to Daniel Krügler from comment #6) > (In reply to Richard Smith from comment #4) > Richard, could you please explain what precisely you meant with: > > "Deducing #1 from #2 gives T=const U, which results in a deduction failure > because enable_if<...const U...>::type is not 'void'." > > ? "U" is an arbitrary dependent type here, so "enable_if<...const U...>::type" is dependent, and is not the same type as "void". Partial ordering does not consider the actual types deduced for the use of the template, so we don't know that U = char.
[Bug c++/59056] enable_if turns a non-ambiguous template into an ambiguous one
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59056 --- Comment #5 from Richard Smith --- (In reply to Jonathan Wakely from comment #2) > I thought if the partial specializations were ambiguous then these function > overloads should be too. Yes, this inconsistency is very surprising. GCC, EDG, and Clang all behave the same way, and yet I can find no justification for this behavior in the standard. Morally, the function call should be ambiguous. The first 'func' takes Bar for any X where check() is true, and the second 'func' takes Bar for any X that matches Foo. Neither of those constraints implies the other, so the call should be ambiguous. In Clang's case, the problem is that we fail to enforce [temp.deduct.type](14.8.2.5)/1 when partially ordering function templates -- we don't check that deduction actually succeeded in finding types that make 'A' match the 'deduced A' -- but we do check that when partially ordering class templates, and we don't spot the problem earlier because the enable_if<...> is a non-deduced context. I expect EDG and GCC have a similar bug.
[Bug c++/59056] ambiguous call to function template overloads not diagnosed
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59056 --- Comment #8 from Richard Smith --- (In reply to Walter Mascarenhas from comment #7) > In itself, Richard's paragraph "Morally, the function should ambiguous... " > implies that the code below is ambiguous. However, it > compiles just fine with gcc 4.8.1, because gcc also takes into > account the information that check< Foo >() is false > in order to discard the specialization with the enable_if. In > other words, the X in check is not completely arbitrary, > it my be related to Foo. GCC can't instantiate check with a dependent type Ty, because that's not a meaningful thing to do. And it's not allowed to use Foo, because partial ordering of templates does not depend on the actual deduced arguments for the template specialization (it orders the templates themselves, not their specializations). Also, the only available definition of check always returns true. So I really don't see how that could be the case.
[Bug c++/59372] New: accepts-invalid with constexpr function pointer variable as non-type template argument
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59372 Bug ID: 59372 Summary: accepts-invalid with constexpr function pointer variable as non-type template argument Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Consider: void f() {} template struct X {}; template struct Y {}; constexpr void (*p)() = &f; X a; constexpr void (*h())() { return &f; } X b; constexpr void (&q)() = f; X c; constexpr void (&i())() { return f; } X d; GCC correctly rejects the types of 'b', 'c', and 'd', but fails to reject 'a'. All four are ill-formed by 14.3.2/1. In particular, a non-type template argument for a parameter of pointer type must be either a null pointer, the name of a non-type template-parameter, or an expression of the form '& id-expression', and the '&' can only be omitted if the id-expression names a function or array. (See also the discussion for core issue 1570, where this direction was reaffirmed.)
[Bug c++/59372] accepts-invalid with constexpr function pointer variable as non-type template argument
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59372 --- Comment #1 from Richard Smith --- (In reply to Richard Smith from comment #0) > X c; > X d; Sorry, transcription error, these should be 'Y', not 'X'.
[Bug c++/59426] __has_trivial_{copy/assign} behavior differs from documentation
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59426 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #2 from Richard Smith --- Which C++11 semantics? Is __has_trivial_copy(T) intended to determine: 1) if T has a trivial copy constructor, or 2) whether T has a trivial copy constructor and no non-trivial copy constructor, or 3) whether the constructor selected to perform a copy from a 'const T' lvalue would be trivial, or 4) the value of std::is_trivially_copyable::value?
[Bug c++/59465] New: g++ allows direct-initialization of an array of class type from another array in a mem-initializer
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59465 Bug ID: 59465 Summary: g++ allows direct-initialization of an array of class type from another array in a mem-initializer Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk Reduced testcase: struct string {} a[1]; struct pair { string s[1]; pair() : s(a) {} }; This is ill-formed, but g++ accepts it. The initialization is rejected if we try to direct-initialize a non-member array this way, or if 'string' is replaced by a non-class type, so I assume this is a bug rather than a deliberate extension.
[Bug c++/59673] New: wrong specialization used when a partial specialization of a member template is explicitly specialized
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59673 Bug ID: 59673 Summary: wrong specialization used when a partial specialization of a member template is explicitly specialized Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk GCC rejects this: template struct X { template struct Y; template struct Y { int x; }; // #1 template struct Y { int y; }; }; template<> template struct X::Y { int z; }; // #2 int a = X::Y().z; ... because it uses #1, not #2, when instantiating X::Y.
[Bug c++/51433] New: constexpr caching leads to incorrect dynamic initialization
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51433 Bug #: 51433 Summary: constexpr caching leads to incorrect dynamic initialization Classification: Unclassified Product: gcc Version: 4.6.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: richard-gccbugzi...@metafoo.co.uk Testcase: constexpr int f(); constexpr int g() { return f(); } extern const int n = g(); constexpr int f() { return 42; } extern const int m = g(); g++ uses dynamic initialization for both m and n. Static initialization is required to be used for m. We can upgrade this to a rejects-valid: int arr[m]; // error!
[Bug c++/51541] New: ICE on ill-formed alias template declarations
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51541 Bug #: 51541 Summary: ICE on ill-formed alias template declarations Classification: Unclassified Product: gcc Version: 4.7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: richard-gccbugzi...@metafoo.co.uk The following tests from clang's alias templates testsuite all cause g++ svn to ICE: template using ::T = void(int n); template using operator int = void(int n); template using typename U = void; template using typename ::V = void(int n); template using typename ::operator bool = void(int n); tmp.cpp:1:28: internal compiler error: in make_id_declarator, at cp/parser.c:1270
[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++/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 &&r = 0; int *p = &r; 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++/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++/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++/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++/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++/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++/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++/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 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 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 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 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++/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++/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++/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++/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++/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(&result, 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++/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/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 &&foo 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 &&foo 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++/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/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++/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 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 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 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++/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/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 libstdc++/53841] [C++11] condition_variable::wait_until() fails with high resolution clocks
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53841 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla at ||metafoo dot co.uk --- Comment #3 from Richard Smith 2012-11-14 23:06:07 UTC --- This code has more problems with duration conversions: // DR 887 - Sync unknown clock to known clock. const typename _Clock::time_point __c_entry = _Clock::now(); const __clock_t::time_point __s_entry = __clock_t::now(); const chrono::nanoseconds __delta = __atime - __c_entry; const __clock_t::time_point __s_atime = __s_entry + __delta; The last line attempts to implicitly convert from time_point<[...], nanoseconds> to system_clock::time_point, which may be in microseconds or even in seconds. Suggested fix: -const chrono::nanoseconds __delta = __atime - __c_entry; -const __clock_t::time_point __s_atime = __s_entry + __delta; +const auto __delta = __atime - __c_entry; +const auto __s_atime = __s_entry + __delta; Clang trunk currently rejects this code (prior to instantiation, even) due to this invalid conversion if _GLIBCXX_USE_CLOCK_REALTIME is not defined (as seems to be the case on several popular linux distributions).
[Bug libstdc++/56158] New: bad enum values computed by operator~ in ios_base.h
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56158 Bug #: 56158 Summary: bad enum values computed by operator~ in ios_base.h Classification: Unclassified Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: richard-gccbugzi...@metafoo.co.uk The overloaded operator~s defined for the enumerations in ios_base.h have the following form: Enum operator~(Enum e) { return Enum(~static_cast(e)); } The ~ creates values outside the range of values of the enumeration type, so the cast back to the Enum type has an unspecified value (see [expr.static.cast]p10), and in practice it produces an Enum value outside the range of representable values for the Enum type, so behavior is undefined. Fix: --- include/bits/ios_base.h +++ include/bits/ios_base.h @@ -87,7 +87,7 @@ inline _GLIBCXX_CONSTEXPR _Ios_Fmtflags operator~(_Ios_Fmtflags __a) - { return _Ios_Fmtflags(~static_cast(__a)); } + { return _Ios_Fmtflags(static_cast(__a) ^ static_cast(_S_ios_fmtflags_end - 1)); } inline const _Ios_Fmtflags& operator|=(_Ios_Fmtflags& __a, _Ios_Fmtflags __b) @@ -127,7 +127,7 @@ inline _GLIBCXX_CONSTEXPR _Ios_Openmode operator~(_Ios_Openmode __a) - { return _Ios_Openmode(~static_cast(__a)); } + { return _Ios_Openmode(static_cast(__a) ^ static_cast(_S_ios_openmode_end - 1)); } inline const _Ios_Openmode& operator|=(_Ios_Openmode& __a, _Ios_Openmode __b) @@ -165,7 +165,7 @@ inline _GLIBCXX_CONSTEXPR _Ios_Iostate operator~(_Ios_Iostate __a) - { return _Ios_Iostate(~static_cast(__a)); } + { return _Ios_Iostate(static_cast(__a) ^ static_cast(_S_ios_iostate_end - 1)); } inline const _Ios_Iostate& operator|=(_Ios_Iostate& __a, _Ios_Iostate __b)
[Bug c++/69763] New: _Alignof(double) in C gives different results from alignof(double) in C++
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69763 Bug ID: 69763 Summary: _Alignof(double) in C gives different results from alignof(double) in C++ Product: gcc Version: 6.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: --- See also bug 52023. On i386, according to GCC we have _Alignof(double) == 4, but according to G++ we have alignof(double) == 8. This makes no sense, as the same words are used to specify the semantics in both languages, and this creates a gratuitous incompatibility between GCC's C and C++ modes.
[Bug c++/69763] _Alignof(double) in C gives different results from alignof(double) in C++
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69763 --- Comment #3 from Richard Smith --- I'm pretty sure neither the C nor C++ committees intended for alignof(T) to give different results in the different languages. And even with the rule in [basic.align]p2, GCC can still choose to specify that the alignment requirement of 'double' is 4 in C++, to make its C and C++ modes agree. (It's not wrong to align a double to 4 bytes, even though GCC would prefer to 8-byte align it when it can.)
[Bug c++/57433] Local classes have an associated namespace
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57433 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #3 from Richard Smith --- (In reply to i.hamsa from comment #2) > This is an expected behaviour in C++14 due to > http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1690. Still a > problem in C++11. That issue is in DR status, so it seems appropriate for the resolution to apply to C++11 (and C++98) as well.
[Bug c++/57745] missing recursive lifetime extension within std::initializer_list
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57745 --- Comment #3 from Richard Smith --- Yes, this is now fixed; the remaining difference is a defect in the standard.
[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++/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 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 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 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(&a)->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 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] 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++/78966] Unjustified variadic template instantiation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78966 Richard Smith changed: What|Removed |Added CC||richard-gccbugzilla@metafoo ||.co.uk --- Comment #5 from Richard Smith --- The vari in f is a non-deduced context because the corresponding argument is an overloaded function that cannot be resolved. The pack T can't be deduced, so it is inferred to be an empty pack. Here's another case that needs the above rules in order to work: template struct X {}; template struct vari { vari(void(*)(X)); }; template void f(vari); template void g(X); void h() { f(g); } // 'f' is equivalent to 'f<>'; T is an empty pack
[Bug c++/79329] New: bogus operator delete access check during instantiation of new-expression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79329 Bug ID: 79329 Summary: bogus operator delete access check during instantiation of new-expression 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 A { A(); void *operator new(unsigned long, void*); private: void operator delete(void*, int); }; A *p = new (p) A; gives a bogus diagnostic: :7:16: error: 'static void A::operator delete(void*, int)' is private within this context A *p = new (p) A; ^ :5:8: note: declared private here void operator delete(void*, int); ^~~~ Adding a second irrelevant operator delete overload suppresses the diagnostic. (Perhaps the access check is being performed prior to filtering out non-matching operator delete functions in the case where the lookup result is not an overload set.)