[Bug c++/113405] Can't access member type alias of concept-constrained class template specialization in global module fragment via alias template in different module
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113405 Nathaniel Shead changed: What|Removed |Added CC||nathanieloshead at gmail dot com --- Comment #4 from Nathaniel Shead --- The issue seems to be that 'depset::hash::add_specializations' only adds the first of a set of constrained specialisations that use the same arguments. This comes down to the fact that the 'type_specializations' hashset is only hashed on the base template and the provided arguments: differently constrained specialisations just aren't added. Other parts of the dependency walker seem to handle this OK, by walking the DECL_TEMPLATE_SPECIALIZATIONS list, but not the base 'specialization_add' function. I'm not entirely sure yet what the best way to approach solving this is.
[Bug c++/113308] derived class doesn't currently allow inherited explicit object member function post increment operator
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113308 Nathaniel Shead changed: What|Removed |Added CC||nathanieloshead at gmail dot com --- Comment #1 from Nathaniel Shead --- I believe this is correct behaviour: The definition of `operator++` in the child class hides the `operator++` declared in the base class. Similarly to the following code: struct base { void f(int) {} }; struct d1 : base { void f() {} }; struct d2 : base { using base::f; // explicitly add base::f as an overload void f() {} }; int main() { d1{}.f(10); // error d2{}.f(10); // OK }
[Bug c++/104221] member functions defined in separate files of classes declared in module partitions won't compile
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104221 Nathaniel Shead changed: What|Removed |Added CC||nathanieloshead at gmail dot com --- Comment #1 from Nathaniel Shead --- I think this is IFNDR; you cannot have more than one partition with the same name. See https://eel.is/c++draft/module.unit#3: > A module partition is a module unit whose module-declaration contains > a module-partition. A named module shall not contain multiple module > partitions with the same module-partition. All module partitions of a > module that are module interface units shall be directly or indirectly > exported by the primary module interface unit ([module.import]). > No diagnostic is required for a violation of these rules. And in particular, unlike a module implementation unit, a module partition does not implicitly import anything; see https://eel.is/c++draft/module.unit#8 which says: > A module-declaration that contains neither an export-keyword nor a > module-partition implicitly imports the primary module interface unit > of the module as if by a module-import-declaration. So this is working as specified. I don't think there'd be any good way of improving the diagnostics for this either.
[Bug c++/113031] [14 Regression] ICE in cxx_fold_indirect_ref_1 starting with r14-6508
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113031 --- Comment #6 from Nathaniel Shead --- Yes, fixed as far as I'm aware.
[Bug c++/113047] dereferencing a null pointer in a constant expression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113047 Nathaniel Shead changed: What|Removed |Added CC||nathanieloshead at gmail dot com --- Comment #4 from Nathaniel Shead --- I've pushed a fix for PR102420 (and hence comment #1), but looking at the DR this isn't sufficient for the result of CWG2823, for which presumably all of the following should also start erroring as well (note none of these error in Clang yet either): struct X { static constexpr int f() { return 0; } }; constexpr int g(X* x) { return (*x).f(); } // error constexpr int a = g(nullptr); constexpr int h(X* x) { return x->f(); } // error constexpr int b = h(nullptr); // and similarly constexpr int test() { int* p = nullptr; *p; // error return 0; } constexpr int t = test();
[Bug c++/113031] [14 Regression] ICE in cxx_fold_indirect_ref_1 starting with r14-6508
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113031 --- Comment #2 from Nathaniel Shead --- Reduced to: template class variant; template auto __variant_cast(_Tp __rhs) { return static_cast&&>(__rhs); } template struct _Move_assign_base : _Types { void operator=(_Move_assign_base __rhs) { __variant_cast<_Types>(__rhs); } }; template struct variant : _Move_assign_base<_Types> { void emplace() { variant __tmp; *this = __tmp; } }; struct _Undefined_class { struct _Nocopy_types { void (_Undefined_class::*_M_member_pointer)(); }; struct function : _Nocopy_types { struct optional { void test03() { variant v; v.emplace(); } }; }; }; The following patch seems to fix the immediate problem (but not yet fully regtested): diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index e1b2d27fc36..051f73fb73f 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -5709,7 +5709,8 @@ cxx_fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, } /* Handle conversion to "as base" type. */ - if (CLASSTYPE_AS_BASE (optype) == type) + if (CLASS_TYPE_P (optype) + && CLASSTYPE_AS_BASE (optype) == type) return op; /* Handle conversion to an empty base class, which is represented with a
[Bug c++/112820] vtable not emitted correctly from module when compiling with -g
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112820 Nathaniel Shead changed: What|Removed |Added CC||nathanieloshead at gmail dot com --- Comment #1 from Nathaniel Shead --- The issue seems to be that the same flag is used for DECL_EXTERN and TYPE_DECL_SUPPRESS_DEBUG, and the modules reading code is getting confused and thinking that TYPE_DECLs with the latter flag set means that they are actually DECL_EXTERN and thus preventing them from being emitted. The following hunk fixes this issue but it'd probably be better to clean up all handling of extern within the modules reading so that we don't lose the "suppress debug" flag entirely. diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 33fcf396875..add3fa4b945 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -5397,7 +5397,7 @@ trees_out::core_bools (tree t) DECL_NOT_REALLY_EXTERN -> base.not_really_extern == that was a lie, it is here */ - bool is_external = t->decl_common.decl_flag_1; + bool is_external = code != TYPE_DECL && t->decl_common.decl_flag_1; if (!is_external) /* decl_flag_1 is DECL_EXTERNAL. Things we emit here, might well be external from the POV of an importer. */
[Bug c++/112588] ICE in make_decl_rtl when returning str literal when string header imported in module
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112588 Nathaniel Shead changed: What|Removed |Added CC||nathanieloshead at gmail dot com --- Comment #1 from Nathaniel Shead --- Minimised (the actual offender here is the with std::allocator): // test.h void f(int*); template struct S { void g(int n) { f(&n); } }; template struct S; // a.cpp module; #include "test.h" export module test; // b.cpp #include "test.h" import test; So far it seems the issue is that the PARM_DECL in the expression tree of the body of the instantiation for `S::g` is a different node from the actual PARM_DECL in g's DECL_ARGUMENTS; the latter gets RTL but the former does not. The issue is in the deduplication logic for instantiations somewhere. The following patch fixes this issue but causes other issues in the testsuite, and I don't think this is the correct approach anyway: diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 4f5b6e2747a..f2d191fc408 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -8302,9 +8302,7 @@ trees_in::decl_value () if (TREE_CODE (inner) == FUNCTION_DECL) { tree e_inner = STRIP_TEMPLATE (existing); - for (auto parm = DECL_ARGUMENTS (inner); - parm; parm = DECL_CHAIN (parm)) - DECL_CONTEXT (parm) = e_inner; + DECL_ARGUMENTS (inner) = DECL_ARGUMENTS (e_inner); } /* And our result is the existing node. */ (I was originally working on this after attempting to reduce PR9.)
[Bug c++/106851] [modules] Name conflict for exported using-declaration
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106851 Nathaniel Shead changed: What|Removed |Added CC||nathanieloshead at gmail dot com --- Comment #2 from Nathaniel Shead --- This behaviour should be as expected right? The 'using' is trying to bring both names into the same scope (the global namespace), irrespective of the fact that we're also exporting that new declaration. (That is, removing the 'export' keywords from this test case gives the exact some result.) That said, perhaps it would be helpful for the error message to point to the using-declaration it actually conflicts with, rather than the definition that said using-declaration points to.
[Bug c++/110936] if constexpr: member function pointers cannot be checked with ubsan
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110936 Nathaniel Shead changed: What|Removed |Added CC||nathanieloshead at gmail dot com --- Comment #3 from Nathaniel Shead --- More generally this appears to be caused by '-fno-delete-null-pointer-checks' causing constant folding not to occur. Minimised example: struct foo { void bar() { } }; constexpr bool b = &foo::bar; https://gcc.godbolt.org/z/x7csTzjfa
[Bug c++/96090] noexcept operator of potentially-throwing defaulted function gives the wrong result
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96090 Nathaniel Shead changed: What|Removed |Added CC||nathanieloshead at gmail dot com --- Comment #2 from Nathaniel Shead --- I'm working on a patch for this. But worth noting... > static_assert(!is_nothrow_default_constructible_v); I'm not sure this is correct. By https://eel.is/c++draft/meta.unary.prop#9 this is testing noexceptness of value-initialisation. And https://eel.is/c++draft/dcl.init.general#9.1 says > if T has either no default constructor ([class.default.ctor]) or >a default constructor that is user-provided or deleted, then >the object is default-initialized; > otherwise, the object is zero-initialized and the semantic constraints >for default-initialization are checked, and if T has a non-trivial >default constructor, the object is default-initialized; Since the default constructor here is not user-provided, and also trivial, the object should not be default-initialized and thus the default constructor is not called, and thus this is not potentially-throwing.
[Bug c++/101631] gcc allows for the changing of an union active member to be changed via a reference
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101631 --- Comment #6 from Nathaniel Shead --- (In reply to Sam James from comment #5) > Fixed for 14 then by the drive-by bit or is there something left? It should be fixed now. The example in comment #2 is g++.dg/cpp2a/constexpr-union2.C.
[Bug c++/111226] New: constexpr doesn't detect change of union to empty member
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111226 Bug ID: 111226 Summary: constexpr doesn't detect change of union to empty member Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: nathanieloshead at gmail dot com Target Milestone: --- While working on a patch for PR101631, I found that the following code is currently incorrectly handled by GCC: (https://godbolt.org/z/1YevacMK3) struct Empty {}; union U { int x; Empty e; }; constexpr int foo() { U u{ 10 }; u.e = {}; return u.x; // incorrectly accepted, even pre-C++20 } constexpr auto y = foo(); constexpr Empty bar() { U u{ 10 }; u.e = {}; return u.e; // incorrectly errors, thinks active member is still 'x' } constexpr auto x = bar(); The cause seems to be that the zero-sized trivial assignment is removed in call.cc (since PR43075) and after constant folding is no longer in the tree that the constexpr handling machinery receives.