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

            Bug ID: 126185
           Summary: [C++26] std::meta::exception not caught with template
                    for in dependent context
           Product: gcc
           Version: 16.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: Eriksander5252Principal at hotmail dot com
  Target Milestone: ---

Severity:
major

Description:

When using std::meta::members_of() with std::meta::access_context::current() 
inside a template for loop, GCC throws an uncaught std::meta::exception instead 
of either compiling successfully or producing a clear diagnostic. 

The same issue occurs when using std::meta::enumerators_of() (the dedicated 
function for enumerations) - in that case, the compiler reports that the 
expression is not a constant expression because it refers to a result of 
'operator new'.

Both failures occur only when the type is dependent (^^typePers inside a
template).
When using a concrete type (e.g., ^^ERRORCODE) outside a template, the code
works
as expected.

Environment:
- GCC 16.1.0 (x86-64)
- Flags: -std=c++26 -freflection
- Platform: Godbolt.org

Minimal Example:

#include <meta>
#include <type_traits>
#include <iostream>
#include <expected>
#include <string>
#include <cstdint>

enum class ERRORCODE : std::uint16_t {
     SUCCESS         = 0x00,
     FAIL            = 0x01,
     WRONG_TYPE      = 0x02
};

template<typename T1, typename T2>
constexpr std::expected<T1, ERRORCODE> SomarValores(const T1& value_1, const
T2& value_2) {
    if constexpr ((std::is_integral_v<T1> || std::is_floating_point_v<T1>) &&
                  (std::is_integral_v<T2> || std::is_floating_point_v<T2>)) {
        return value_1 + value_2;
    } else {
        return std::unexpected(ERRORCODE::FAIL);
    }
}

template<typename TipoDesconhecido>
constexpr auto InterpretarErro(const TipoDesconhecido& err) {
    auto error = err.error_or(ERRORCODE::SUCCESS);
    using typePers = typename TipoDesconhecido::error_type;

    // This loop triggers the uncaught exception
    template for (constexpr auto member : std::meta::members_of(^^typePers,
std::meta::access_context::current())) {
        if (error == [:member:])
            return std::meta::identifier_of(member);
    }
    return "UNKNOWN_ERROR";
}

int main() {
    std::cout << "ErroR: " << InterpretarErro(SomarValores(true, 1.0f)) <<
std::endl;
    return 0;
}

Error Message:

With members_of:
error: uncaught exception of type 'std::meta::exception'; 
'what()': 'neither complete class type nor namespace'

With enumerators_of:
error: 'std::meta::enumerators_of(^^typePers)' is not a constant expression 
because it refers to a result of 'operator new'

Full output (members_of):
<source>: In instantiation of 'constexpr auto InterpretarErro(const
TipoDesconhecido&) [with TipoDesconhecido = std::expected<bool, ERRORCODE>]':
<source>:40:46:   required from here
   40 |     std::cout << "ErroR: " << InterpretarErro(SomarValores(true, 1.0f))
<< std::endl;
      |                               ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:32:5: error: uncaught exception of type 'std::meta::exception';
'what()': 'neither complete class type nor namespace'
   32 |     template for (constexpr auto member :
std::meta::members_of(^^typePers, std::meta::access_context::current())) {
      |     ^~~~~~~~
Compiler returned: 1

Full output (enumerators_of):
<source>: In instantiation of 'constexpr auto InterpretarErro(const
TipoDesconhecido&) [with TipoDesconhecido = std::expected<bool, ERRORCODE>]':
<source>:40:163:   required from here
   40 |     std::cout << "ErroR: " << InterpretarErro(SomarValores(true, 1.0f))
<< std::endl;
      |                                                                        
                                                                          
~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:32:90: error: 'std::meta::enumerators_of(^^typePers)' is not a
constant expression because it refers to a result of 'operator new'
   32 |     template for (constexpr auto member :
std::meta::enumerators_of(^^typePers)) {
      |                                                                        
                 ^~~~~~~~
In file included from
/cefs/38/383ad2f84cbd57a52fd68bbe_consolidated/compilers_c++_x86_gcc_16.1.0/include/c++/16.1.0/string:46:
/cefs/38/383ad2f84cbd57a52fd68bbe_consolidated/compilers_c++_x86_gcc_16.1.0/include/c++/16.1.0/bits/allocator.h:203:52:
note: allocated here
  203 |             return static_cast<_Tp*>(::operator new(__n));
      |                                      ~~~~~~~~~~~~~~^~~~~
Compiler returned: 1

Expected Behavior:
1. The code should compile successfully (since the type is a complete
enumeration)
2. Alternatively, GCC should produce a clear diagnostic explaining why the
reflection operation is invalid
3. GCC should NOT throw an uncaught exception or produce misleading internal
errors

Actual Behavior:
GCC throws an uncaught std::meta::exception with a generic message when using
members_of,
or an internal "not a constant expression" error when using enumerators_of.

Additional Information:
- The function InterpretarErro is meant to iterate over all enumerators of the
enum type 
  ERRORCODE using reflection, compare each enumerator value to an error code,
and return 
  the enumerator's name as a string. This should be possible with
std::meta::members_of 
  or std::meta::enumerators_of, as proposed in P2996.

- The problem appears only when the type is dependent (^^typePers inside a
template).
- When using a concrete type (e.g., ^^ERRORCODE) outside a template, the
reflection works correctly.
- Both std::meta::members_of and std::meta::enumerators_of fail in this
context.

- This might be related to bugs 125519, 124215, or 125770, which also deal with
uncaught exceptions in the reflection implementation.

I searched for possible duplicates and found bugs 125519, 124215, and 125770,
which deal with similar uncaught exceptions in the reflection implementation,
but they do not cover the specific case of using members_of/enumerators_of in
a dependent context. I also checked bugs 125900 and others listed, but they
are unrelated to this issue.
  • [Bug c++/126185] N... Eriksander5252Principal at hotmail dot com via Gcc-bugs

Reply via email to