From: Marek Polacek Date: Thu, 7 May 2026 22:09:57 +0000 (-0400) Subject: c++: fix ICE with invalid targ [PR125043] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=90ec6eeca09f5a411fd7878e2532a7ac2f2e3d71;p=thirdparty%2Fgcc.git c++: fix ICE with invalid targ [PR125043] The patch that allowed DECL_NTTP_OBJECT_P in invalid_tparm_referent_p also added the assert checking for tinfos/__func__ (r14-8189). But in these tests we got to the assert with a temporary object coming from create_temporary_var: either a reference temporary or compound literal temporary. The former could be checked by seeing if the name starts with _ZGR but the latter don't have it. So perhaps we can just check DECL_IGNORED_P, always set for create_temporary_var objects. PR c++/115181 PR c++/125043 PR c++/124979 gcc/cp/ChangeLog: * pt.cc (invalid_tparm_referent_p): Allow DECL_IGNORED_P in an assert. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/nontype-auto27.C: New test. * g++.dg/cpp1z/nontype-auto28.C: New test. * g++.dg/cpp2a/nontype-class75.C: New test. Reviewed-by: Jason Merrill --- diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 6992b5196fe..b6e8948f005 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -7439,18 +7439,22 @@ invalid_tparm_referent_p (tree type, tree expr, tsubst_flags_t complain) "because %qD has no linkage", expr, type, decl); return true; } - /* C++17: For a non-type template-parameter of reference or pointer - type, the value of the constant expression shall not refer to (or - for a pointer type, shall not be the address of): - * a subobject (4.5), - * a temporary object (15.2), - * a string literal (5.13.5), - * the result of a typeid expression (8.2.8), or - * a predefined __func__ variable (11.4.1). */ + /* For a constant template parameter of reference or pointer type, + or for each non-static data member of reference or pointer type + in a constant template parameter of class type or subobject thereof, + the reference or pointer value shall not refer or point to + (respectively): + -- a temporary object, + -- a string literal object, + -- the result of a typeid expression, + -- a predefined __func__ variable, or + -- a subobject of one of the above. */ else if (VAR_P (decl) && DECL_ARTIFICIAL (decl) && !DECL_NTTP_OBJECT_P (decl)) { - gcc_checking_assert (DECL_TINFO_P (decl) || DECL_FNAME_P (decl)); + gcc_checking_assert (DECL_TINFO_P (decl) + || DECL_FNAME_P (decl) + || DECL_IGNORED_P (decl)); if (complain & tf_error) error ("the address of %qD is not a valid template argument", decl); diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype-auto27.C b/gcc/testsuite/g++.dg/cpp1z/nontype-auto27.C new file mode 100644 index 00000000000..51ff86dfc25 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/nontype-auto27.C @@ -0,0 +1,5 @@ +// PR c++/115181 +// { dg-do compile { target c++17 } } + +template struct S {}; +__extension__ S<(int[]){1}> x; // { dg-error "not a valid template argument" } diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype-auto28.C b/gcc/testsuite/g++.dg/cpp1z/nontype-auto28.C new file mode 100644 index 00000000000..d9165f87987 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/nontype-auto28.C @@ -0,0 +1,14 @@ +// PR c++/125043 +// { dg-do compile { target c++17 } } + +template +struct wrapper { + static constexpr const auto& value = V; +}; + +template +auto f() -> void; + +auto main() -> int { + f::value>(); // { dg-error "no matching function|not a valid template argument" } +} diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class75.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class75.C new file mode 100644 index 00000000000..a30ccbee85d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class75.C @@ -0,0 +1,34 @@ +// PR c++/124979 +// { dg-do compile { target c++20 } } + +template +struct cw; + +struct base { + + template + friend constexpr auto operator &(L) noexcept + -> cw<(&L::value)> { + return {}; + } +}; + +template +struct cw : base { + static constexpr const auto& value = X; +}; + template + constexpr auto operator ->*(cw, cw) noexcept + -> cw* R> { + return {}; + } + +struct Divide { int value; }; +auto cvalue = cw<&Divide::value>{}; +constexpr const Divide &t = {42}; +auto co = cw{}; +auto co1 = cw<&t>{}; // { dg-error "not a valid template argument|is invalid" } + +template class TD; +template class TD>{}; +TD*cvalue)> _; // { dg-error "is invalid" }