Message ID | 20220527154647.39582-1-polacek@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: Fix ICE with -Wmismatched-tags [PR105725] | expand |
On 5/27/22 11:46, Marek Polacek wrote: > Here we ICE with -Wmismatched-tags on something like > > template <class T> > bool B<T, enable_if_t<is_class_v<class T::foo>>>; > > Specifically, the "class T::foo" bit. There, class_decl_loc_t::add gets > a TYPENAME_TYPE as TYPE, rather than a class/union type, so checking > TYPE_BEING_DEFINED will crash. I think it's OK to allow a TYPENAME_TYPE to > slip into that function; we just shouldn't consider the 'class' tag redundant > (which works as a 'typename'). In fact, every other compiler *requires* it. > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? OK. > PR c++/105725 > > gcc/cp/ChangeLog: > > * parser.cc (class_decl_loc_t::add): Check CLASS_TYPE_P. > > gcc/testsuite/ChangeLog: > > * g++.dg/warn/Wmismatched-tags-10.C: New test. > --- > gcc/cp/parser.cc | 5 +++-- > gcc/testsuite/g++.dg/warn/Wmismatched-tags-10.C | 10 ++++++++++ > 2 files changed, 13 insertions(+), 2 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/warn/Wmismatched-tags-10.C > > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc > index 4b9859543ed..9a9f859974a 100644 > --- a/gcc/cp/parser.cc > +++ b/gcc/cp/parser.cc > @@ -33666,7 +33666,8 @@ class_decl_loc_t::add (cp_parser *parser, location_t key_loc, > bool key_redundant = (!def_p && !decl_p > && (decl == type_decl > || TREE_CODE (decl) == TEMPLATE_DECL > - || TYPE_BEING_DEFINED (type))); > + || (CLASS_TYPE_P (type) > + && TYPE_BEING_DEFINED (type)))); > > if (key_redundant > && class_key != class_type > @@ -33704,7 +33705,7 @@ class_decl_loc_t::add (cp_parser *parser, location_t key_loc, > } > else > { > - /* TYPE was previously defined in some unknown precompiled hdeader. > + /* TYPE was previously defined in some unknown precompiled header. > Simply add a record of its definition at an unknown location and > proceed below to add a reference to it at the current location. > (Declarations in precompiled headers that are not definitions > diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-tags-10.C b/gcc/testsuite/g++.dg/warn/Wmismatched-tags-10.C > new file mode 100644 > index 00000000000..d7e10743bb4 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/warn/Wmismatched-tags-10.C > @@ -0,0 +1,10 @@ > +// PR c++/105725 > +// { dg-do compile { target c++14 } } > +// { dg-options "-Wall -Wmismatched-tags" } > + > +template <bool> struct enable_if; > +template <bool Cond> using enable_if_t = typename enable_if<Cond>::type; > +template <typename> bool is_class_v; > +template <class, class> bool B; > +template <class T> > +bool B<T, enable_if_t<is_class_v<class T::foo>>>; > > base-commit: de57440858591a88e8fd7ba2505ca54546c86021
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 4b9859543ed..9a9f859974a 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -33666,7 +33666,8 @@ class_decl_loc_t::add (cp_parser *parser, location_t key_loc, bool key_redundant = (!def_p && !decl_p && (decl == type_decl || TREE_CODE (decl) == TEMPLATE_DECL - || TYPE_BEING_DEFINED (type))); + || (CLASS_TYPE_P (type) + && TYPE_BEING_DEFINED (type)))); if (key_redundant && class_key != class_type @@ -33704,7 +33705,7 @@ class_decl_loc_t::add (cp_parser *parser, location_t key_loc, } else { - /* TYPE was previously defined in some unknown precompiled hdeader. + /* TYPE was previously defined in some unknown precompiled header. Simply add a record of its definition at an unknown location and proceed below to add a reference to it at the current location. (Declarations in precompiled headers that are not definitions diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-tags-10.C b/gcc/testsuite/g++.dg/warn/Wmismatched-tags-10.C new file mode 100644 index 00000000000..d7e10743bb4 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wmismatched-tags-10.C @@ -0,0 +1,10 @@ +// PR c++/105725 +// { dg-do compile { target c++14 } } +// { dg-options "-Wall -Wmismatched-tags" } + +template <bool> struct enable_if; +template <bool Cond> using enable_if_t = typename enable_if<Cond>::type; +template <typename> bool is_class_v; +template <class, class> bool B; +template <class T> +bool B<T, enable_if_t<is_class_v<class T::foo>>>;