diff mbox series

c++: Prevent bogus -Wtype-limits warning with NTTP [PR100161]

Message ID 20210421004246.361459-1-polacek@redhat.com
State New
Headers show
Series c++: Prevent bogus -Wtype-limits warning with NTTP [PR100161] | expand

Commit Message

Marek Polacek April 21, 2021, 12:42 a.m. UTC
Recently, we made sure that we never call value_dependent_expression_p
on an expression that isn't potential_constant_expression.  That caused
this bogus warning with a non-type template parameter, something that
users don't want to see.

The problem is that in tsubst_copy_and_build/LE_EXPR 't' is "i < n",
which, due to 'i', is not p_c_e, therefore we call t_d_e_p.  But the
type of 'n' isn't dependent, so we think the whole 't' expression is
not dependent.  It seems we need to test both op0 and op1 separately
to suppress this warning.  I use a lambda so as not to repeat the
check.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11.2?
Think I also want to backport to 10.4, but then the patch can't use
a lambda.

gcc/cp/ChangeLog:

	PR c++/100161
	* pt.c (tsubst_copy_and_build) <case PLUS_EXPR>: Test op0 and
	op1 separately for value- or type-dependence.

gcc/testsuite/ChangeLog:

	PR c++/100161
	* g++.dg/warn/Wtype-limits6.C: New test.
---
 gcc/cp/pt.c                               | 24 ++++++++++++++---------
 gcc/testsuite/g++.dg/warn/Wtype-limits6.C | 17 ++++++++++++++++
 2 files changed, 32 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/warn/Wtype-limits6.C


base-commit: 5491da23088734d516aae220810f253b9922c98c

Comments

Jason Merrill April 21, 2021, 2:40 a.m. UTC | #1
On 4/20/21 8:42 PM, Marek Polacek wrote:
> Recently, we made sure that we never call value_dependent_expression_p
> on an expression that isn't potential_constant_expression.  That caused
> this bogus warning with a non-type template parameter, something that
> users don't want to see.
> 
> The problem is that in tsubst_copy_and_build/LE_EXPR 't' is "i < n",
> which, due to 'i', is not p_c_e, therefore we call t_d_e_p.  But the
> type of 'n' isn't dependent, so we think the whole 't' expression is
> not dependent.  It seems we need to test both op0 and op1 separately
> to suppress this warning.  I use a lambda so as not to repeat the
> check.
> 
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11.2?
> Think I also want to backport to 10.4, but then the patch can't use
> a lambda.

It should be straightforward to rewrite the lambda as a local class; 
let's use that version for all the branches.

