[Bug c++/101113] g++ thinks constructor suppressed by a requires clause is actually a bad copy constructor

2023-11-28 Thread gcc at nospam dot scs.stanford.edu via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101113

David Mazières  changed:

   What|Removed |Added

 Status|NEW |RESOLVED
 Resolution|--- |INVALID

--- Comment #4 from David Mazières  ---
Sorry I should have closed this bug report a while ago when I said it wasn't a
bug.

[Bug c++/112715] Incorrect handling of template type aliases instantiated from decltype of lambdas

2023-11-25 Thread gcc at nospam dot scs.stanford.edu via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112715

--- Comment #1 from David Mazières  ---
I should have mentioned, I hereby place the test case in the public domain.

[Bug c++/112715] New: Incorrect handling of template type aliases instantiated from decltype of lambdas

2023-11-25 Thread gcc at nospam dot scs.stanford.edu via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112715

Bug ID: 112715
   Summary: Incorrect handling of template type aliases
instantiated from decltype of lambdas
   Product: gcc
   Version: 13.2.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: gcc at nospam dot scs.stanford.edu
  Target Milestone: ---

Created attachment 56689
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=56689=edit
File that should compile but doesn't

I'm using g++ version 13.2.1 on arch linux, configured as follows:


$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/13.2.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure
--enable-languages=ada,c,c++,d,fortran,go,lto,objc,obj-c++ --enable-bootstrap
--prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man
--infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/
--with-build-config=bootstrap-lto --with-linker-hash-style=gnu
--with-system-zlib --enable-__cxa_atexit --enable-cet=auto
--enable-checking=release --enable-clocale=gnu --enable-default-pie
--enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object
--enable-libstdcxx-backtrace --enable-link-serialization=1
--enable-linker-build-id --enable-lto --enable-multilib --enable-plugin
--enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch
--disable-werror
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 13.2.1 20230801 (GCC) 


When defining template type aliases, I get bizarrely incorrect types in some
contexts but not others.  For example, the static assertion fails in this code
but should not:


#include 

template
using uintsz = decltype([](auto i){
  if constexpr (i <= 32)
return 0;
  else
return 0L;
 }(std::integral_constant{}));

template
constexpr uintsz<8*Nbytes>
f()
{
  return 0;
}

static_assert(std::is_same_v()), uintsz<56>>);


Specifically I get the following error:


$ g++ -std=c++20 -ggdb -O -Wall -c -o uintsz.o uintsz.cc
uintsz.cc:18:20: error: static assertion failed
   18 | static_assert(std::is_same_v()), uintsz<56>>);
  |   ~^~~


This feels like some sort of state corruption in the compiler, because there
are more complicated examples in which gcc rejects other things inside
functions (like rejecting a using type alias and accepting the corresponding
typedef).  I think this example suffices to show the problem, but I could try
to reduce another test case if necessary.  In all cases, clang++ -std=c++20
accepts the code.

[Bug c++/107889] New: Incorrect parsing of qualified friend function returning decltype(auto)

2022-11-27 Thread gcc at nospam dot scs.stanford.edu via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107889

Bug ID: 107889
   Summary: Incorrect parsing of qualified friend function
returning decltype(auto)
   Product: gcc
   Version: 12.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: gcc at nospam dot scs.stanford.edu
  Target Milestone: ---

G++ 12.2.0 rejects a valid friend declaration for a fully-qualified function
returning `decltype(auto)`.  To reproduce the problem, you can try to compile
the following code with `g++ -std=c++20 -c bug.cc`:

decltype(auto)
f()
{
}

struct S {
  friend decltype(auto) ::f();
};


This results in the following error:

$ c++ -std=c++20 -c bug.cc
bug.cc:7:27: error: 'decltype(auto)' is not a class type
7 |   friend decltype(auto) ::f();
  |   ^
bug.cc:7:27: error: 'decltype(auto)' is not a class type
bug.cc:7:27: error: 'decltype(auto)' is not a class type
bug.cc:7:29: error: 'decltype(auto)' is not a class type
7 |   friend decltype(auto) ::f();
  | ^
bug.cc:7:10: error: ISO C++ forbids declaration of 'f' with no type
[-fpermissive]
7 |   friend decltype(auto) ::f();
  |  ^~
bug.cc:7:29: error: invalid use of 'decltype(auto)'
7 |   friend decltype(auto) ::f();


A similar problem was reported in bug #59766 for friend functions returning
auto.  It seems to have been mostly fixed, but the combination of
decltype(auto) and the function name being qualified (::f) is still a problem.

[Bug c++/101113] g++ thinks constructor suppressed by a requires clause is actually a bad copy constructor

2021-06-22 Thread gcc at nospam dot scs.stanford.edu via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101113

