Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -14570,10 +14570,14 @@ indication in *rcblock).
pesep != NULL && pesep->instantiation_descr == NULL) {
/* Check that the identifier is a parameter pack name. */
if (!symbol_is_pack(sym)) {
expr_pos_error(ec_sizeof_operand_not_parameter_pack,
&pos_curr_token);
suppress_expansion_with_no_packs_diagnostic(pesep);
err = TRUE;
/* An earlier scan may have recorded a pack whose name now
refers to a substituted symbol. */
if (!pesep->recorded_pack_expansion) {
expr_pos_error(ec_sizeof_operand_not_parameter_pack,
&pos_curr_token);
suppress_expansion_with_no_packs_diagnostic(pesep);
err = TRUE;
} /* if */
} else {
record_potential_pack_reference(sym, &pos_curr_token);
} /* if */
Expand Down
14 changes: 14 additions & 0 deletions src/pending_changes/gh-491.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[GH #491]
Spurious error for pack expansions in nested generic lambdas

Previously, valid pack expansions, sizeof... operands, and fold expressions in
nested generic lambdas (for example, in default arguments or exception
specifications) could be rejected during instantiation with spurious missing
parameter pack errors. For example, with --c++14 -tused:

int f() {
auto g = [](auto... x) {
return [](auto, int n = sizeof...(x)) { return n; }(0);
};
return g(1, 2); // Previously a spurious error, now okay.
}
29 changes: 21 additions & 8 deletions src/scope_stk.c
Original file line number Diff line number Diff line change
Expand Up @@ -11678,6 +11678,7 @@ to it.
pesep->enclosing_packs_reset = FALSE;
pesep->preserve_deduced_packs = FALSE;
pesep->contains_pack_reference = FALSE;
pesep->recorded_pack_expansion = FALSE;
return pesep;
} /* alloc_pack_expansion_stack_entry */

Expand Down Expand Up @@ -13754,6 +13755,12 @@ pack-index scanner.
values for both T and U. */
reset_enclosing_pack_values();
pesep->enclosing_packs_reset = TRUE;
if (claim_pack_index || !pedp->is_pack_index) {
/* An earlier scan recorded a pack here, even if lookup now yields
substituted symbols. Pack-index descriptors belong to their
operand scanner, not an enclosing list-level context. */
pesep->recorded_pack_expansion = TRUE;
} /* if */
} /* if */
/* Allocate an expansion descriptor for this stack entry. */
pesep->expansion_descr = alloc_pack_expansion_descr();
Expand Down Expand Up @@ -14202,11 +14209,11 @@ effect and returns NULL.
result_pedp = pedp;
} /* if */
} else {
/* There were no packs referenced. This is not a pack expansion.
If a pack expansion ("...") has been seen, issue an error that
no packs were encountered. */
/* No packs were referenced. Diagnose an ellipsis unless an
earlier scan recorded a pack expansion for this context. */
if (pedp->ellipsis_seen &&
!pesep->expansion_with_no_packs_diagnostic_issued) {
!pesep->expansion_with_no_packs_diagnostic_issued &&
!pesep->recorded_pack_expansion) {
pos_error(ec_expansion_contains_no_packs,
&pedp->ellipsis_position);
} /* if */
Expand Down Expand Up @@ -14532,7 +14539,8 @@ a_boolean any_packs_referenced(void)
Return TRUE if the current pack expansion context contains any pack
references (including those from an enclosing pack context) and we are in
a template definition context. See any_packs_referenced_in_curr_context
for more information.
for more information. recorded_pack_expansion is not considered here
because it describes only the context on the top of the stack.
*/
{
a_boolean result = FALSE;
Expand All @@ -14558,20 +14566,25 @@ references and we are in a template definition context. This differs
from any_packs_referenced in that this will only be TRUE if the
context on the top of the pack expansion stack contains a pack reference
while any_packs_referenced will be TRUE if the reference was in an
enclosing context.
enclosing context. This is also TRUE when an earlier scan recorded a
pack expansion for the context even though the current scan records no
pack references (see recorded_pack_expansion).
*/
{
a_boolean result = FALSE;

/* In a prototype instantiation context expansion_descr->packs_referenced
will be NULL but contains_pack_reference could be TRUE. In a real
instantiation expansion_descr->packs_referenced might be TRUE but
contains_pack_reference will be FALSE. */
contains_pack_reference will be FALSE. recorded_pack_expansion is
TRUE when an earlier scan recorded a pack expansion but the current
scan records no pack references. */
if (pack_expansion_stack != NULL &&
!pack_expansion_stack->is_suppression) {
a_pack_expansion_stack_entry_ptr pesep = pack_expansion_stack;
result = pesep->expansion_descr->packs_referenced != NULL ||
pesep->contains_pack_reference;
pesep->contains_pack_reference ||
pesep->recorded_pack_expansion;
} /* if */
return result;
} /* any_packs_referenced_in_curr_context */
Expand Down
30 changes: 14 additions & 16 deletions src/scope_stk.h
Original file line number Diff line number Diff line change
Expand Up @@ -606,55 +606,53 @@ typedef struct a_pack_expansion_stack_entry {
/* In rescan contexts, a copy of the supplied
template argument list is made. This points to
that copy of the list. NULL otherwise. */
a_byte_boolean
is_rescan;
a_bit_field is_rescan:1;
/* TRUE when the expansion is being done in an
expression rescan context. In such contexts the
current values of the packs are maintained, but
no token manipulation or checking is done. */
a_byte_boolean
is_deduction;
a_bit_field is_deduction:1;
/* TRUE when the expansion is being done in an
template argument deduction context. In such
contexts a new template argument is created for
each pack element produced by the deduction
process, but no token manipulation or checking
is done. */
a_byte_boolean
is_suppression;
a_bit_field is_suppression:1;
/* TRUE when the processing of expansion contexts
is being suppressed. This only suppresses
expansions from tokens, not rescans. */
a_byte_boolean
expansion_with_no_packs_diagnostic_issued;
a_bit_field expansion_with_no_packs_diagnostic_issued:1;
/* TRUE if suppress_expansion_with_no_packs_diagnostic
was called to indicate that the caller already
issued a diagnostic for an expansion with no
packs. */
a_byte_boolean
is_lookahead;
a_bit_field is_lookahead:1;
/* TRUE if this context is being pushed to
distinguish between two contexts. When this
is TRUE, it is assumed that another begin...
call will be done for the same starting position,
and that context will be responsible for the
end... and advance... calls. */
a_byte_boolean
enclosing_packs_reset;
a_bit_field enclosing_packs_reset:1;
/* TRUE for a pack expansion of a template declaration
in a real instantiation (see call of
reset_enclosing_pack_values in
begin_potential_pack_expansion_context_full for
more information). */
a_boolean
preserve_deduced_packs;
a_bit_field preserve_deduced_packs:1;
/* TRUE if is_rescan is TRUE and deduced parameter
packs should be retained in the substituted type. */
a_byte_boolean
contains_pack_reference;
a_bit_field contains_pack_reference:1;
/* TRUE during prototype instantiations if any
pack references were recorded while this entry
was at the top of the pack expansion stack. */
a_bit_field recorded_pack_expansion:1;
/* TRUE if an earlier scan recorded a pack expansion
for this context, which is being scanned without
pack instantiation. The descriptor is evidence
of a pack even if lookup yields substituted
symbols and no pack references are recorded. */
} a_pack_expansion_stack_entry;


Expand Down
1 change: 0 additions & 1 deletion tests/expectations/edg_x86_64/imported.log
Original file line number Diff line number Diff line change
Expand Up @@ -1506,7 +1506,6 @@ clang/cpp/SemaTemplate/fun-template-def.sft.cpp:fn:-DTEST_NUMBER=1 --c++03:FAIL:
clang/cpp/SemaTemplate/fun-template-def.sft.cpp:fn:-DTEST_NUMBER=2 --c++11:FAIL:
clang/cpp/SemaTemplate/fun-template-def.sft.cpp:fn:-DTEST_NUMBER=3 --c++17:FAIL:
clang/cpp/SemaTemplate/fun-template-def.sft.cpp:fn:-DTEST_NUMBER=4 --c++20:FAIL:
clang/cpp/SemaTemplate/generic-lambda.sft.cpp:fp:-DTEST_NUMBER=1 --c++20:FAIL:
clang/cpp/SemaTemplate/instantiate-after-fatal-cxx17.sft.cpp:fp:-DTEST_NUMBER=1 --c++17:CATASTROPHE:
clang/cpp/SemaTemplate/instantiate-explicitly-after-fatal.sft.cpp:fp:-DTEST_NUMBER=1 --c++11:FAIL:
clang/cpp/SemaTemplate/instantiate-incomplete-typo-suggested-error-limit.sft.cpp:fp:-DTEST_NUMBER=1:FAIL:
Expand Down
1 change: 1 addition & 0 deletions tests/tests/changes/.gh-491.rto/default.1.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=1 --c++14 -tused Test_name.c
10 changes: 10 additions & 0 deletions tests/tests/changes/gh-491.sft.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//type:fp
//options:--c++14 -tused
//remark:Spurious error for pack expansions in nested generic lambdas

int f() {
auto g = [](auto... x) {
return [](auto, int n = sizeof...(x)) { return n; }(0);
};
return g(1, 2); // Previously a spurious error, now okay.
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
auto L = [](auto a) {
^

"Test_name.c", line 448: error: pack expansion does not make use of any argument packs
print("d = ", d ..., "\n");
^
detected during instantiation of function "lambda [](auto)->auto [with <auto-1>=char]" at line 461

"Test_name.c", line 468: error: no suitable conversion function from "lambda [](const char *, int, const char *, double, const char *, int)->char" to "int (*)(const char *, int, const char *, double, const char *, int)" exists
int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}}
^
Expand All @@ -79,34 +74,14 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
} // end test()
^

"Test_name.c", line 527: error: the operand of sizeof... must be a parameter pack name
x = sizeof...(b);
^
detected during instantiation of "auto nested_non_capturing_lambda_tests::wrapped_within_templates::implicit_return_deduction::fooV(Ts...) [with Ts=<double, const char *, char, int>]" at line 542

"Test_name.c", line 563: error: pack expansion does not make use of any argument packs
print("d = ", d ..., "\n");
^
detected during instantiation of function "lambda [](auto)->auto [with <auto-1>=char]" at line 574

"Test_name.c", line 581: error: no suitable conversion function from "lambda [](const char *, int, const char *, double, const char *, int)->char" to "int (*)(const char *, int, const char *, double, const char *, int)" exists
int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}}
^

