https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90799

            Bug ID: 90799
           Summary: noexcept specification dependent on template argument
                    throws internal compiler error when trying to deduce
                    it from a function argument
           Product: gcc
           Version: 9.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: franwade33 at googlemail dot com
  Target Milestone: ---

If you have a non-type template argument `bool is_noexcept` that is deduced
from `noexcept(is_noexcept)` on a function pointer / member function pointer,
it gives an internal compiler error if the function was instantiated from a
template and the noexcept specifier is dependent on a template parameter.

For example, the following compiled with or without `-DMEMBER` both give the
same output:

    template<class T>
    void foo() noexcept(T::value);

    struct S {
        static constexpr const bool value = true;

        template<class T>
        void bar() noexcept(T::value);
    };

    template<class... Args, bool is_noexcept>
    constexpr bool is_noexcept_function(void(Args...) noexcept(is_noexcept))
noexcept {
        return is_noexcept;
    }

    template<class... Args, bool is_noexcept>
    constexpr bool is_noexcept_member_function(void(S::*)(Args...)
noexcept(is_noexcept)) noexcept {
        return is_noexcept;
    }

    #ifdef MEMBER
    static_assert(is_noexcept_member_function(&S::bar<S>));
    #else
    static_assert(is_noexcept_function(foo<S>));
    #endif

Expected behaviour:

Nothing happens (static_assert is successful, as `is_noexcept` is deduced to be
true) in both cases.

Actual behaviour:

(Error with `g++ -std=c++17`)

    test.cpp: In substitution of 'template<class ... Args, bool is_noexcept>
constexpr bool is_noexcept_function(void (*)(Args ...) noexcept (is_noexcept))
[with Args = <missing>; bool is_noexcept = <missing>]':
    test.cpp:24:42:   required from here
    test.cpp:24:42: internal compiler error: in structural_comptypes, at
cp/typeck.c:1236
       24 | static_assert(is_noexcept_function(foo<S>));
          |                                          ^
    Please submit a full bug report,
    with preprocessed source if appropriate.
    See <https://gcc.gnu.org/bugs/> for instructions.

(Error with `g++ -std=c++17 -DMEMBER`)

    test.cpp: In substitution of 'template<class ... Args, bool is_noexcept>
constexpr bool is_noexcept_member_function(void (S::*)(Args ...) noexcept
(is_noexcept)) [with Args = <missing>; bool is_noexcept = <missing>]':
    test.cpp:22:53:   required from here
    test.cpp:22:53: internal compiler error: in structural_comptypes, at
cp/typeck.c:1236
       22 | static_assert(is_noexcept_member_function(&S::bar<S>));
          |                                                     ^
    Please submit a full bug report,
    with preprocessed source if appropriate.
    See <https://gcc.gnu.org/bugs/> for instructions.

There also seems to be a problem deducing argument types, as if I replace
`template<class... Args, bool is_noexcept>` and `void(Args...)
noexcept(is_noexcept)` with just `template<bool is_noexcept>` and `void()
noexcept(is_noexcept)`, I don't get an internal compiler error but I get a
substitution failure:

    error: no matching function for call to
'is_noexcept_(member_)function(<unresolved overloaded function type>)'
    note: candidate: 'template<bool is_noexcept> ...'
    note:   template argument deduction/substitution failed:
    note:   couldn't deduce template parameter 'is_noexcept'

This is also the error I get in g++-8 (8.3.0 (Ubuntu 8.3.0-6ubuntu1~18.04)) in
all 4 cases (So no internal compiler error in g++-8).

Reply via email to