[Bug c++/110958] New: [CWG 2137][accepts-invalid] Copy-list-initialization with single element of same class only considers converting constructors as viable

2023-08-09 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110958

Bug ID: 110958
   Summary: [CWG 2137][accepts-invalid] Copy-list-initialization
with single element of same class only considers
converting constructors as viable
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: davveston at gmail dot com
  Target Milestone: ---

There are several (closed) bug reports relating to CWG 2137, particularly
highlighting the still present implementation divergence between e.g. GCC and
Clang. These mostly relate to whether or not a non-aggregate class initialized
via single element init-list of same-class resolves to the rules of
[over.match.list] or not. See e.g.
https://gcc.gnu.org/bugzilla//show_bug.cgi?id=85577 and its duplicates

I interpret the wording the same way as GCC, such that after CWG 2137
initializer list constructors take precedence over e.g. copy constructors
([over.match.list]/1.1).

However, when falling through to [over.match.list]/1.2, GCC seems to consider
only converting constructors as if following [over.match.ctor]/1, whereas by
[over.match.list]/1.2 explicit constructors are still viable, although leading
to an ill-formed program if picked as most viable. 

The following example is accepted by GCC:

struct S {
  S()= default;
  S(S const&)= default; // #1
  explicit S(S&) = delete;  // #2
};

S a; 
S b = {a}; // #3

As #3 picks #1 for the copy-list-initialization. As of CWG 2137 I believe it
should be rejected as ill-formed as #2 should be selected instead: ill-formed
not due to deleted definition but due to the last paragraph of
[over.match.list]/1.

(Holds for various GCC versions and C++ language versions).

[Bug c++/98822] Rejects-valid: instantiation of class template instantiates (all) constrained non-template friend definitions (, even those) with unsatisfied constraints

2022-06-02 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98822

--- Comment #3 from David Friberg  ---
I believe the current wording doesn't cover what should happen when
instantiating a constrained non-template (hidden) friend, particularly
instantiation of constrained (hidden) friends whose requires-clauses are not
satisfied for the particular enclosing class template specialization being
instantiated. 

I haven't found an open DR for this, though, so I've posted
https://github.com/cplusplus/CWG/issues/47.

Moreover, the Itanium C++ ABI currently not allowing unambiguously mangling
these kind of friends. See
https://github.com/itanium-cxx-abi/cxx-abi/issues/24#issuecomment-934713719.

[Bug c++/99699] Type deduction failure for deducing a non-type template parameter via another deducible structural type (class template specialization) non-type template parameter

2022-04-07 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99699

--- Comment #1 from David Friberg  ---
This seems to have been fixed on trunk/GCC 12:
https://wandbox.org/permlink/qq207mBL7q5ndRgS

[Bug c++/104996] New: Overload resolution over rvalue/const lvalue array reference parameters for an init. list argument incorrectly picks the const lvalue ref. overload

2022-03-21 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104996

Bug ID: 104996
   Summary: Overload resolution over rvalue/const lvalue array
reference parameters for an init. list argument
incorrectly picks the const lvalue ref. overload
   Product: gcc
   Version: 11.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: davveston at gmail dot com
  Target Milestone: ---

GCC, MSVC and Clang all agrees and picks the rvalue overload for these two
examples:

 #include 

 // #g.1: rvalue reference function parameter
 constexpr bool g(int&&)   { return true; }

 // #g.2: const lvalue reference function parameter
 constexpr bool g(int const&)  { return false; }

 static_assert(g(0), ""); // OK: all compilers agree

 // #f.1: rvalue ref overload
 template
 constexpr bool f(int (&&)[size])  { return true; }

 // #f.2: lvalue ref overload
 template
 constexpr bool f(int const (&)[size]) { return false; }

 template
 using type = T;

 static_assert(f(type{1, 2, 3})); // OK: all compilers agree.

As expected, as per
https://timsong-cpp.github.io/cppwp/n4868/over.ics.rank#3.2.3.

However for a call to the `f` overloads with an initializer list argument GCC
picks the lvalue ref overload #f.2 whereas Clang and MVSC picks the rvalue ref
overload #f.1.

Afaict Clang and MSVC are correct, as per
https://timsong-cpp.github.io/cppwp/n4868/over.ics.list#9, particularly (albeit
non-normative) covered by /Note 2.

