c++: Fix ICE with -Wmismatched-tags [PR93869]

Message ID 20200221180620.192368-1-polacek@redhat.com
State New
Headers show
Series
  • c++: Fix ICE with -Wmismatched-tags [PR93869]
Related show

Commit Message

Marek Polacek Feb. 21, 2020, 6:06 p.m.
This is a crash in cp_parser_check_class_key:
  tree type_decl = TYPE_MAIN_DECL (type);
  tree name = DECL_NAME (type_decl); // HERE
because TYPE_MAIN_DECL of type was null as it's not a class type.
Instead of checking CLASS_TYPE_P we should simply check class_key
a bit earlier (in this case it was typename_type).

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2020-02-21  Marek Polacek  <polacek@redhat.com>

	PR c++/93869 - ICE with -Wmismatched-tags.
	* parser.c (cp_parser_check_class_key): Check class_key earlier.

	* g++.dg/warn/Wmismatched-tags-2.C: New test.
---
 gcc/cp/parser.c                                | 14 +++++++-------
 gcc/testsuite/g++.dg/warn/Wmismatched-tags-2.C |  6 ++++++
 2 files changed, 13 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/warn/Wmismatched-tags-2.C


base-commit: dbfba41e95d1d93b17e907b7f516b52ed3a3c415
-- 
Marek Polacek • Red Hat, Inc. • 300 A St, Boston, MA

Comments

Jason Merrill Feb. 24, 2020, 3:01 p.m. | #1
On 2/21/20 1:06 PM, Marek Polacek wrote:
> This is a crash in cp_parser_check_class_key:

>    tree type_decl = TYPE_MAIN_DECL (type);

>    tree name = DECL_NAME (type_decl); // HERE

> because TYPE_MAIN_DECL of type was null as it's not a class type.

> Instead of checking CLASS_TYPE_P we should simply check class_key

> a bit earlier (in this case it was typename_type).

> 

> Bootstrapped/regtested on x86_64-linux, ok for trunk?


OK.

> 2020-02-21  Marek Polacek  <polacek@redhat.com>

> 

> 	PR c++/93869 - ICE with -Wmismatched-tags.

> 	* parser.c (cp_parser_check_class_key): Check class_key earlier.

> 

> 	* g++.dg/warn/Wmismatched-tags-2.C: New test.

> ---

>   gcc/cp/parser.c                                | 14 +++++++-------

>   gcc/testsuite/g++.dg/warn/Wmismatched-tags-2.C |  6 ++++++

>   2 files changed, 13 insertions(+), 7 deletions(-)

>   create mode 100644 gcc/testsuite/g++.dg/warn/Wmismatched-tags-2.C

> 

> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c

> index ee534b5db21..d5f2c14d951 100644

> --- a/gcc/cp/parser.c

> +++ b/gcc/cp/parser.c

> @@ -30987,6 +30987,13 @@ cp_parser_check_class_key (cp_parser *parser, location_t key_loc,

>     if (!warn_mismatched_tags && !warn_redundant_tags)

>       return;

>   

> +  /* Only consider the true class-keys below and ignore typename_type,

> +     etc. that are not C++ class-keys.  */

> +  if (class_key != class_type

> +      && class_key != record_type

> +      && class_key != union_type)

> +    return;

> +

>     tree type_decl = TYPE_MAIN_DECL (type);

>     tree name = DECL_NAME (type_decl);

>     /* Look up the NAME to see if it unambiguously refers to the TYPE

> @@ -30995,13 +31002,6 @@ cp_parser_check_class_key (cp_parser *parser, location_t key_loc,

>     tree decl = cp_parser_lookup_name_simple (parser, name, input_location);

>     pop_deferring_access_checks ();

>   

> -  /* Only consider the true class-keys below and ignore typename_type,

> -     etc. that are not C++ class-keys.  */

> -  if (class_key != class_type

> -      && class_key != record_type

> -      && class_key != union_type)

> -    return;

> -

>     /* The class-key is redundant for uses of the CLASS_TYPE that are

>        neither definitions of it nor declarations, and for which name

>        lookup returns just the type itself.  */

> diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-tags-2.C b/gcc/testsuite/g++.dg/warn/Wmismatched-tags-2.C

> new file mode 100644

> index 00000000000..00193f02f61

> --- /dev/null

> +++ b/gcc/testsuite/g++.dg/warn/Wmismatched-tags-2.C

> @@ -0,0 +1,6 @@

> +// PR c++/93869 - ICE with -Wmismatched-tags.

> +// { dg-do compile }

> +// { dg-options "-Wmismatched-tags" }

> +

> +namespace N { typedef int T; }

> +typename N::T x;

> 

> base-commit: dbfba41e95d1d93b17e907b7f516b52ed3a3c415

>

Patch

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ee534b5db21..d5f2c14d951 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -30987,6 +30987,13 @@  cp_parser_check_class_key (cp_parser *parser, location_t key_loc,
   if (!warn_mismatched_tags && !warn_redundant_tags)
     return;
 
+  /* Only consider the true class-keys below and ignore typename_type,
+     etc. that are not C++ class-keys.  */
+  if (class_key != class_type
+      && class_key != record_type
+      && class_key != union_type)
+    return;
+
   tree type_decl = TYPE_MAIN_DECL (type);
   tree name = DECL_NAME (type_decl);
   /* Look up the NAME to see if it unambiguously refers to the TYPE
@@ -30995,13 +31002,6 @@  cp_parser_check_class_key (cp_parser *parser, location_t key_loc,
   tree decl = cp_parser_lookup_name_simple (parser, name, input_location);
   pop_deferring_access_checks ();
 
-  /* Only consider the true class-keys below and ignore typename_type,
-     etc. that are not C++ class-keys.  */
-  if (class_key != class_type
-      && class_key != record_type
-      && class_key != union_type)
-    return;
-
   /* The class-key is redundant for uses of the CLASS_TYPE that are
      neither definitions of it nor declarations, and for which name
      lookup returns just the type itself.  */
diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-tags-2.C b/gcc/testsuite/g++.dg/warn/Wmismatched-tags-2.C
new file mode 100644
index 00000000000..00193f02f61
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmismatched-tags-2.C
@@ -0,0 +1,6 @@ 
+// PR c++/93869 - ICE with -Wmismatched-tags.
+// { dg-do compile }
+// { dg-options "-Wmismatched-tags" }
+
+namespace N { typedef int T; }
+typename N::T x;