PR c++/64382 * g++.dg/cpp1y/pr64382.C: New test. --- gcc/cp/cp-tree.h | 1 + gcc/cp/parser.c | 21 +++++++++++++++++++++ gcc/cp/semantics.c | 8 +++++--- gcc/testsuite/g++.dg/cpp1y/pr64382.C | 23 +++++++++++++++++++++++ 4 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr64382.C
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 2a904a5..484f352 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5645,6 +5645,7 @@ extern bool maybe_clone_body (tree); /* In parser.c */ extern tree cp_convert_range_for (tree, tree, tree, bool); extern bool parsing_nsdmi (void); +extern bool parsing_default_capturing_generic_lambda_in_template (void); extern void inject_this_parameter (tree, cp_cv_quals); /* in pt.c */ diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index ac91976..74b55df 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -18339,6 +18339,27 @@ parsing_nsdmi (void) return false; } +/* Return true iff our current scope is a default capturing generic lambda + defined within a template. */ + +bool +parsing_default_capturing_generic_lambda_in_template (void) +{ + if (processing_template_decl && current_class_type) + if (tree lam = CLASSTYPE_LAMBDA_EXPR (current_class_type)) + if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam) != CPLD_NONE) + if (tree callop = lambda_function (lam)) + if (DECL_TEMPLATE_INFO (callop) + && (DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (callop)) + == callop) + && ((current_nonlambda_class_type () + && CLASSTYPE_TEMPLATE_INFO (current_nonlambda_class_type ())) + || ((current_nonlambda_function () + && DECL_TEMPLATE_INFO (current_nonlambda_function ()))))) + return true; + return false; +} + /* Parse a late-specified return type, if any. This is not a separate non-terminal, but part of a function declarator, which looks like diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 74af7e8..f1ab183 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3450,9 +3450,11 @@ finish_id_expression (tree id_expression, } } - /* If the name was dependent on a template parameter, we will - resolve the name at instantiation time. */ - if (dependent_p) + /* If the name was dependent on a template parameter and we're not in a + default capturing generic lambda within a template, we will resolve the + name at instantiation time. */ + if (dependent_p + && !parsing_default_capturing_generic_lambda_in_template ()) { /* Create a SCOPE_REF for qualified names, if the scope is dependent. */ diff --git a/gcc/testsuite/g++.dg/cpp1y/pr64382.C b/gcc/testsuite/g++.dg/cpp1y/pr64382.C new file mode 100644 index 0000000..ff552ac --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr64382.C @@ -0,0 +1,23 @@ +// PR c++/64382 +// { dg-do compile { target c++1y } } + +template<typename T> +struct my_queue +{ + void push(T) + { + } + void ice() + { + auto L = [=](auto &&v) { + push(v); + }; + trav(L); + } + template<typename F> + void trav(F &&f) + { + f(T()); + } +}; +template struct my_queue<int>; -- 2.3.5