Concepts-checking and other kinds of early tsubsting may often take place while location wrappers are suppressed, e.g. because we've triggered template instantiation within template parameter lists.
With that, exprs that are usually wrapped by VIEW_CONVERT_EXPRs location wrappers may end up wrapped by NON_LVALUE_EXPRs that are not marked as location wrappers. If such NON_LVALUE_EXPRs tsubsted exprs undergo another round of tsubsting, say for constraint checking, or even for another round of specialization, they will be rejected by tsubst_copy_and_build. This patch introduces a sentinel to reset suppress_location_wrappers to zero, and uses it for template class and decl instantiation, including constraint checking. Regstrapped on x86_64- and i686-linux-gnu. Ok to install? for gcc/ChangeLog PR c++/87768 * tree.h (auto_restore_location_wrappers): New sentinel class. for gcc/cp/ChangeLog PR c++/87768 * pt.c (instantiate_class_template_1, instantiate_decl): Do not suppress location wrappers. for gcc/testsuite/ChangeLog PR c++/87768 * g++.dg/concepts/pr87768.C: New. --- gcc/cp/pt.c | 8 ++++++++ gcc/testsuite/g++.dg/concepts/pr87768.C | 14 ++++++++++++++ gcc/tree.h | 17 +++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 gcc/testsuite/g++.dg/concepts/pr87768.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 18b093e7d2d2..e4d07c5103b6 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10895,6 +10895,10 @@ instantiate_class_template_1 (tree type) it now. */ deferring_access_check_sentinel acs (dk_no_deferred); + /* Do not drop location wrappers just because we're tsubsting e.g. + constraints while parsing e.g. template parameters. */ + auto_restore_location_wrappers sentinel; + /* Determine what specialization of the original template to instantiate. */ t = most_specialized_partial_spec (type, tf_warning_or_error); @@ -24172,6 +24176,10 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p) timevar_push (TV_TEMPLATE_INST); + /* Do not drop location wrappers just because we're tsubsting e.g. + constraints while parsing e.g. template parameters. */ + auto_restore_location_wrappers sentinel; + /* Set TD to the template whose DECL_TEMPLATE_RESULT is the pattern for the instantiation. */ td = template_for_substitution (d); diff --git a/gcc/testsuite/g++.dg/concepts/pr87768.C b/gcc/testsuite/g++.dg/concepts/pr87768.C new file mode 100644 index 000000000000..de436e5d9edd --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/pr87768.C @@ -0,0 +1,14 @@ +// { dg-do compile { target c++17 } } +// { dg-options "-fconcepts" } + +struct a {}; +template <bool> using b = a; + +template <typename> struct c; +template <typename d> + requires requires(d e) { e[0]; } +struct c<d> { + static constexpr bool f = [] { return false; }(); +}; + +struct g : b<c<unsigned[]>::f> {}; diff --git a/gcc/tree.h b/gcc/tree.h index ed37e5455743..5bab3b284074 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1194,6 +1194,23 @@ class auto_suppress_location_wrappers ~auto_suppress_location_wrappers () { --suppress_location_wrappers; } }; +/* A class for restoring the creation of location wrappers. */ + +class auto_restore_location_wrappers +{ + const int saved; +public: + auto_restore_location_wrappers () + : saved (suppress_location_wrappers) + { + suppress_location_wrappers = 0; + } + ~auto_restore_location_wrappers () + { + suppress_location_wrappers = saved; + } +}; + /* In a TARGET_EXPR node. */ #define TARGET_EXPR_SLOT(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 0) #define TARGET_EXPR_INITIAL(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 1) -- Alexandre Oliva, freedom fighter https://FSFLA.org/blogs/lxo Be the change, be Free! FSF Latin America board member GNU Toolchain Engineer Free Software Evangelist Hay que enGNUrecerse, pero sin perder la terGNUra jamás-GNUChe