diff mbox series

c++: Fix ICE in check_local_shadow with enum [PR95560]

Message ID 20200610211148.1237792-1-polacek@redhat.com
State New
Headers show
Series c++: Fix ICE in check_local_shadow with enum [PR95560] | expand

Commit Message

Marek Polacek June 10, 2020, 9:11 p.m. UTC
Another indication that perhaps this warning is emitted too early.  We
crash because same_type_p gets a null type: we have an enumerator
without a fixed underlying type and finish_enum_value_list hasn't yet
run.  So check if the type is null before calling same_type_p.

(This is a regression and this fix is suitable for backporting.  Delaying
the warning would not be suitable to backport.)

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/10/9?

gcc/cp/ChangeLog:

	PR c++/95560
	* name-lookup.c (check_local_shadow): Check if types are
	non-null before calling same_type_p.

gcc/testsuite/ChangeLog:

	PR c++/95560
	* g++.dg/warn/Wshadow-local-3.C: New test.
---
 gcc/cp/name-lookup.c                        | 4 +++-
 gcc/testsuite/g++.dg/warn/Wshadow-local-3.C | 7 +++++++
 2 files changed, 10 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/warn/Wshadow-local-3.C


base-commit: 3a391adf7a38780f8d01dbac08a2a143fc80b469

Comments

Jason Merrill June 11, 2020, 7:32 p.m. UTC | #1
On 6/10/20 5:11 PM, Marek Polacek wrote:
> Another indication that perhaps this warning is emitted too early.  We
> crash because same_type_p gets a null type: we have an enumerator
> without a fixed underlying type and finish_enum_value_list hasn't yet
> run.  So check if the type is null before calling same_type_p.

Hmm, I wonder why we use NULL_TREE for the type of uninitialized 
enumerators in a template; why not give them integer_type_node temporarily?