> Otherwise, if the parameter is a reference, see [over.ics.ref].
> 
> [Note 2: The rules in this subclause will apply **for initializing the 
> underlying temporary for the reference.** — end note]

DEMO: https://godbolt.org/z/YbeKo4T1q

[Bug c++/103333] New: [accepts-invalid] function template argument deduction for incompatible 'transformed A' / 'deduced A' pair

2021-11-19 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=10

Bug ID: 10
   Summary: [accepts-invalid] function template argument deduction
for incompatible 'transformed A' / 'deduced A' pair
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: davveston at gmail dot com
  Target Milestone: ---

The following program is accepted by GCC but rejected by Clang/MSVC
(-std=c++20):

---
#include 

template
struct S{
S() = default;

template::value>>
operator S() { return S{}; }
};

template
void f(S, b1>,
 // ^- T in non-deduced context for func-param
#1 
   S)
  // ^- T deduced from here
{} 

int main() {
S s1{};
S s2{};
f(s1, s2);
}
---

The program is ill-formed as function template argument deduction
([temp.deduct.call]) for the first argument resolves in a mismatched deduced A
vs. transformed A that is S and S, respectively,
and none of the three special cases of [temp.deduct.call]/4 allows this
mismatch.

[temp.arg.explicit]/7 allows a function argument to be converted to the type of
the corresponding function parameter, but only if the parameter type contains
to template arguments that participate in template argument deduction [from
that function argument]. This does not apply here, as the non-type template
parameter 'b1' participates in template argument deduction for the call.

---

https://timsong-cpp.github.io/cppwp/n4861/temp.deduct.call#4
https://timsong-cpp.github.io/cppwp/n4861/temp.arg.explicit#7

[Bug c++/102092] [C++2b] Passing argument to auto template parameter modifies the value of argument inside function

2021-08-27 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102092

