Bug 91706 - [10 Regression] ICE: tree check: expected class 'type', have 'exceptional' (error_mark) in equate_type_number_to_die, at dwarf2out.c:5782
Summary: [10 Regression] ICE: tree check: expected class 'type', have 'exceptional' (e...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 10.0
: P2 normal
Target Milestone: 11.2
Assignee: Jason Merrill
URL:
Keywords: accepts-invalid, ice-on-valid-code
Depends on: 101078
Blocks:
  Show dependency treegraph
 
Reported: 2019-09-09 08:24 UTC by Szőts Ákos
Modified: 2023-07-07 08:34 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work: 11.2.0
Known to fail: 10.5.0, 11.1.0
Last reconfirmed: 2019-09-09 00:00:00


Attachments
near fix (1.20 KB, patch)
2021-04-20 04:40 UTC, Jason Merrill
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Szőts Ákos 2019-09-09 08:24:15 UTC
The following test case causes internal compiler error:

#include <type_traits>
#include <vector>

struct A {
  template <typename>
  static std::false_type fn(...);
};

template <class T>
struct B : public A  {
  using fn = decltype(fn<T>(0));
  using type = typename std::conditional<fn::value, std::true_type, std::false_type>::type;
};

int main(){
  static_assert(B<std::vector<int>>::type::value, "assertion failed");
}

If you change either of them, the bug will go away:
- Move A::fn() out of its structure thus make "B : public A" inheritance unnecessary
- Rename B::fn to something else, like B::fn_alias.

The issue first appeared in 8.1 (7.4 is fine) and still occurs with 10.0.0 20190908.

Error messages:

GCC 10.0:
internal compiler error: tree check: expected class 'type', have 'exceptional' (error_mark) in equate_type_number_to_die, at dwarf2out.c:5782

9.2 - 8.1:
internal compiler error: in is_base_type, at dwarf2out.c:12987

Related issue: Bug 87772 (though I don't know whether the path is the same which led to a similar ICE message).
Comment 1 Richard Biener 2019-09-09 10:44:38 UTC
Confirmed.

The struct B type has a member

 <type_decl 0x7ffff5e2eed8 type type <error_mark 0x7ffff680de40>
    asm_written external nonlocal suppress-debug decl_6 VOID t.C:12:9
    align:8 warn_if_not_align:0 context <record_type 0x7ffff60a8888 B>
    result <typename_type 0x7ffff60a8150 type VOID
        align:8 warn_if_not_align:0 symtab:0 alias-set -1 structural-equality context <record_type 0x7ffff6098f18 conditional>
        fullname <identifier_node 0x7ffff6826f00 type type <error_mark 0x7ffff680de40>
           
            normal local bindings <0x7ffff5d40be0>>
        chain <type_decl 0x7ffff5e2e000 type>>
   >

which we don't expect.  Frontend issue.  It should have raised an error here?

> clang++ t.C
t.C:16:3: error: static_assert failed due to requirement 'B<std::vector<int>
      >::type::value' "assertion failed"
  static_assert(B<std::vector<int>>::type::value, "assertion failed");
  ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.


The ICE with GCC 9 is the same

note DECL_ORGINAL_TYPE is "sane" (well, 'void').  And dwarf2out has

25421     if (DECL_ORIGINAL_TYPE (decl))
25422       {
25423         type = DECL_ORIGINAL_TYPE (decl);
25424         if (type == error_mark_node)
25425           return;
25426
25427         gcc_assert (type != TREE_TYPE (decl));
25428         equate_type_number_to_die (TREE_TYPE (decl), type_die);

so it checks DECL_ORIGINAL_TYPE but then uses TREE_TYPE which actually
is error_mark_node.
Comment 2 Martin Liška 2019-09-09 11:05:14 UTC
Started with r251438.
Comment 3 Jakub Jelinek 2019-11-20 17:49:11 UTC
template <bool> struct A;
template <typename = int> struct B;
struct C {
  template <typename> static int c ();
};
template <class T> struct D : C {
  using c = decltype (c<T>);
  using E = typename A<c::g>::E;
};
D<B<>> g;

Without -g this is a accepts-invalid.
Comment 4 Jakub Jelinek 2020-03-04 09:50:08 UTC
GCC 8.4.0 has been released, adjusting target milestone.
Comment 5 Patrick Palka 2020-04-24 14:56:32 UTC
Slightly more reduced testcase:


template <bool> struct A;

struct C {
  template <typename> static int c ();
};

template <class T> struct D : C {
  using c = decltype (c<T>);
  using E = A<c::g>;
};

D<int> g;
Comment 6 Jason Merrill 2021-04-16 16:07:39 UTC
Valid variant:

template <bool> struct A;

struct B { static constexpr bool g = false; };

struct C {
  template <typename> static B c ();
};

template <class T> struct D : C {
  using c = decltype (c<T>());
  using E = A<c::g>;
};

D<int> g;

This is a complex interaction of issues.  Looking up c<T> in the definition of D::c finds C::c, OK.  Looking up c in the definition of E finds D::c, which is depedent, OK.  Since the alias is not dependent, we strip it from the template argument, leaving

using E = A<decltype(c<T>())>;

where 'c' still refers to C::c.  But instantiating E looks up 'c' again and finds D::c, which isn't a function, so things go wrong.

I think the bug here is looking up 'c' in D at instantiation time; the declaration we found before is not dependent.
Comment 7 Jason Merrill 2021-04-20 04:40:15 UTC
Created attachment 50632 [details]
near fix

This seemed like a fix, but it breaks the modules/merge-8 testcase, and debugging that is being slow.
Comment 8 Jakub Jelinek 2021-05-14 09:52:09 UTC
GCC 8 branch is being closed.
Comment 9 Richard Biener 2021-06-01 08:15:14 UTC
GCC 9.4 is being released, retargeting bugs to GCC 9.5.
Comment 10 GCC Commits 2021-06-08 03:56:57 UTC
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:f07edb5d7f3e77218ec846a9382f7c1d23e67b71

commit r12-1272-gf07edb5d7f3e77218ec846a9382f7c1d23e67b71
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Apr 16 11:13:40 2021 -0400

    c++: alias with same name as base fn [PR91706]
    
    This is a bit complex.  Looking up c<T> in the definition of D::c finds
    C::c, OK.  Looking up c in the definition of E finds D::c, OK.  Since the
    alias is not dependent, we strip it from the template argument, leaving
    
    using E = A<decltype(c<T>())>;
    
    where 'c' still refers to C::c.  But instantiating E looks up 'c' again and
    finds D::c, which isn't a function, and sadness ensues.
    
    I think the bug here is looking up 'c' in D at instantiation time; the
    declaration we found before is not dependent.  This seems to happen because
    baselink_for_fns gets BASELINK_BINFO wrong; it is supposed to be the base
    where lookup found the functions, C in this case.
    
    gcc/cp/ChangeLog:
    
            PR c++/91706
            * semantics.c (baselink_for_fns): Fix BASELINK_BINFO.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/91706
            * g++.dg/template/lookup17.C: New test.
Comment 11 GCC Commits 2021-06-08 03:56:59 UTC
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:1a98f830332e5a623278aaeea39c2a88177b2a9a

commit r12-1273-g1a98f830332e5a623278aaeea39c2a88177b2a9a
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Apr 16 13:52:02 2021 -0400

    c++: preserve BASELINK from lookup [PR91706]
    
    In the earlier patch for PR91706 I fixed the BASELINK built by
    baselink_for_fns, but since we already had one from lookup, we should keep
    that one around instead of stripping it.  The removed hunk in
    get_class_binding was a wierdly large amount of code to decide whether to
    pull out BASELINK_FUNCTIONS.
    
    gcc/cp/ChangeLog:
    
            PR c++/91706
            * name-lookup.c (get_class_binding): Keep a BASELINK.
            (set_inherited_value_binding_p): Adjust.
            * lambda.c (is_lambda_ignored_entity): Adjust.
            * pt.c (lookup_template_function): Copy a BASELINK before
            modifying it.
Comment 12 GCC Commits 2021-06-08 13:24:31 UTC
The releases/gcc-11 branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:46c1a9f6d03ab444b42c41067597e3fbfba38486

commit r11-8524-g46c1a9f6d03ab444b42c41067597e3fbfba38486
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Apr 16 11:13:40 2021 -0400

    c++: alias with same name as base fn [PR91706]
    
    This is a bit complex.  Looking up c<T> in the definition of D::c finds
    C::c, OK.  Looking up c in the definition of E finds D::c, OK.  Since the
    alias is not dependent, we strip it from the template argument, leaving
    
    using E = A<decltype(c<T>())>;
    
    where 'c' still refers to C::c.  But instantiating E looks up 'c' again and
    finds D::c, which isn't a function, and sadness ensues.
    
    I think the bug here is looking up 'c' in D at instantiation time; the
    declaration we found before is not dependent.  This seems to happen because
    baselink_for_fns gets BASELINK_BINFO wrong; it is supposed to be the base
    where lookup found the functions, C in this case.
    
    gcc/cp/ChangeLog:
    
            PR c++/91706
            * semantics.c (baselink_for_fns): Fix BASELINK_BINFO.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/91706
            * g++.dg/template/lookup17.C: New test.
Comment 13 Jason Merrill 2021-06-08 21:20:29 UTC
Fixed for 11.2/12 so far.  Is there interest in fixing this on the 9/10 branches?
Comment 14 GCC Commits 2021-06-16 21:29:01 UTC
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:6816a44dfe1b5fa9414490a18a4aa723b6f38f18

commit r12-1543-g6816a44dfe1b5fa9414490a18a4aa723b6f38f18
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Jun 16 16:09:59 2021 -0400

    c++: static memfn from non-dependent base [PR101078]
    
    After my patch for PR91706, or before that with the qualified call,
    tsubst_baselink returned a BASELINK with BASELINK_BINFO indicating a base of
    a still-dependent derived class.  We need to look up the relevant base binfo
    in the substituted class.
    
            PR c++/101078
            PR c++/91706
    
    gcc/cp/ChangeLog:
    
            * pt.c (tsubst_baselink): Update binfos in non-dependent case.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/template/access39.C: New test.
Comment 15 Richard Biener 2022-05-27 09:41:20 UTC
GCC 9 branch is being closed
Comment 16 Jakub Jelinek 2022-06-28 10:38:23 UTC
GCC 10.4 is being released, retargeting bugs to GCC 10.5.
Comment 17 Richard Biener 2023-07-07 08:34:10 UTC
Fixed in GCC 11.2