"Test_name.c", line 687: error: pack expansion does not make use of any argument packs
print("d = ", d ..., "\n");
^
detected during instantiation of function "lambda [](auto)->auto [with <auto-1>=char]" at line 700

"Test_name.c", line 707: error: no suitable conversion function from "lambda [](const char *, int, const char *, double, const char *, int)->char" to "int (*)(const char *, int, const char *, double, const char *, int)" exists
int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}}
^

"Test_name.c", line 728: error: pack expansion does not make use of any argument packs
print("d = ", d ..., "\n");
^
detected during instantiation of function "lambda [](auto)->auto [with <auto-1>=char]" at line 742

"Test_name.c", line 749: error: no suitable conversion function from "lambda [](const char *, int, const char *, double, const char *, int)->char" to "int (*)(const char *, int, const char *, double, const char *, int)" exists
int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}}
^
Expand Down Expand Up @@ -156,7 +131,7 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
auto y = [](auto (*p)() -> auto) { return p(); };
^

30 errors and 1 catastrophic error detected in the compilation of "Test_name.c".
25 errors and 1 catastrophic error detected in the compilation of "Test_name.c".
Compilation aborted.
Aborted
eccp: front end returned an exit status of 134
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,6 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
auto L = [](auto a) {
^

"Test_name.c", line 448: error: pack expansion does not make use of any argument packs
print("d = ", d ..., "\n");
^
detected during instantiation of function "lambda [](auto)->auto [with <auto-1>=char]" at line 461

"Test_name.c", line 468: error: no suitable conversion function from "lambda [](const char *, int, const char *, double, const char *, int)->char" to "int (*)(const char *, int, const char *, double, const char *, int)" exists
int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}}
^
Expand All @@ -79,34 +74,14 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
} // end test()
^

