[Bug c++/94227] New: ambiguous lookup for nested-name-specifier in using-declaration is not diagnosed

2020-03-19 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-03-23 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-03-24 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-03-24 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-03-24 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-04-12 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-04-14 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-04-20 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-05-29 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-05-29 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-05-29 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-06-04 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-06-10 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-06-15 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-07-13 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-08-06 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-08-13 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-08-19 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-08-25 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-08-26 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-08-26 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-08-31 Thread richard-gccbugzilla at metafoo dot co.uk
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

2019-10-21 Thread richard-gccbugzilla at metafoo dot co.uk
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

2019-10-29 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-01-28 Thread richard-gccbugzilla at metafoo dot co.uk
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

2020-01-30 Thread richard-gccbugzilla at metafoo dot co.uk
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

2013-03-04 Thread richard-gccbugzilla at metafoo dot co.uk


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

2013-03-09 Thread richard-gccbugzilla at metafoo dot co.uk


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

2012-10-27 Thread richard-gccbugzilla at metafoo dot co.uk


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

2013-05-20 Thread richard-gccbugzilla at metafoo dot co.uk
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

2013-05-20 Thread richard-gccbugzilla at metafoo dot co.uk
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 ..."

2013-05-23 Thread richard-gccbugzilla at metafoo dot co.uk
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

2013-06-07 Thread richard-gccbugzilla at metafoo dot co.uk
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

2013-06-27 Thread richard-gccbugzilla at metafoo dot co.uk
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)

2013-06-30 Thread richard-gccbugzilla at metafoo dot co.uk
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

2013-06-30 Thread richard-gccbugzilla at metafoo dot co.uk
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)

2013-07-20 Thread richard-gccbugzilla at metafoo dot co.uk
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

2013-08-07 Thread richard-gccbugzilla at metafoo dot co.uk
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

2013-08-09 Thread richard-gccbugzilla at metafoo dot co.uk
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

2013-09-05 Thread richard-gccbugzilla at metafoo dot co.uk
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

2011-11-03 Thread richard-gccbugzilla at metafoo dot co.uk
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

2011-11-03 Thread richard-gccbugzilla at metafoo dot co.uk
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

2012-06-04 Thread richard-gccbugzilla at metafoo dot co.uk
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

2012-02-01 Thread richard-gccbugzilla at metafoo dot co.uk
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

2012-02-03 Thread richard-gccbugzilla at metafoo dot co.uk
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

2012-02-05 Thread richard-gccbugzilla at metafoo dot co.uk
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

2012-02-13 Thread richard-gccbugzilla at metafoo dot co.uk
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

2013-11-11 Thread richard-gccbugzilla at metafoo dot co.uk
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

2013-11-13 Thread richard-gccbugzilla at metafoo dot co.uk
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

2013-11-13 Thread richard-gccbugzilla at metafoo dot co.uk
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

2013-12-02 Thread richard-gccbugzilla at metafoo dot co.uk
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

2013-12-02 Thread richard-gccbugzilla at metafoo dot co.uk
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

2013-12-09 Thread richard-gccbugzilla at metafoo dot co.uk
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

2013-12-10 Thread richard-gccbugzilla at metafoo dot co.uk
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

2014-01-03 Thread richard-gccbugzilla at metafoo dot co.uk
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

2011-12-05 Thread richard-gccbugzilla at metafoo dot co.uk
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

2011-12-13 Thread richard-gccbugzilla at metafoo dot co.uk
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

2018-12-11 Thread richard-gccbugzilla at metafoo dot co.uk
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

2019-01-22 Thread richard-gccbugzilla at metafoo dot co.uk
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

2018-04-15 Thread richard-gccbugzilla at metafoo dot co.uk
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

2018-06-05 Thread richard-gccbugzilla at metafoo dot co.uk
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)

2019-08-12 Thread richard-gccbugzilla at metafoo dot co.uk
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'"

2017-12-08 Thread richard-gccbugzilla at metafoo dot co.uk
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

2019-03-05 Thread richard-gccbugzilla at metafoo dot co.uk
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

2019-03-18 Thread richard-gccbugzilla at metafoo dot co.uk
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

2019-04-15 Thread richard-gccbugzilla at metafoo dot co.uk
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()

2019-04-26 Thread richard-gccbugzilla at metafoo dot co.uk
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()

2019-04-26 Thread richard-gccbugzilla at metafoo dot co.uk
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

2019-06-08 Thread richard-gccbugzilla at metafoo dot co.uk
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

2019-06-09 Thread richard-gccbugzilla at metafoo dot co.uk
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

2019-06-14 Thread richard-gccbugzilla at metafoo dot co.uk
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

2019-06-20 Thread richard-gccbugzilla at metafoo dot co.uk
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

2018-07-31 Thread richard-gccbugzilla at metafoo dot co.uk
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

2018-07-31 Thread richard-gccbugzilla at metafoo dot co.uk
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

2018-08-03 Thread richard-gccbugzilla at metafoo dot co.uk
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

2018-08-06 Thread richard-gccbugzilla at metafoo dot co.uk
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

2018-08-16 Thread richard-gccbugzilla at metafoo dot co.uk
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

2018-08-24 Thread richard-gccbugzilla at metafoo dot co.uk
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

2018-09-05 Thread richard-gccbugzilla at metafoo dot co.uk
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

2018-09-05 Thread richard-gccbugzilla at metafoo dot co.uk
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

2018-09-11 Thread richard-gccbugzilla at metafoo dot co.uk
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

2018-09-11 Thread richard-gccbugzilla at metafoo dot co.uk
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

2018-02-15 Thread richard-gccbugzilla at metafoo dot co.uk
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

2018-02-15 Thread richard-gccbugzilla at metafoo dot co.uk
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

2018-12-05 Thread richard-gccbugzilla at metafoo dot co.uk
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

2012-11-14 Thread richard-gccbugzilla at metafoo dot co.uk


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

2013-01-30 Thread richard-gccbugzilla at metafoo dot co.uk


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++

2016-02-10 Thread richard-gccbugzilla at metafoo dot co.uk
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++

2016-02-11 Thread richard-gccbugzilla at metafoo dot co.uk
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

2016-06-07 Thread richard-gccbugzilla at metafoo dot co.uk
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

2016-06-08 Thread richard-gccbugzilla at metafoo dot co.uk
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

2017-08-18 Thread richard-gccbugzilla at metafoo dot co.uk
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

2017-08-18 Thread richard-gccbugzilla at metafoo dot co.uk
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

2017-04-24 Thread richard-gccbugzilla at metafoo dot co.uk
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

2017-04-25 Thread richard-gccbugzilla at metafoo dot co.uk
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

2017-06-20 Thread richard-gccbugzilla at metafoo dot co.uk
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

2017-06-20 Thread richard-gccbugzilla at metafoo dot co.uk
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

2017-06-20 Thread richard-gccbugzilla at metafoo dot co.uk
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

2017-01-06 Thread richard-gccbugzilla at metafoo dot co.uk
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

2017-02-01 Thread richard-gccbugzilla at metafoo dot co.uk
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.)

  1   2   >