Re: [PATCH] c++: address of NTTP object as targ [PR113242]

2024-01-17 Thread Jason Merrill

On 1/17/24 10:43, Patrick Palka wrote:

On Mon, 15 Jan 2024, Jason Merrill wrote:

On 1/5/24 11:50, Patrick Palka wrote:


invalid_tparm_referent_p was rejecting using the address of a class NTTP
object as a template argument, but this should be fine.


Hmm, I suppose so; https://eel.is/c++draft/temp#param-8 saying "No two
template parameter objects are template-argument-equivalent" suggests there
can be only one.  And clang/msvc allow it.


+   else if (VAR_P (decl) && !DECL_NTTP_OBJECT_P (decl)
+&& DECL_ARTIFICIAL (decl))


If now some artificial variables are OK and others are not, perhaps we should
enumerate them either way and abort if it's one we haven't specifically
considered.


Sounds good, like so?  Shall we backport this patch or the original
patch to the 13 branch?


Hmm, looks like this patch changes the non-checking default behavior 
from reject to accept; maybe just add a checking_assert (tinfo || fname) 
to your original patch?  OK with that change, for trunk and 13.



-- >8 --

Subject: [PATCH] c++: address of class NTTP object as targ [PR113242]

invalid_tparm_referent_p was rejecting using the address of a class NTTP
object as a template argument, but this should be fine.

This patch fixes this by refining the DECL_ARTIFICIAL rejection test to
check specifically for the kinds of artificial variables we want to
exclude.

PR c++/113242

gcc/cp/ChangeLog:

* pt.cc (invalid_tparm_referent_p) : Refine
DECL_ARTIFICIAL rejection test.  Assert that C++20 template
parameter objects are the only artificial variables we accept.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/nontype-class61.C: New test.
---
  gcc/cp/pt.cc | 13 +++---
  gcc/testsuite/g++.dg/cpp2a/nontype-class61.C | 27 
  2 files changed, 37 insertions(+), 3 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class61.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index b6117231de1..885c297450e 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -7212,12 +7212,14 @@ invalid_tparm_referent_p (tree type, tree expr, 
tsubst_flags_t complain)
/* C++17: For a non-type template-parameter of reference or pointer
   type, the value of the constant expression shall not refer to (or
   for a pointer type, shall not be the address of):
-  * a subobject (4.5),
+  * a subobject (4.5), (relaxed in C++20)
   * a temporary object (15.2),
-  * a string literal (5.13.5),
+  * a string literal (5.13.5), (we diagnose this early in
+convert_nontype_argument)
   * the result of a typeid expression (8.2.8), or
   * a predefined __func__ variable (11.4.1).  */
-   else if (VAR_P (decl) && DECL_ARTIFICIAL (decl))
+   else if (VAR_P (decl)
+&& (DECL_TINFO_P (decl) || DECL_FNAME_P (decl)))
  {
if (complain & tf_error)
  error ("the address of %qD is not a valid template argument",
@@ -7242,6 +7244,11 @@ invalid_tparm_referent_p (tree type, tree expr, 
tsubst_flags_t complain)
 decl);
return true;
  }
+
+   /* The only artificial variables we do accept are C++20
+  template parameter objects.   */
+   if (VAR_P (decl) && DECL_ARTIFICIAL (decl))
+ gcc_checking_assert (DECL_NTTP_OBJECT_P (decl));
}
break;
  
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class61.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class61.C

new file mode 100644
index 000..90805a05ecf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class61.C
@@ -0,0 +1,27 @@
+// PR c++/113242
+// { dg-do compile { target c++20 } }
+
+struct wrapper {
+  int n;
+};
+
+template
+void f1() {
+  static_assert(X.n == 42);
+}
+
+template
+void f2() {
+  static_assert(X->n == 42);
+}
+
+template
+void g() {
+  f1();
+  f2<>();
+}
+
+int main() {
+  constexpr wrapper X = {42};
+  g();
+}




Re: [PATCH] c++: address of NTTP object as targ [PR113242]

2024-01-17 Thread Patrick Palka
On Mon, 15 Jan 2024, Jason Merrill wrote:

> On 1/5/24 11:50, Patrick Palka wrote:
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK
> > for trunk and perhaps 13?
> > 
> > -- >8 --
> > 
> > invalid_tparm_referent_p was rejecting using the address of a class NTTP
> > object as a template argument, but this should be fine.
> 
> Hmm, I suppose so; https://eel.is/c++draft/temp#param-8 saying "No two
> template parameter objects are template-argument-equivalent" suggests there
> can be only one.  And clang/msvc allow it.
> 
> > PR c++/113242
> > 
> > gcc/cp/ChangeLog:
> > 
> > * pt.cc (invalid_tparm_referent_p) : Suppress
> > DECL_ARTIFICIAL rejection test for class NTTP objects.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp2a/nontype-class61.C: New test.
> > ---
> >   gcc/cp/pt.cc |  3 ++-
> >   gcc/testsuite/g++.dg/cpp2a/nontype-class61.C | 27 
> >   2 files changed, 29 insertions(+), 1 deletion(-)
> >   create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class61.C
> > 
> > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> > index 154ac76cb65..8c7d178328d 100644
> > --- a/gcc/cp/pt.cc
> > +++ b/gcc/cp/pt.cc
> > @@ -7219,7 +7219,8 @@ invalid_tparm_referent_p (tree type, tree expr,
> > tsubst_flags_t complain)
> >* a string literal (5.13.5),
> >* the result of a typeid expression (8.2.8), or
> >* a predefined __func__ variable (11.4.1).  */
> > -   else if (VAR_P (decl) && DECL_ARTIFICIAL (decl))
> > +   else if (VAR_P (decl) && !DECL_NTTP_OBJECT_P (decl)
> > +&& DECL_ARTIFICIAL (decl))
> 
> If now some artificial variables are OK and others are not, perhaps we should
> enumerate them either way and abort if it's one we haven't specifically
> considered.

Sounds good, like so?  Shall we backport this patch or the original
patch to the 13 branch?

-- >8 --

Subject: [PATCH] c++: address of class NTTP object as targ [PR113242]

invalid_tparm_referent_p was rejecting using the address of a class NTTP
object as a template argument, but this should be fine.

This patch fixes this by refining the DECL_ARTIFICIAL rejection test to
check specifically for the kinds of artificial variables we want to
exclude.

PR c++/113242

gcc/cp/ChangeLog:

* pt.cc (invalid_tparm_referent_p) : Refine
DECL_ARTIFICIAL rejection test.  Assert that C++20 template
parameter objects are the only artificial variables we accept.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/nontype-class61.C: New test.
---
 gcc/cp/pt.cc | 13 +++---
 gcc/testsuite/g++.dg/cpp2a/nontype-class61.C | 27 
 2 files changed, 37 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class61.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index b6117231de1..885c297450e 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -7212,12 +7212,14 @@ invalid_tparm_referent_p (tree type, tree expr, 
tsubst_flags_t complain)
/* C++17: For a non-type template-parameter of reference or pointer
   type, the value of the constant expression shall not refer to (or
   for a pointer type, shall not be the address of):
-  * a subobject (4.5),
+  * a subobject (4.5), (relaxed in C++20)
   * a temporary object (15.2),
-  * a string literal (5.13.5),
+  * a string literal (5.13.5), (we diagnose this early in
+convert_nontype_argument)
   * the result of a typeid expression (8.2.8), or
   * a predefined __func__ variable (11.4.1).  */
-   else if (VAR_P (decl) && DECL_ARTIFICIAL (decl))
+   else if (VAR_P (decl)
+&& (DECL_TINFO_P (decl) || DECL_FNAME_P (decl)))
  {
if (complain & tf_error)
  error ("the address of %qD is not a valid template argument",
@@ -7242,6 +7244,11 @@ invalid_tparm_referent_p (tree type, tree expr, 
tsubst_flags_t complain)
 decl);
return true;
  }
+
+   /* The only artificial variables we do accept are C++20
+  template parameter objects.   */
+   if (VAR_P (decl) && DECL_ARTIFICIAL (decl))
+ gcc_checking_assert (DECL_NTTP_OBJECT_P (decl));
   }
   break;
 
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class61.C 
b/gcc/testsuite/g++.dg/cpp2a/nontype-class61.C
new file mode 100644
index 000..90805a05ecf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class61.C
@@ -0,0 +1,27 @@
+// PR c++/113242
+// { dg-do compile { target c++20 } }
+
+struct wrapper {
+  int n;
+};
+
+template
+void f1() {
+  static_assert(X.n == 42);
+}
+
+template
+void f2() {
+  static_assert(X->n == 42);
+}
+
+template
+void g() {
+  f1();
+  f2<>();
+}
+
+int main() {
+  constexpr wrapper X = {42};
+  g();
+}
-- 
2.43.0.367.g186b115d30