"Test_name.c", line 527: error: the operand of sizeof... must be a parameter pack name
x = sizeof...(b);
^
detected during instantiation of "auto nested_non_capturing_lambda_tests::wrapped_within_templates::implicit_return_deduction::fooV(Ts...) [with Ts=<double, const char *, char, int>]" at line 542

"Test_name.c", line 563: error: pack expansion does not make use of any argument packs
print("d = ", d ..., "\n");
^
detected during instantiation of function "lambda [](auto)->auto [with <auto-1>=char]" at line 574

"Test_name.c", line 581: error: no suitable conversion function from "lambda [](const char *, int, const char *, double, const char *, int)->char" to "int (*)(const char *, int, const char *, double, const char *, int)" exists
int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}}
^

"Test_name.c", line 687: error: pack expansion does not make use of any argument packs
print("d = ", d ..., "\n");
^
detected during instantiation of function "lambda [](auto)->auto [with <auto-1>=char]" at line 700

"Test_name.c", line 707: error: no suitable conversion function from "lambda [](const char *, int, const char *, double, const char *, int)->char" to "int (*)(const char *, int, const char *, double, const char *, int)" exists
int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}}
^

"Test_name.c", line 728: error: pack expansion does not make use of any argument packs
print("d = ", d ..., "\n");
^
detected during instantiation of function "lambda [](auto)->auto [with <auto-1>=char]" at line 742

"Test_name.c", line 749: error: no suitable conversion function from "lambda [](const char *, int, const char *, double, const char *, int)->char" to "int (*)(const char *, int, const char *, double, const char *, int)" exists
int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}}
^
Expand Down Expand Up @@ -156,7 +131,7 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
auto y = [](auto (*p)() -> auto) { return p(); };
^

30 errors and 1 catastrophic error detected in the compilation of "Test_name.c".
25 errors and 1 catastrophic error detected in the compilation of "Test_name.c".
Compilation aborted.
Aborted
eccp: front end returned an exit status of 134
Loading
Loading