Skip to content

Commit 85e38dc

Browse files
znoffel1wchilders-nvidia
authored andcommitted
Unrecognized attribute with a pack expansion in its arguments [GH #412]
We call record_pack_expansion_ellipsis_position for unrecognized attributes presumably to silence an error that would occur when we don't know the attribute in a pack expansion e.g. acquire_capability(m...). We keep the arguments as plain text tokens and therefore we don't see it as expanding m (error). So we add a ... when there isn't one and record an expansion and sets the flag. The attempted fix still fakes the ... but only skips setting the flag. The printer stops writing the extra ... but instantiation still repeats or drops the attribute. This change doesn't fake the expansion. If no real ... follows an unrecognized attribute it would just throw away the pack names collected from the attribute's arguments.
1 parent ac9e490 commit 85e38dc

14 files changed

Lines changed: 224 additions & 6 deletions

File tree

‎src/attribute.c‎

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2632,12 +2632,15 @@ that appeared in a previous "using" prefix. Can return NULL on error.
26322632
{ a_pack_expansion_descr_ptr pedep;
26332633
if (pesep != NULL &&
26342634
(*p_attribute == NULL || is_unrecognized_attr(*p_attribute))) {
2635-
/* For an unknown attribute, we do not know if packs encountered
2636-
within the attribute arguments were expanded within the pack or
2637-
should be expanded with the attribute as a whole. By recording
2638-
the presence of an ellipsis, we avoid spurious diagnostics. */
2639-
record_pack_expansion_ellipsis_position(&pos_curr_token);
2640-
pesep->expansion_with_no_packs_diagnostic_issued = TRUE;
2635+
/* An unknown attribute's arguments are raw tokens, in which packs
2636+
may already be expanded (e.g., "attr(args...)"). */
2637+
if (curr_token == tok_ellipsis) {
2638+
/* A pack expansion, but packs in raw tokens may go undetected. */
2639+
suppress_expansion_with_no_packs_diagnostic(pesep);
2640+
} else {
2641+
/* Not a pack expansion. */
2642+
discard_pack_references_for_context(pesep);
2643+
} /* if */
26412644
} /* if */
26422645
pedep = end_potential_pack_expansion_context(pesep,
26432646
/*is_declarator=*/FALSE);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[GH #412]
2+
Unrecognized attribute with a pack expansion in its arguments
3+
4+
In a variadic template, an unrecognized attribute whose arguments referenced a
5+
parameter pack (e.g., in a pack expansion) was treated as a pack expansion of
6+
the attribute as a whole. As a result, the C++-generating back end could put
7+
out a spurious "..." after the attribute when generating a template from its
8+
IL, and instantiations could receive the wrong number of copies of the
9+
attribute (e.g., one per pack element, or none for an empty pack). For
10+
example, in Clang mode:
11+
12+
template <class... M> struct scoped_lock {
13+
scoped_lock(M&... m) __attribute__((acquire_capability(m...))) {}
14+
};
15+
16+
could be generated as
17+
18+
scoped_lock(M &...m) __attribute((acquire_capability(m ... )...)) { }
19+
20+
That is now fixed.

‎src/scope_stk.c‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14232,6 +14232,44 @@ effect and returns NULL.
1423214232
} /* end_potential_pack_expansion_context */
1423314233

1423414234

14235+
void discard_pack_references_for_context(
14236+
a_pack_expansion_stack_entry_ptr pesep)
14237+
/*
14238+
This is called just before end_potential_pack_expansion_context for a
14239+
potential pack expansion context (described by pesep) that is known not to be
14240+
a pack expansion, but that may contain pack references whose expansion cannot
14241+
be determined. For example, in
14242+
template <class... M>
14243+
void f(M&... m) __attribute__((some_attr(m...)));
14244+
the arguments of the unrecognized attribute are recorded as raw tokens, so it
14245+
is not known whether m is expanded within them. The pack references recorded
14246+
so far for the context are discarded without any diagnostic, so that
14247+
end_potential_pack_expansion_context neither records a pack expansion, nor
14248+
issues diagnostics for unexpanded packs, nor passes the references on to an
14249+
enclosing context. pesep can be NULL, in which case nothing is done; nothing
14250+
is done either for suppression, rescan, or real instantiation contexts, in
14251+
which pack references are not recorded.
14252+
*/
14253+
{
14254+
if (pesep != NULL && !pesep->is_rescan && !pesep->is_suppression &&
14255+
pesep->instantiation_descr == NULL) {
14256+
a_pack_expansion_descr_ptr pedp = pesep->expansion_descr;
14257+
check_assertion(pesep == pack_expansion_stack);
14258+
/* The context ends here: Extract its pack references and free them. */
14259+
pedp->last_token = curr_token_sequence_number;
14260+
extract_pack_references_for_context(pedp);
14261+
#if DEBUG
14262+
if (db_flag_is_set("packs") && pedp->packs_referenced != NULL) {
14263+
fprintf(f_debug, "Discarding the references extracted above\n");
14264+
} /* if */
14265+
#endif /* DEBUG */
14266+
free_list_of_pack_references(pedp->packs_referenced);
14267+
pedp->packs_referenced = NULL;
14268+
pesep->contains_pack_reference = FALSE;
14269+
} /* if */
14270+
} /* discard_pack_references_for_context */
14271+
14272+
1423514273
a_boolean advance_to_next_pack_element(a_pack_expansion_stack_entry_ptr pesep)
1423614274
/*
1423714275
This routine is called after end_potential_pack_expansion_context has been

‎src/scope_stk.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2667,6 +2667,9 @@ extern a_pack_expansion_descr_ptr end_potential_pack_expansion_context(
26672667
a_pack_expansion_stack_entry_ptr pesep,
26682668
a_boolean is_declarator);
26692669

2670+
extern void discard_pack_references_for_context(
2671+
a_pack_expansion_stack_entry_ptr pesep);
2672+
26702673
extern void begin_tentative_pack_expansion_context(void);
26712674

26722675
extern void end_tentative_pack_expansion_context(a_boolean);

‎tests/expectations/edg_x86_32_cp/regressions.log‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ gh-309.sft.cpp:fp:-DTEST_NUMBER=2 --g++ --no_exceptions:REQUIREMENTS NOT MET:
44
immediate-pragma-lost.sft.cpp:cppbe:-DTEST_NUMBER=1:PASS:
55
pragma-il-class-no-lowering.sft.cpp:fp:-DTEST_NUMBER=1:REQUIREMENTS NOT MET:
66
pragma-il-class.sft.cpp:fp:-DTEST_NUMBER=1:REQUIREMENTS NOT MET:
7+
unrecognized-attr-arg-pack-expansion/test.mft.cpp:fp:-DTEST_NUMBER=1 --c++17 --clang_version 230000:PASS:
8+
unrecognized-attr-arg-pack-expansion/test.mft.cpp:fp:-DTEST_NUMBER=2 --c++17 --gnu_version 150000:PASS:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
immediate-pragma-lost.sft.cpp:cppbe:-DTEST_NUMBER=1:REQUIREMENTS NOT MET:
22
modules/crash-processing-imported-explicit-specialization/test.mft.cpp:cp:-DTEST_NUMBER=1:FAIL:
3+
unrecognized-attr-arg-pack-expansion/test.mft.cpp:fp:-DTEST_NUMBER=1 --c++17 --clang_version 230000:REQUIREMENTS NOT MET:Unrecognized attribute with a pack expansion in its arguments
4+
unrecognized-attr-arg-pack-expansion/test.mft.cpp:fp:-DTEST_NUMBER=2 --c++17 --gnu_version 150000:REQUIREMENTS NOT MET:Unrecognized attribute with a pack expansion in its arguments

‎tests/expectations/edg_x86_64_cp/regressions.log‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ gh-309.sft.cpp:fp:-DTEST_NUMBER=2 --g++ --no_exceptions:REQUIREMENTS NOT MET:
44
immediate-pragma-lost.sft.cpp:cppbe:-DTEST_NUMBER=1:PASS:
55
pragma-il-class-no-lowering.sft.cpp:fp:-DTEST_NUMBER=1:REQUIREMENTS NOT MET:
66
pragma-il-class.sft.cpp:fp:-DTEST_NUMBER=1:REQUIREMENTS NOT MET:
7+
unrecognized-attr-arg-pack-expansion/test.mft.cpp:fp:-DTEST_NUMBER=1 --c++17 --clang_version 230000:PASS:
8+
unrecognized-attr-arg-pack-expansion/test.mft.cpp:fp:-DTEST_NUMBER=2 --c++17 --gnu_version 150000:PASS:
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fe_only -DTEST_NUMBER=1 --c++17 -w --clang_version 230000 Test_name.c
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fe_only -DTEST_NUMBER=2 --c++17 -w --gnu_version 150000 Test_name.c
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
./first_stage_il -DTEST_NUMBER=1 --il_display --c++17 --clang_version 230000 Test_name.c
2+
name: file-scope other-text: "acquire_capability"
3+
4+
name: file-scope other-text: "requires_capability"
5+
6+
name: file-scope other-text: "acquire_capability"
7+
8+
name: file-scope other-text: "requires_capability"
9+
10+
name: file-scope other-text: "acquire_capability"
11+
12+
name: file-scope other-text: "requires_capability"
13+
14+
name: file-scope other-text: "release_capability"
15+
16+
name: file-scope other-text: "try_acquire_capability"
17+
18+
name: file-scope other-text: "attr_unexpanded"
19+
20+
is_pack_expansion: TRUE
21+
name: file-scope other-text: "attr_expanded"
22+
23+
name: file-scope other-text: "release_capability"
24+
25+
name: file-scope other-text: "try_acquire_capability"
26+
27+
name: file-scope other-text: "try_acquire_capability"
28+
29+
name: file-scope other-text: "attr_unexpanded"
30+
31+
name: file-scope other-text: "attr_expanded"
32+
33+
name: file-scope other-text: "attr_expanded"
34+

0 commit comments

Comments
 (0)