--- Comment #3 from David Friberg  ---
(In reply to David Friberg from comment #2)
> I believe your program has UB as it contains an odr-violation due to the
> friend declaration of the stream operator function , as its in-class
> definition ("hidden friend") makes use of the non-type template parameter
> 'Degree'. 
> 
> The hidden friend, albeit being inline (protection against multiple-TU
> odr-violations, given token-by-token identical definitions), will have
> multiple definitions that are not the same as soon as two specializations of
> the class template 'Polynomial' are instantiated if these two
> specializations differ in the 'Degree' template parameter.
> 
> Recall that a non-template friend of a class template is in itself not a
> templated entity, but a namespace-scope function.

Never mind, I realized the hidden friend uses the class template as an
argument, though, so each specialization will instantiate a separate overload,
so I guess there will be no odr-violation Nafter all.

[Bug c++/102092] [C++2b] Passing argument to auto template parameter modifies the value of argument inside function

2021-08-27 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102092

David Friberg  changed:

   What|Removed |Added

 CC||davveston at gmail dot com

--- Comment #2 from David Friberg  ---
I believe your program has UB as it contains an odr-violation due to the friend
declaration of the stream operator function , as its in-class definition
("hidden friend") makes use of the non-type template parameter 'Degree'. 

The hidden friend, albeit being inline (protection against multiple-TU
odr-violations, given token-by-token identical definitions), will have multiple
definitions that are not the same as soon as two specializations of the class
template 'Polynomial' are instantiated if these two specializations differ in
the 'Degree' template parameter.

Recall that a non-template friend of a class template is in itself not a
templated entity, but a namespace-scope function.

[Bug c++/69348] alias declarations can not be used inside qualifiers of declarators

2021-08-05 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69348

--- Comment #5 from David Friberg  ---
(In reply to Andrew Pinski from comment #4)
> (In reply to David Friberg from comment #2)
> > Another similar but more common (/less contrived) example, rejects-valid
> > e.g. for GCC 10.1.0 for all C++ version (-std=c++X with X in {98, 11, 17,
> > 2a/20}).
> 
> This is a different issue and should be filed seperately.

Thanks for the prompt Andrew. I filed Bug 101789.

[Bug c++/101789] New: Fails to match (re-)declaration of member function of class template when using an alias template for the (dependent) return type

2021-08-05 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101789

Bug ID: 101789
   Summary: Fails to match (re-)declaration of member function of
class template when using an alias template for the
(dependent) return type
   Product: gcc
   Version: 11.1.0
Status: UNCONFIRMED
  Keywords: rejects-valid
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: davveston at gmail dot com
  Target Milestone: ---

(Broken out into a separate report, from my comment to Bug 69348, after prompt
by Andrew Pinski)

---

The following program 

template
struct S {
using type = int;
type f() const;  // #1
};

template
using type_t = typename S::type;

template 
type_t S::f() const { }  // #2a
// error: no declaration matches 'type_t S::f() const'

int main() {}


is rejected e.g. for GCC 11.1.0 for all C++ versions (-std=c++X with X in {11,
17, 2a/2b}), failing to match the (re-)declaration and definition at #2a of the
member function of the class template at #1, when using an alias template for
the dependent return type of the member function. Clang accepts this program.

The program is accepted if we remove the alias template

template 
typename S::type S::f() const { }  // #2b: OK

[Bug c++/54835] [C++11][DR 1518] Explicit default constructors not respected during copy-list-initialization

2021-06-09 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54835

--- Comment #22 from David Friberg  ---
(In reply to TC from comment #21)
> (In reply to David Friberg from comment #19)
> > 
> > P0398R0 [1] describes the final resolution to CWG 1518, after which the
> > following example is arguably well-formed:
> > 
> 
> It's not. Explicitness of a constructor is not considered when forming
> implicit conversion sequences from a braced-init-list, and therefore the
> assignment is ambiguous because {} can convert to either S or tag_t, even
> though the latter is ill-formed if actually used.

TC, thanks for the clarification. Just to be sure I'm not missing something, I
was under the impression that the [**emphasis**]

> For direct-initialization or default-initialization
> **that is not in the context of copy-initialization**, 
> the candidate functions are all the constructors of 
> the class of the object being initialized.

part of [over.match.ctor]/1 [1], which was added in P0398R0, intended to remove
non-converting (explicit) constructors from overload resolution in this
context, particularly resolving the issue shown in the original example of LWG
issue 251 [2]:


> That turns out to be very unfortunate, consider the following:
>
> #include 
> #include 
>
> void f(std::array, int) {} // #1
> void f(std::allocator_arg_t, int) {} // #2
>
> int main()
> {
>   f({}, 666); // #3
> }
> 
> The call at #3 is ambiguous.

after which the call at #3 in the LWG example above is no longer ambiguous
(afaict). I may be missing some subtlety here, but does my example above not
fall into the same category as this one?

[1] https://timsong-cpp.github.io/cppwp/n4861/over.match.ctor#1
[2] https://cplusplus.github.io/LWG/issue2510

[Bug c++/54835] [C++11][DR 1518] Explicit default constructors not respected during copy-list-initialization

2021-05-11 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54835

David Friberg  changed:

   What|Removed |Added

 CC||davveston at gmail dot com

--- Comment #19 from David Friberg  ---
Note that this bug report was marked as suspended based on the resolution of
CWG 1518 (and the related DR 1630) in June 2015, but the resolution of both
these issue were since changed. Citing 1518:

> Additional note, October, 2015:
> 
> It has been suggested that **the resolution of issue 1630 went too**
> far in allowing use of explicit constructors for default initialization, 
> and that default initialization should be considered to model copy 
> initialization instead. The resolution of this issue would provide an
> opportunity to adjust that.

P0398R0 [1] describes the final resolution to CWG 1518, after which the
following example is arguably well-formed:

 struct tag_t {
 explicit constexpr tag_t() = default;  // #3
 };

 struct S {
 constexpr S() {}
 constexpr S(S const&) {}
 S& operator=(S const&) { return *this; }
 S& operator=(tag_t) { return *this; } // #1
 };

 int main() {
 S s{};
 s = {};  // #2: GCC error: ambiguous overload for 'operator='
 }


as (at least from C++17) #1 is not a viable overload for the assignment at #2,
as tag_t is not an aggregate and copy-list-init from empty braces will not
consider the ctor #3 as it is explicit.

The example above is rejected by GCC (various versions) for both C++17 and
C++20, whereas Clang and MSVC both accepts it (curiosly Clang accepts it also
for C++11 for C++14, which may be wrong as tag_t is an aggregate for these
case, but I'm unsure, as we are covering a lot of CWG/LWG/DR confusion for this
issue).

---

[1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0398r0.html

[Bug c++/99699] New: Type deduction failure for deducing a non-type template parameter via another deducible structural type (class template specialization) non-type template parameter

2021-03-21 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99699

Bug ID: 99699
   Summary: Type deduction failure for deducing a non-type
template parameter via another deducible structural
type (class template specialization) non-type template
parameter
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: davveston at gmail dot com
  Target Milestone: ---

The following program:

// 
templatestruct S {};
template  struct U {};
template struct V { V() = delete; };

template  s>
struct V> {};

V{}>> v{};  // #1
// Expected:   use partial specialization #1
// GCC actual: error (rejects-valid): use of deleted function

int main() {}
// 

is rejected by gcc HEAD 11.0.1 20210320 (experimental) when compiling with 'g++
prog.cc -Wall -Wextra -std=c++2b', as #1 matches to the primary template
instead of the partial specialization.

It seems to find the non-type template parameter N non-deducible; however all
arguments of the partial specialization are arguably deducible from the
'U{}>' argument to the primary template:

- 'A' / 'P' matching 'U{}>' / 'U' deduces 's' to 'S<0>{}' and its type
to 'S<0>',
- 'A' / 'P' matching 'S<0>' to 'S' deduces 'N' to '0'; 'N' is particularly
not in a non-deduced context above, as it's not used in sub-expression in the
non-type template parameter 's' of the partial specialization.

Demo: https://wandbox.org/permlink/QQQxa3BhBTMM476E

[Bug c++/99697] New: ICE for class template partial specialization over non-template (structural class template) parameter of deduced class type

2021-03-21 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99697

Bug ID: 99697
   Summary: ICE for class template partial specialization over
non-template (structural class template) parameter of
deduced class type
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: davveston at gmail dot com
  Target Milestone: ---

The following program:

// ---
// prog.cc
template struct S {};
template   struct U {};
template  struct V;

template struct V> {}; // #1: ICE

int main() {}
// ---

compiled with gcc HEAD 11.0.1 20210320 (experimental) and the following command

 g++ prog.cc -Wall -Wextra -std=gnu++2b

results in the following ICE (segfault) at #1:

// ---
prog.cc:5:28: internal compiler error: Segmentation fault
5 | template struct V> {}; // ICE
  |^
0xca91ff crash_signal
../../source/gcc/toplev.c:327
0x63a207 resolve_args(vec*, int)
../../source/gcc/cp/call.c:4548
0x78a764 do_class_deduction
../../source/gcc/cp/pt.c:29332
0x78a764 do_auto_deduction(tree_node*, tree_node*, tree_node*, int,
auto_deduction_context, tree_node*, int)
../../source/gcc/cp/pt.c:29509
0x798c37 convert_template_argument
../../source/gcc/cp/pt.c:8491
0x79a19b convert_template_argument
../../source/gcc/cp/pt.c:8264
0x79a19b coerce_template_parms
../../source/gcc/cp/pt.c:8995
0x79b411 lookup_template_class_1
../../source/gcc/cp/pt.c:9833
0x79c3ec lookup_template_class(tree_node*, tree_node*, tree_node*, tree_node*,
int, int)
../../source/gcc/cp/pt.c:10237
0x7c028d finish_template_type(tree_node*, tree_node*, int)
../../source/gcc/cp/semantics.c:3563
0x75f603 cp_parser_template_id
../../source/gcc/cp/parser.c:17458
0x75f86b cp_parser_class_name
../../source/gcc/cp/parser.c:24685
0x75783a cp_parser_qualifying_entity
../../source/gcc/cp/parser.c:7002
0x75783a cp_parser_nested_name_specifier_opt
../../source/gcc/cp/parser.c:6684
0x76c30f cp_parser_simple_type_specifier
../../source/gcc/cp/parser.c:18851
0x74cd8d cp_parser_type_specifier
../../source/gcc/cp/parser.c:18509
0x75d323 cp_parser_type_specifier_seq
../../source/gcc/cp/parser.c:23360
0x75bba4 cp_parser_type_id_1
../../source/gcc/cp/parser.c:23163
0x75de83 cp_parser_template_type_arg
../../source/gcc/cp/parser.c:23268
0x75dfaf cp_parser_template_argument
../../source/gcc/cp/parser.c:17908
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See  for instructions.
// ---

I think the partial specialization at #1 can never be used as the non-type
template parameter 's' of deduced class type can never be deduced, such that
the correct behaviour should arguably be to reject the program as ill-formed
(at #1).

Demo: https://wandbox.org/permlink/ufm4B9uIn8dgHYAI

[Bug c++/83417] Pointer-to-member template parameter with auto member type dependent container type does not work (C++17)

2021-02-03 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83417

--- Comment #4 from David Friberg  ---
The example of my previous comment may fall under (the original intent of?) CWG
1892. If so it ill-formed, as 'auto (*fp)(T)' is not a function declaration in
the template parameter list. 
http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1892

Although afaict a pointer to function declarator is not a function declarator,
meaning [dcl.spec.auto]/2 may not apply here.
https://timsong-cpp.github.io/cppwp/n4861/dcl.spec.auto#2

[Bug c++/83417] Pointer-to-member template parameter with auto member type dependent container type does not work (C++17)

2021-01-27 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83417

David Friberg  changed:

   What|Removed |Added

 CC||davveston at gmail dot com

--- Comment #3 from David Friberg  ---
The same holds for the case of function pointers.

Given the following function:

 void f(int) {}

Both examples (A) and (B) below are well-formed, as per [temp.deduct.type]/13
(and for (B): also as per [temp.arg.nontype]/1).

 // Example (A)
 template 
 struct A;

 template 
 struct A { };

 A a{};  // #1: OK

 // Example (B)
 template 
 struct B;

 template 
 struct B { };

 B b{};  // #2: Rejected (type deduction failure in partial specialization)

Clang accepts both, whereas GCC (trunk/any version I've tried that supports
C++17) rejects example (B), as #2 is resolved to the primary (non-defined)
class template after failing to deduce the dependent 'T' from 'auto (*fp)(T)'
in the partial specialization, given the argument 'f' to the latter (non-type)
template parameter.

[Bug c++/98822] New: Rejects-valid: instantiation of class template instantiates (all) constrained non-template friend definitions (, even those) with unsatisfied constraints

2021-01-25 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98822

Bug ID: 98822
   Summary: Rejects-valid: instantiation of class template
instantiates (all) constrained non-template friend
definitions (, even those) with unsatisfied
constraints
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: davveston at gmail dot com
  Target Milestone: ---

(All standard references below refer to N4861).

Constrained hidden non-template friends was added as per NS US115 of P2103R0
(adding [temp.friend]/9), meaning the following program is (afaict)
well-formed:

 template
 struct S {
 friend void f(int) requires (N == 0) { }
 operator int() const { return 0; }
 };

 int main() { 
 f(S<0>{});
 }

whereas the following is ill-formed, as overload resolution rejects the friend
due to unsatisfied constraints:

 template
 struct S {
 friend void f(int) requires (N == 0) { }
 operator int() const { return 0; }
 };

 int main() { 
 f(S<1>{});
 // error: no matching function for call to 'f'
 // candidate function not viable: constraints not satisfied
 }

and GCC correctly accepts and rejects these two examples, respectively.

However, the following program is also rejected by GCC:

 template
 struct S {
 friend void f(int) requires (N == 0) { }
 operator int() const { return 0; }
 };

 S<1> s1{};
 S<2> s2{};
 // error: redefinition of 'void foo(int) requires  N == 0'

implying that GCC, for each instantiation of the class template S, also
instantiates its constrained friend definitions, even those where the
associated constraints are not satisfied, meaning more than a single
instantiation in a single TU fails due to and ODR-violation
([basic.def.odr]/1). It basically acts the same way as for hidden friend
definitions prior to constrained (non-templated) friends.

I have not been able to sort out whether the final example above is actually
well-formed as per N4861, but it's arguably weird if US115 added support for
constrained non-template (hidden) friends whilst not allowing overloading
solely on the constraint. As per [temp.friend]/9 each constrained hidden friend
is indeed unique (to its specialization), which is also supported by
[defns.signature.friend].

Constraint satisfaction should arguably be checked in the context of the
template instantiation and not only during overload resolution.

---

(MSVC accepts the final example above, but fails with ambiguous call errors
during overload resolution if we start overloading constrainded non-template
friends solely on their constraints. Clang has fails this feature for other
reasons; failing [defns.signature.friend] w.r.t. unique mangled names if we add
another overload with another constraint).

[Bug c++/98820] New: Placeholder (auto) non-type template parameter wrongly deduced to 'const' for class type arguments

2021-01-25 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98820

Bug ID: 98820
   Summary: Placeholder (auto) non-type template parameter wrongly
deduced to 'const' for class type arguments
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: davveston at gmail dot com
  Target Milestone: ---

As per [temp.param]/6 in N4861, for non-template parameters (including a type
that contains a placeholder type):

"[...] The top-level cv-qualifiers on the template-parameter are ignored when
determining its type."

and as per [dcl.type.decltype]/1.2:

"For an expression E, the type denoted by decltype(E) is defined as follows: 
- [...] naming a non-type template-parameter, decltype(E) is the type of the
template-parameter after performing any necessary type deduction [...]"

Thus, the following example should arguably be well-formed:

 #include 

 struct A{};

 template  
 void f() { 
 static_assert(std::is_same_v);
 }

 template  
 void g() { 
 static_assert(std::is_same_v);
 }

 int main() {
 constexpr A a{};
 f();
 g();
 }

However GCC rejects it as `decltype(a)` resolves to `A const` rather than `A`.

---

We may note that:

1) Clang accepts the program, and 
2) Both Clang and GCC accepts the program when using a structural type directly
instead of a placeholder type for the non-type template parameter; replacing
the definitions of `f` and `g` above with:

 template  
 void f() { 
 static_assert(std::is_same_v);
 }

 template  
 void g() { 
 static_assert(std::is_same_v);
 }

3) Both clang and GCC accepts the program when using a placeholder type but
with a non-class type as template argument to it; replacing the definitions of
`f` and `g` above with:

 template  
 void f() { 
 static_assert(std::is_same_v);
 }

 template  
 void g() { 
 static_assert(std::is_same_v);
 }

and calling them as f<0>() and g<0>();

---

These standard rules are arguably somewhat confusing given that the template
parameter object itself (associated with the class-type non-type template
parameter) is `const` ([temp.param]/8).

[Bug c++/59238] Dynamic allocating a list-initialized object of a type with private destructor fails.

2020-12-07 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59238

David Friberg  changed:

   What|Removed |Added

 CC||davveston at gmail dot com

--- Comment #1 from David Friberg  ---
This bug is still present in GCC 10.1.0 and GCC trunk (for various C++
versions).

Related SO Q (https://stackoverflow.com/questions/65124761) list the
following examples as rejects-valid:

struct A { ~A() = delete; };
A *pa{new A{}};

class B { ~B() = default; };
B *pb{new B{}};

struct E {
~E() = delete; 
private: 
int x;
};
E *pe{new E{}};


whereas the following are all accepted (accepts-valid):

class C { ~C(); };
C *pc{new C{}};  // OK

class D { ~D() {} };
D *pd{new D{}};  // OK

struct F {
F() = default;
~F() = delete; 
};
F *pf{new F{}};

struct G {
G() = default;
~G() = delete; 
private: 
int x;
};
G *pg{new G{}};


The SO Q lists standard passages to motivate that this is a rejects-valid, in
case this is challenged.

[Bug c++/98120] New: Multiple definitions (single TU) of explicit specialization of member enumeration of a class template

2020-12-03 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98120

Bug ID: 98120
   Summary: Multiple definitions (single TU) of explicit
specialization of member enumeration of a class
template
   Product: gcc
   Version: 10.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: davveston at gmail dot com
  Target Milestone: ---

[temp.expl.spec]/1.7[1] allows explicitly specializing a member enumeration of
a class template.

Although [temp.spec]/5.2[2] specifies that multiple definitions of an explicit
specialization in a program is ill-formed (referring to [basic.def.odr]) NDR,
multiple definitions within a single TU falls under [basic.def.odr]/1[3], as
e.g. an explicit specialization of a class template (for some set template
arguments) is a class; the latter is not NDR and violations of it should be
diagnosed.

Both GCC and Clang does so for multiple ODR-violating (within same TU) explicit
specializations of function templates, class templates, variable templates,
member functions of class templates, static data members of class templates,
and member classes of class templates. However, only Clang diagnoses it for
member enumerations of class templates:

// prog.cc
template 
struct S { enum class E; };

template<>
enum class S<0>::E { ex };

template<>
enum class S<0>::E { ey };  // (C')
  // Clang only - error: redefinition of 'C<...>::E'

int main() {}


The above ill-formed program (arguably not NDR) is accepted by various GCC
versions for various C++ versions.

Demo for GCC 10.1.0 compiled with 

 g++ prog.cc -Wall -Wextra -std=c++17 

here: https://wandbox.org/permlink/B3GhCK4UqfIh36VH

---

Explicit specializations for member enumerations of class templates have some
other tickets where the root cause (of fix of the root cause) may be related,
e.g. bug 53815 and bug 61491.

---

References:

[1] https://timsong-cpp.github.io/cppwp/n4659/temp.expl.spec#1.7
[2] https://timsong-cpp.github.io/cppwp/n4659/temp.spec#5.2
[3] https://timsong-cpp.github.io/cppwp/n4659/basic.def.odr#1

[Bug c++/69348] alias declarations can not be used inside qualifiers of declarators

2020-12-03 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69348

David Friberg  changed:

   What|Removed |Added

 CC||davveston at gmail dot com

--- Comment #2 from David Friberg  ---
Another similar but more common (/less contrived) example, rejects-valid e.g.
for GCC 10.1.0 for all C++ version (-std=c++X with X in {98, 11, 17, 2a/20}).

// https://wandbox.org/permlink/aQpRzgcvAHOihKz5
template
struct S {
using type = int;
type f() const;
};

template
using type_t = typename S::type;

template 
type_t S::f() const { }
// error: no declaration matches 'type_t S::f() const'

int main() {}

---

Brought up in
https://stackoverflow.com/questions/65110143/using-typealias-in-place-of-typedef-defined-in-class-in-definition

[Bug c++/97942] [C++20][P0692R1] Access checking not waived for declarations of explicit specializations of function and variable templates

2020-12-03 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97942

--- Comment #1 from David Friberg  ---
Somewhat related, we may note that GCC accepts-valid the following program, say
(D):

class A { class B {}; };

template struct S {};
template struct S {};
template struct S {};

int main() {}


which is valid as per [temp.class.spec]/10
(https://timsong-cpp.github.io/cppwp/n4861/temp.class.spec#10), which covers
waiving of access checking for template arguments in the simple-template-id of
partial specializations, a paragraph that was also added as part of P0692R1.

[Bug c++/97942] New: [C++20][P0692R1] Access checking not waived for declarations of explicit specializations of function and variable templates

2020-11-23 Thread davveston at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97942

Bug ID: 97942
   Summary: [C++20][P0692R1] Access checking not waived for
declarations of explicit specializations of function
and variable templates
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: davveston at gmail dot com
  Target Milestone: ---

[temp.spec]/6[1] was added to the C++20 spec by implementation of P0692R1[2]:

"The usual access checking rules do not apply to names in a declaration of an
explicit instantiation or explicit specialization, with the exception of names
appearing in a function body, default argument, base-clause,
member-specification, enumerator-list, or static data member or variable
template initializer."

Meaning that programs (A) through (C) below are (arguably) well-formed:

(A) (DEMO: https://wandbox.org/permlink/No9RdUGRQFinIPie)

class A { class B {}; };

template struct S {};
template<> struct S {};

int main() {}


(B) (DEMO: https://wandbox.org/permlink/Ki1iLlje2raKJoEb):

class A { class B {}; };

template void foo() {};
template<> void foo() {}

int main() {}


(C) (DEMO: https://wandbox.org/permlink/AN06msZgJNmxB0HS)

class A { class B {}; };

template
constexpr bool v = false;

template<>
constexpr bool v = true;

int main() {}


However whilst GCC accepts (A), it rejects (B) and (C).

> (gcc HEAD 11.0.0 20201121 (experimental))
> g++ prog.cc -Wall -Wextra -std=c++2a
> error: 'class A::B' is private within this context

As per [3], P0692R1 has been implemented in GCC ("Available in GCC: Yes").

---

References

[1] https://timsong-cpp.github.io/cppwp/n4861/temp.spec#6

[2] P0692R1 - Access Checking on Specializations
http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0692r1.html)

[3] https://gcc.gnu.org/projects/cxx-status.html