Re: [PATCH] c++: address of NTTP object as targ [PR113242]

2024-01-15 Thread Jason Merrill

On 1/5/24 11:50, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK
for trunk and perhaps 13?

-- >8 --

invalid_tparm_referent_p was rejecting using the address of a class NTTP
object as a template argument, but this should be fine.


Hmm, I suppose so; https://eel.is/c++draft/temp#param-8 saying "No two 
template parameter objects are template-argument-equivalent" suggests 
there can be only one.  And clang/msvc allow it.



PR c++/113242

gcc/cp/ChangeLog:

* pt.cc (invalid_tparm_referent_p) : Suppress
DECL_ARTIFICIAL rejection test for class NTTP objects.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/nontype-class61.C: New test.
---
  gcc/cp/pt.cc |  3 ++-
  gcc/testsuite/g++.dg/cpp2a/nontype-class61.C | 27 
  2 files changed, 29 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class61.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 154ac76cb65..8c7d178328d 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -7219,7 +7219,8 @@ invalid_tparm_referent_p (tree type, tree expr, 
tsubst_flags_t complain)
   * a string literal (5.13.5),
   * the result of a typeid expression (8.2.8), or
   * a predefined __func__ variable (11.4.1).  */
-   else if (VAR_P (decl) && DECL_ARTIFICIAL (decl))
+   else if (VAR_P (decl) && !DECL_NTTP_OBJECT_P (decl)
+&& DECL_ARTIFICIAL (decl))


If now some artificial variables are OK and others are not, perhaps we 
should enumerate them either way and abort if it's one we haven't 
specifically considered.


Jason



Re: [PATCH] c++: address of NTTP object as targ [PR113242]

2024-01-15 Thread Patrick Palka
On Fri, Jan 5, 2024 at 11:50 AM Patrick Palka  wrote:
>
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK
> for trunk and perhaps 13?

Ping.

>
> -- >8 --
>
> invalid_tparm_referent_p was rejecting using the address of a class NTTP
> object as a template argument, but this should be fine.
>
> PR c++/113242
>
> gcc/cp/ChangeLog:
>
> * pt.cc (invalid_tparm_referent_p) : Suppress
> DECL_ARTIFICIAL rejection test for class NTTP objects.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/cpp2a/nontype-class61.C: New test.
> ---
>  gcc/cp/pt.cc |  3 ++-
>  gcc/testsuite/g++.dg/cpp2a/nontype-class61.C | 27 
>  2 files changed, 29 insertions(+), 1 deletion(-)
>  create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class61.C
>
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 154ac76cb65..8c7d178328d 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -7219,7 +7219,8 @@ invalid_tparm_referent_p (tree type, tree expr, 
> tsubst_flags_t complain)
>* a string literal (5.13.5),
>* the result of a typeid expression (8.2.8), or
>* a predefined __func__ variable (11.4.1).  */
> -   else if (VAR_P (decl) && DECL_ARTIFICIAL (decl))
> +   else if (VAR_P (decl) && !DECL_NTTP_OBJECT_P (decl)
> +&& DECL_ARTIFICIAL (decl))
>   {
> if (complain & tf_error)
>   error ("the address of %qD is not a valid template argument",
> diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class61.C 
> b/gcc/testsuite/g++.dg/cpp2a/nontype-class61.C
> new file mode 100644
> index 000..90805a05ecf
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class61.C
> @@ -0,0 +1,27 @@
> +// PR c++/113242
> +// { dg-do compile { target c++20 } }
> +
> +struct wrapper {
> +  int n;
> +};
> +
> +template
> +void f1() {
> +  static_assert(X.n == 42);
> +}
> +
> +template
> +void f2() {
> +  static_assert(X->n == 42);
> +}
> +
> +template
> +void g() {
> +  f1();
> +  f2<>();
> +}
> +
> +int main() {
> +  constexpr wrapper X = {42};
> +  g();
> +}
> --
> 2.43.0.254.ga26002b628
>