> gcc/cp/ChangeLog:
> 
> 	PR c++/100161
> 	* pt.c (tsubst_copy_and_build) <case PLUS_EXPR>: Test op0 and
> 	op1 separately for value- or type-dependence.
> 
> gcc/testsuite/ChangeLog:
> 
> 	PR c++/100161
> 	* g++.dg/warn/Wtype-limits6.C: New test.
> ---
>   gcc/cp/pt.c                               | 24 ++++++++++++++---------
>   gcc/testsuite/g++.dg/warn/Wtype-limits6.C | 17 ++++++++++++++++
>   2 files changed, 32 insertions(+), 9 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/warn/Wtype-limits6.C
> 
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index 7bcbe6dc3ce..8d64fef957d 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -19906,15 +19906,21 @@ tsubst_copy_and_build (tree t,
>       case MEMBER_REF:
>       case DOTSTAR_EXPR:
>         {
> -	/* If T was type-dependent, suppress warnings that depend on the range
> -	   of the types involved.  */
> -	++processing_template_decl;
> -	const bool was_dep = (potential_constant_expression (t)
> -			      ? value_dependent_expression_p (t)
> -			      : type_dependent_expression_p (t));
> -	--processing_template_decl;
> -	tree op0 = RECUR (TREE_OPERAND (t, 0));
> -	tree op1 = RECUR (TREE_OPERAND (t, 1));
> +	/* If either OP0 or OP1 was value- or type-dependent, suppress
> +	   warnings that depend on the range of the types involved.  */
> +	tree op0 = TREE_OPERAND (t, 0);
> +	tree op1 = TREE_OPERAND (t, 1);
> +	auto dep_p = [](tree t) {
> +	  ++processing_template_decl;
> +	  bool r = (potential_constant_expression (t)
> +		    ? value_dependent_expression_p (t)
> +		    : type_dependent_expression_p (t));
> +	  --processing_template_decl;
> +	  return r;
> +	};
> +	const bool was_dep = dep_p (op0) || dep_p (op1);
> +	op0 = RECUR (op0);
> +	op1 = RECUR (op1);
>   
>   	warning_sentinel s1(warn_type_limits, was_dep);
>   	warning_sentinel s2(warn_div_by_zero, was_dep);
> diff --git a/gcc/testsuite/g++.dg/warn/Wtype-limits6.C b/gcc/testsuite/g++.dg/warn/Wtype-limits6.C
> new file mode 100644
> index 00000000000..9d5886d5323
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/warn/Wtype-limits6.C
> @@ -0,0 +1,17 @@
> +// PR c++/100161
> +// { dg-additional-options "-Wtype-limits" }
> +
> +void f(unsigned);
> +
> +template<unsigned n>
> +void g()
> +{
> +    for (unsigned i = 0; i < n; i++) { // { dg-bogus "always false" }
> +        f(i);
> +    }
> +}
> +
> +void h()
> +{
> +    g<0>();
> +}
> 
> base-commit: 5491da23088734d516aae220810f253b9922c98c
>
Marek Polacek April 21, 2021, 5:30 p.m. UTC | #2
On Tue, Apr 20, 2021 at 10:40:52PM -0400, Jason Merrill wrote:
> On 4/20/21 8:42 PM, Marek Polacek wrote:
> > Recently, we made sure that we never call value_dependent_expression_p
> > on an expression that isn't potential_constant_expression.  That caused
> > this bogus warning with a non-type template parameter, something that
> > users don't want to see.
> > 
> > The problem is that in tsubst_copy_and_build/LE_EXPR 't' is "i < n",
> > which, due to 'i', is not p_c_e, therefore we call t_d_e_p.  But the
> > type of 'n' isn't dependent, so we think the whole 't' expression is
> > not dependent.  It seems we need to test both op0 and op1 separately
> > to suppress this warning.  I use a lambda so as not to repeat the
> > check.
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11.2?
> > Think I also want to backport to 10.4, but then the patch can't use
> > a lambda.
> 
> It should be straightforward to rewrite the lambda as a local class; let's
> use that version for all the branches.

I was thinking that I'd use a lambda for GCC 11 and 12 and for GCC 10
play some functor games, but I can use the following for all three, if
you want.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11.2/10.4?

-- >8 --
Recently, we made sure that we never call value_dependent_expression_p
on an expression that isn't potential_constant_expression.  That caused
this bogus warning with a non-type template parameter, something that
users don't want to see.

The problem is that in tsubst_copy_and_build/LE_EXPR 't' is "i < n",
which, due to 'i', is not p_c_e, therefore we call t_d_e_p.  But the
type of 'n' isn't dependent, so we think the whole 't' expression is
not dependent.  It seems we need to test both op0 and op1 separately
to suppress this warning.

gcc/cp/ChangeLog:

	PR c++/100161
	* pt.c (tsubst_copy_and_build) <case PLUS_EXPR>: Test op0 and
	op1 separately for value- or type-dependence.

gcc/testsuite/ChangeLog:

	PR c++/100161
	* g++.dg/warn/Wtype-limits6.C: New test.
---
 gcc/cp/pt.c                               | 26 +++++++++++++++--------
 gcc/testsuite/g++.dg/warn/Wtype-limits6.C | 17 +++++++++++++++
 2 files changed, 34 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/warn/Wtype-limits6.C

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 7bcbe6dc3ce..c1acfc498b1 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -19906,15 +19906,23 @@ tsubst_copy_and_build (tree t,
     case MEMBER_REF:
     case DOTSTAR_EXPR:
       {
-	/* If T was type-dependent, suppress warnings that depend on the range
-	   of the types involved.  */
-	++processing_template_decl;
-	const bool was_dep = (potential_constant_expression (t)
-			      ? value_dependent_expression_p (t)
-			      : type_dependent_expression_p (t));
-	--processing_template_decl;
-	tree op0 = RECUR (TREE_OPERAND (t, 0));
-	tree op1 = RECUR (TREE_OPERAND (t, 1));
+	/* If either OP0 or OP1 was value- or type-dependent, suppress
+	   warnings that depend on the range of the types involved.  */
+	tree op0 = TREE_OPERAND (t, 0);
+	tree op1 = TREE_OPERAND (t, 1);
+	struct {
+	  inline bool operator()(tree t) const {
+	    ++processing_template_decl;
+	    bool r = (potential_constant_expression (t)
+		      ? value_dependent_expression_p (t)
+		      : type_dependent_expression_p (t));
+	    --processing_template_decl;
+	    return r;
+	  };
+	} dep_p;
+	const bool was_dep = dep_p (op0) || dep_p (op1);
+	op0 = RECUR (op0);
+	op1 = RECUR (op1);
 
 	warning_sentinel s1(warn_type_limits, was_dep);
 	warning_sentinel s2(warn_div_by_zero, was_dep);
diff --git a/gcc/testsuite/g++.dg/warn/Wtype-limits6.C b/gcc/testsuite/g++.dg/warn/Wtype-limits6.C
new file mode 100644
index 00000000000..9d5886d5323
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wtype-limits6.C
@@ -0,0 +1,17 @@
+// PR c++/100161
+// { dg-additional-options "-Wtype-limits" }
+
+void f(unsigned);
+
+template<unsigned n>
+void g()
+{
+    for (unsigned i = 0; i < n; i++) { // { dg-bogus "always false" }
+        f(i);
+    }
+}
+
+void h()
+{
+    g<0>();
+}

base-commit: c2fc1702cb3a3d5cc9c40de47f63b4c8f3f1d09c
Jason Merrill April 22, 2021, 1:17 a.m. UTC | #3
On 4/21/21 1:30 PM, Marek Polacek wrote:
> On Tue, Apr 20, 2021 at 10:40:52PM -0400, Jason Merrill wrote:
>> On 4/20/21 8:42 PM, Marek Polacek wrote:
>>> Recently, we made sure that we never call value_dependent_expression_p
>>> on an expression that isn't potential_constant_expression.  That caused
>>> this bogus warning with a non-type template parameter, something that
>>> users don't want to see.
>>>
>>> The problem is that in tsubst_copy_and_build/LE_EXPR 't' is "i < n",
>>> which, due to 'i', is not p_c_e, therefore we call t_d_e_p.  But the
>>> type of 'n' isn't dependent, so we think the whole 't' expression is
>>> not dependent.  It seems we need to test both op0 and op1 separately
>>> to suppress this warning.  I use a lambda so as not to repeat the
>>> check.
>>>
>>> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11.2?
>>> Think I also want to backport to 10.4, but then the patch can't use
>>> a lambda.
>>
>> It should be straightforward to rewrite the lambda as a local class; let's
>> use that version for all the branches.
> 
> I was thinking that I'd use a lambda for GCC 11 and 12 and for GCC 10
> play some functor games, but I can use the following for all three, if
> you want.

Either is fine with me.

> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11.2/10.4?

OK.

> -- >8 --
> Recently, we made sure that we never call value_dependent_expression_p
> on an expression that isn't potential_constant_expression.  That caused
> this bogus warning with a non-type template parameter, something that
> users don't want to see.
> 
> The problem is that in tsubst_copy_and_build/LE_EXPR 't' is "i < n",
> which, due to 'i', is not p_c_e, therefore we call t_d_e_p.  But the
> type of 'n' isn't dependent, so we think the whole 't' expression is
> not dependent.  It seems we need to test both op0 and op1 separately
> to suppress this warning.
> 
> gcc/cp/ChangeLog:
> 
> 	PR c++/100161
> 	* pt.c (tsubst_copy_and_build) <case PLUS_EXPR>: Test op0 and
> 	op1 separately for value- or type-dependence.
> 
> gcc/testsuite/ChangeLog:
> 
> 	PR c++/100161
> 	* g++.dg/warn/Wtype-limits6.C: New test.
> ---
>   gcc/cp/pt.c                               | 26 +++++++++++++++--------
>   gcc/testsuite/g++.dg/warn/Wtype-limits6.C | 17 +++++++++++++++
>   2 files changed, 34 insertions(+), 9 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/warn/Wtype-limits6.C
> 
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index 7bcbe6dc3ce..c1acfc498b1 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -19906,15 +19906,23 @@ tsubst_copy_and_build (tree t,
>       case MEMBER_REF:
>       case DOTSTAR_EXPR:
>         {
> -	/* If T was type-dependent, suppress warnings that depend on the range
> -	   of the types involved.  */
> -	++processing_template_decl;
> -	const bool was_dep = (potential_constant_expression (t)
> -			      ? value_dependent_expression_p (t)
> -			      : type_dependent_expression_p (t));
> -	--processing_template_decl;
> -	tree op0 = RECUR (TREE_OPERAND (t, 0));
> -	tree op1 = RECUR (TREE_OPERAND (t, 1));
> +	/* If either OP0 or OP1 was value- or type-dependent, suppress
> +	   warnings that depend on the range of the types involved.  */
> +	tree op0 = TREE_OPERAND (t, 0);
> +	tree op1 = TREE_OPERAND (t, 1);
> +	struct {
> +	  inline bool operator()(tree t) const {
> +	    ++processing_template_decl;
> +	    bool r = (potential_constant_expression (t)
> +		      ? value_dependent_expression_p (t)
> +		      : type_dependent_expression_p (t));
> +	    --processing_template_decl;
> +	    return r;
> +	  };
> +	} dep_p;
> +	const bool was_dep = dep_p (op0) || dep_p (op1);
> +	op0 = RECUR (op0);
> +	op1 = RECUR (op1);
>   
>   	warning_sentinel s1(warn_type_limits, was_dep);
>   	warning_sentinel s2(warn_div_by_zero, was_dep);
> diff --git a/gcc/testsuite/g++.dg/warn/Wtype-limits6.C b/gcc/testsuite/g++.dg/warn/Wtype-limits6.C
> new file mode 100644
> index 00000000000..9d5886d5323
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/warn/Wtype-limits6.C
> @@ -0,0 +1,17 @@
> +// PR c++/100161
> +// { dg-additional-options "-Wtype-limits" }
> +
> +void f(unsigned);
> +
> +template<unsigned n>
> +void g()
> +{
> +    for (unsigned i = 0; i < n; i++) { // { dg-bogus "always false" }
> +        f(i);
> +    }
> +}
> +
> +void h()
> +{
> +    g<0>();
> +}
> 
> base-commit: c2fc1702cb3a3d5cc9c40de47f63b4c8f3f1d09c
>
diff mbox series

Patch

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 7bcbe6dc3ce..8d64fef957d 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -19906,15 +19906,21 @@  tsubst_copy_and_build (tree t,
     case MEMBER_REF:
     case DOTSTAR_EXPR:
       {
-	/* If T was type-dependent, suppress warnings that depend on the range
-	   of the types involved.  */
-	++processing_template_decl;
-	const bool was_dep = (potential_constant_expression (t)
-			      ? value_dependent_expression_p (t)
-			      : type_dependent_expression_p (t));
-	--processing_template_decl;
-	tree op0 = RECUR (TREE_OPERAND (t, 0));
-	tree op1 = RECUR (TREE_OPERAND (t, 1));
+	/* If either OP0 or OP1 was value- or type-dependent, suppress
+	   warnings that depend on the range of the types involved.  */
+	tree op0 = TREE_OPERAND (t, 0);
+	tree op1 = TREE_OPERAND (t, 1);
+	auto dep_p = [](tree t) {
+	  ++processing_template_decl;
+	  bool r = (potential_constant_expression (t)
+		    ? value_dependent_expression_p (t)
+		    : type_dependent_expression_p (t));
+	  --processing_template_decl;
+	  return r;
+	};
+	const bool was_dep = dep_p (op0) || dep_p (op1);
+	op0 = RECUR (op0);
+	op1 = RECUR (op1);
 
 	warning_sentinel s1(warn_type_limits, was_dep);
 	warning_sentinel s2(warn_div_by_zero, was_dep);
diff --git a/gcc/testsuite/g++.dg/warn/Wtype-limits6.C b/gcc/testsuite/g++.dg/warn/Wtype-limits6.C
new file mode 100644
index 00000000000..9d5886d5323
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wtype-limits6.C
@@ -0,0 +1,17 @@ 
+// PR c++/100161
+// { dg-additional-options "-Wtype-limits" }
+
+void f(unsigned);
+
+template<unsigned n>
+void g()
+{
+    for (unsigned i = 0; i < n; i++) { // { dg-bogus "always false" }
+        f(i);
+    }
+}
+
+void h()
+{
+    g<0>();
+}