--- Comment #3 from David Mazieres  ---
(In reply to TC from comment #2)
> https://eel.is/c++draft/class.copy.ctor#5
> 
> I don't think this code is valid. The constraint (which isn't checked until
> overload resolution time anyway) can't suppress the outright ill-formedness
> of the declaration.

Admittedly, 11.4.5.3/5 makes no mention of constraints:

A declaration of a constructor for a class X is ill-formed if its first
parameter is of type cv X and either there are no other parameters or else all
other parameters have default arguments.
A member function template is never instantiated to produce such a constructor
signature.
- https://timsong-cpp.github.io/cppwp/n4868/class.copy.ctor#5

On the other hand, suppressed functions should not participate in overload
resolution.  Here's some normative language to the same effect 12.4.3/3:

Second, for a function to be viable, if it has associated constraints
([temp.constr.decl]), those constraints shall be satisfied
([temp.constr.constr]).
- https://timsong-cpp.github.io/cppwp/n4868/over.match.viable#3

So here's another example that doesn't involve 11.4.5.3/5:

#include 

template struct S2 {
  static T *fn() requires (!std::is_reference_v) { return nullptr; }
  static std::nullptr_t fn() requires std::is_reference_v { return {}; }
};

void
f()
{
  auto p = S2::fn();
}

$ g++ -std=c++20-c -o constructor.o constructor.cc
constructor.cc: In instantiation of 'struct S2':
constructor.cc:11:20:   required from here
constructor.cc:4:13: error: forming pointer to reference type 'int&'
4 |   static T *fn() requires (!std::is_reference_v) { return nullptr; }
  | ^~
make: *** [: constructor.o] Error 1

So I guess your argument is that there's a certain level of well-formedness
required even before the constraints can be evaluated, and an X::X(X) method is
as non-sensical as a type like "int&*".  That seems like a reasonable position,
though I wish the standard were more explicit.

I apologize for wasting your time if this was a bogus bug report.

For the record, in case the closed bug report comes up in anyone's web search,
an easy fix is to rely on the fact that templates won't be instantiated to bad
copy constructors:

template struct S {
  S() {}
  template S(S) requires B2 {}
};
S sf;
S st;

[Bug c++/101113] New: g++ thinks constructor suppressed by a requires clause is actually a bad copy constructor

2021-06-17 Thread gcc at nospam dot scs.stanford.edu via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101113

Bug ID: 101113
   Summary: g++ thinks constructor suppressed by a requires clause
is actually a bad copy constructor
   Product: gcc
   Version: 11.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: gcc at nospam dot scs.stanford.edu
  Target Milestone: ---

g++ 11.1.0 is rejecting the following correct code when compiling with
`-std=c++20` (test case public domain):

template struct S {
  S() {}
  S(S) requires B {}
};
S sf;

Here is the error message:

$ g++ -std=c++20 -c test.cc
y.cc: In instantiation of 'struct S':
y.cc:3:26:   required from here
y.cc:3:3: error: invalid constructor; you probably meant 'S (const
S&)'
3 |   S(S) requires B {}
  |   ^

[Bug c++/100946] New: [concepts] nonsensical results of compound requirements in requires expressions

2021-06-07 Thread gcc at nospam dot scs.stanford.edu via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100946

Bug ID: 100946
   Summary: [concepts] nonsensical results of compound
requirements in requires expressions
   Product: gcc
   Version: 11.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: gcc at nospam dot scs.stanford.edu
  Target Milestone: ---

Created attachment 50958
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=50958=edit
test case (public domain)

g++ handles compound requirements in requires clauses in an inconsistent way,
almost as if the compiler itself is using an uninitialized variable.  I'm
checking the behavior with the following simple program:

#include 
#include 

#define CHECK(e,T)  \
  std::cout << "Is " << #e << " of type " << #T << "? " << requires {   \
{ e } -> std::same_as;   \
  } << std::endl

int
main()
{
  std::cout << std::boolalpha;

  int i = 0;
  CHECK(0, int);
  //CHECK(0, int&);
  CHECK(i, int);
  CHECK(i, int&);
}

The above program yields the following output:

Is 0 of type int? true
Is i of type int? true
Is i of type int&? true

This doesn't make sense, since i can't be both int and int&.  But then if I
change the program to add the line CHECK(0,int&);, I get the following:

Is 0 of type int? true
Is 0 of type int&? false
Is i of type int? true
Is i of type int&? false

This is wrong according to the spec--i should be of type int&, because you are
supposed to use the expression rules [like decltype((e))] rather than the
variable rules [like decltype(e)] for compound requirements.  But what's even
worse is the inconsistency between the two programs--somehow just adding a
different check changed the behavior.  If I remove the checks against 0
altogether, I get the following, which is correct according to the language
spec, and again inconsistent with the previous examples:

Is i of type int? false
Is i of type int&? true