> (This is a regression and this fix is suitable for backporting.  Delaying
> the warning would not be suitable to backport.)
> 
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/10/9?
> 
> gcc/cp/ChangeLog:
> 
> 	PR c++/95560
> 	* name-lookup.c (check_local_shadow): Check if types are
> 	non-null before calling same_type_p.
> 
> gcc/testsuite/ChangeLog:
> 
> 	PR c++/95560
> 	* g++.dg/warn/Wshadow-local-3.C: New test.
> ---
>   gcc/cp/name-lookup.c                        | 4 +++-
>   gcc/testsuite/g++.dg/warn/Wshadow-local-3.C | 7 +++++++
>   2 files changed, 10 insertions(+), 1 deletion(-)
>   create mode 100644 gcc/testsuite/g++.dg/warn/Wshadow-local-3.C
> 
> diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
> index 2ff85f1cf5e..159c98a67cd 100644
> --- a/gcc/cp/name-lookup.c
> +++ b/gcc/cp/name-lookup.c
> @@ -2762,7 +2762,9 @@ check_local_shadow (tree decl)
>         enum opt_code warning_code;
>         if (warn_shadow)
>   	warning_code = OPT_Wshadow;
> -      else if (same_type_p (TREE_TYPE (old), TREE_TYPE (decl))
> +      else if ((TREE_TYPE (old)
> +		&& TREE_TYPE (decl)
> +		&& same_type_p (TREE_TYPE (old), TREE_TYPE (decl)))
>   	       || TREE_CODE (decl) == TYPE_DECL
>   	       || TREE_CODE (old) == TYPE_DECL
>   	       || (!dependent_type_p (TREE_TYPE (decl))
> diff --git a/gcc/testsuite/g++.dg/warn/Wshadow-local-3.C b/gcc/testsuite/g++.dg/warn/Wshadow-local-3.C
> new file mode 100644
> index 00000000000..fd743eca347
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/warn/Wshadow-local-3.C
> @@ -0,0 +1,7 @@
> +// PR c++/95560
> +// { dg-do compile { target c++11 } }
> +
> +template <typename> void fn1() {
> +  bool ready;
> +  enum class State { ready };
> +}
> 
> base-commit: 3a391adf7a38780f8d01dbac08a2a143fc80b469
>
Jason Merrill June 11, 2020, 7:34 p.m. UTC | #2
On 6/11/20 3:32 PM, Jason Merrill wrote:
> On 6/10/20 5:11 PM, Marek Polacek wrote:
>> Another indication that perhaps this warning is emitted too early.  We
>> crash because same_type_p gets a null type: we have an enumerator
>> without a fixed underlying type and finish_enum_value_list hasn't yet
>> run.  So check if the type is null before calling same_type_p.
> 
> Hmm, I wonder why we use NULL_TREE for the type of uninitialized 
> enumerators in a template; why not give them integer_type_node temporarily?

But this patch is OK for 10.2.

>> (This is a regression and this fix is suitable for backporting.  Delaying
>> the warning would not be suitable to backport.)
>>
>> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/10/9?
>>
>> gcc/cp/ChangeLog:
>>
>>     PR c++/95560
>>     * name-lookup.c (check_local_shadow): Check if types are
>>     non-null before calling same_type_p.
>>
>> gcc/testsuite/ChangeLog:
>>
>>     PR c++/95560
>>     * g++.dg/warn/Wshadow-local-3.C: New test.
>> ---
>>   gcc/cp/name-lookup.c                        | 4 +++-
>>   gcc/testsuite/g++.dg/warn/Wshadow-local-3.C | 7 +++++++
>>   2 files changed, 10 insertions(+), 1 deletion(-)
>>   create mode 100644 gcc/testsuite/g++.dg/warn/Wshadow-local-3.C
>>
>> diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
>> index 2ff85f1cf5e..159c98a67cd 100644
>> --- a/gcc/cp/name-lookup.c
>> +++ b/gcc/cp/name-lookup.c
>> @@ -2762,7 +2762,9 @@ check_local_shadow (tree decl)
>>         enum opt_code warning_code;
>>         if (warn_shadow)
>>       warning_code = OPT_Wshadow;
>> -      else if (same_type_p (TREE_TYPE (old), TREE_TYPE (decl))
>> +      else if ((TREE_TYPE (old)
>> +        && TREE_TYPE (decl)
>> +        && same_type_p (TREE_TYPE (old), TREE_TYPE (decl)))
>>              || TREE_CODE (decl) == TYPE_DECL
>>              || TREE_CODE (old) == TYPE_DECL
>>              || (!dependent_type_p (TREE_TYPE (decl))
>> diff --git a/gcc/testsuite/g++.dg/warn/Wshadow-local-3.C 
>> b/gcc/testsuite/g++.dg/warn/Wshadow-local-3.C
>> new file mode 100644
>> index 00000000000..fd743eca347
>> --- /dev/null
>> +++ b/gcc/testsuite/g++.dg/warn/Wshadow-local-3.C
>> @@ -0,0 +1,7 @@
>> +// PR c++/95560
>> +// { dg-do compile { target c++11 } }
>> +
>> +template <typename> void fn1() {
>> +  bool ready;
>> +  enum class State { ready };
>> +}
>>
>> base-commit: 3a391adf7a38780f8d01dbac08a2a143fc80b469
>>
>
Jason Merrill June 11, 2020, 7:34 p.m. UTC | #3
On 6/11/20 3:34 PM, Jason Merrill wrote:
> On 6/11/20 3:32 PM, Jason Merrill wrote:
>> On 6/10/20 5:11 PM, Marek Polacek wrote:
>>> Another indication that perhaps this warning is emitted too early.  We
>>> crash because same_type_p gets a null type: we have an enumerator
>>> without a fixed underlying type and finish_enum_value_list hasn't yet
>>> run.  So check if the type is null before calling same_type_p.
>>
>> Hmm, I wonder why we use NULL_TREE for the type of uninitialized 
>> enumerators in a template; why not give them integer_type_node 
>> temporarily?
> 
> But this patch is OK for 10.2.

And 9.

> 
>>> (This is a regression and this fix is suitable for backporting.  
>>> Delaying
>>> the warning would not be suitable to backport.)
>>>
>>> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/10/9?
>>>
>>> gcc/cp/ChangeLog:
>>>
>>>     PR c++/95560
>>>     * name-lookup.c (check_local_shadow): Check if types are
>>>     non-null before calling same_type_p.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>>     PR c++/95560
>>>     * g++.dg/warn/Wshadow-local-3.C: New test.
>>> ---
>>>   gcc/cp/name-lookup.c                        | 4 +++-
>>>   gcc/testsuite/g++.dg/warn/Wshadow-local-3.C | 7 +++++++
>>>   2 files changed, 10 insertions(+), 1 deletion(-)
>>>   create mode 100644 gcc/testsuite/g++.dg/warn/Wshadow-local-3.C
>>>
>>> diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
>>> index 2ff85f1cf5e..159c98a67cd 100644
>>> --- a/gcc/cp/name-lookup.c
>>> +++ b/gcc/cp/name-lookup.c
>>> @@ -2762,7 +2762,9 @@ check_local_shadow (tree decl)
>>>         enum opt_code warning_code;
>>>         if (warn_shadow)
>>>       warning_code = OPT_Wshadow;
>>> -      else if (same_type_p (TREE_TYPE (old), TREE_TYPE (decl))
>>> +      else if ((TREE_TYPE (old)
>>> +        && TREE_TYPE (decl)
>>> +        && same_type_p (TREE_TYPE (old), TREE_TYPE (decl)))
>>>              || TREE_CODE (decl) == TYPE_DECL
>>>              || TREE_CODE (old) == TYPE_DECL
>>>              || (!dependent_type_p (TREE_TYPE (decl))
>>> diff --git a/gcc/testsuite/g++.dg/warn/Wshadow-local-3.C 
>>> b/gcc/testsuite/g++.dg/warn/Wshadow-local-3.C
>>> new file mode 100644
>>> index 00000000000..fd743eca347
>>> --- /dev/null
>>> +++ b/gcc/testsuite/g++.dg/warn/Wshadow-local-3.C
>>> @@ -0,0 +1,7 @@
>>> +// PR c++/95560
>>> +// { dg-do compile { target c++11 } }
>>> +
>>> +template <typename> void fn1() {
>>> +  bool ready;
>>> +  enum class State { ready };
>>> +}
>>>
>>> base-commit: 3a391adf7a38780f8d01dbac08a2a143fc80b469
>>>
>>
>
Marek Polacek June 16, 2020, 1:20 a.m. UTC | #4
On Thu, Jun 11, 2020 at 03:32:14PM -0400, Jason Merrill wrote:
> On 6/10/20 5:11 PM, Marek Polacek wrote:
> > Another indication that perhaps this warning is emitted too early.  We
> > crash because same_type_p gets a null type: we have an enumerator
> > without a fixed underlying type and finish_enum_value_list hasn't yet
> > run.  So check if the type is null before calling same_type_p.
> 
> Hmm, I wonder why we use NULL_TREE for the type of uninitialized enumerators
> in a template; why not give them integer_type_node temporarily?

That breaks enum22.C:

  template <class T>
  struct A {
    enum e_ : unsigned char { Z_, E_=sizeof(Z_) };
  };

  static_assert ( A<double>::E_ == 1, "E_ should be 1");

If we give 'Z_' a type, it's no longer instantiation-dependent, so sizeof(Z_)
immediately evaluates to 4.  Whereas if it doesn't have a type, in the template
we create a SIZEOF_EXPR and only evaluate when instantiating (to 1).

This sounded like a problem big enough for me not to pursue this any further.
Do you want me to try anything else or is the original patch ok?

Marek
Jason Merrill June 16, 2020, 4:06 p.m. UTC | #5
On 6/15/20 9:20 PM, Marek Polacek wrote:
> On Thu, Jun 11, 2020 at 03:32:14PM -0400, Jason Merrill wrote:
>> On 6/10/20 5:11 PM, Marek Polacek wrote:
>>> Another indication that perhaps this warning is emitted too early.  We
>>> crash because same_type_p gets a null type: we have an enumerator
>>> without a fixed underlying type and finish_enum_value_list hasn't yet
>>> run.  So check if the type is null before calling same_type_p.
>>
>> Hmm, I wonder why we use NULL_TREE for the type of uninitialized enumerators
>> in a template; why not give them integer_type_node temporarily?
> 
> That breaks enum22.C:
> 
>    template <class T>
>    struct A {
>      enum e_ : unsigned char { Z_, E_=sizeof(Z_) };
>    };
> 
>    static_assert ( A<double>::E_ == 1, "E_ should be 1");
> 
> If we give 'Z_' a type, it's no longer instantiation-dependent, so sizeof(Z_)
> immediately evaluates to 4.  Whereas if it doesn't have a type, in the template
> we create a SIZEOF_EXPR and only evaluate when instantiating (to 1).
> 
> This sounded like a problem big enough for me not to pursue this any further.
> Do you want me to try anything else or is the original patch ok?

The original patch is OK, thanks.

Jason
diff mbox series

Patch

diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 2ff85f1cf5e..159c98a67cd 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -2762,7 +2762,9 @@  check_local_shadow (tree decl)
       enum opt_code warning_code;
       if (warn_shadow)
 	warning_code = OPT_Wshadow;
-      else if (same_type_p (TREE_TYPE (old), TREE_TYPE (decl))
+      else if ((TREE_TYPE (old)
+		&& TREE_TYPE (decl)
+		&& same_type_p (TREE_TYPE (old), TREE_TYPE (decl)))
 	       || TREE_CODE (decl) == TYPE_DECL
 	       || TREE_CODE (old) == TYPE_DECL
 	       || (!dependent_type_p (TREE_TYPE (decl))
diff --git a/gcc/testsuite/g++.dg/warn/Wshadow-local-3.C b/gcc/testsuite/g++.dg/warn/Wshadow-local-3.C
new file mode 100644
index 00000000000..fd743eca347
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wshadow-local-3.C
@@ -0,0 +1,7 @@ 
+// PR c++/95560
+// { dg-do compile { target c++11 } }
+
+template <typename> void fn1() {
+  bool ready;
+  enum class State { ready };
+}