diff options
author | Marek Polacek <polacek@redhat.com> | 2021-01-12 16:16:44 -0500 |
---|---|---|
committer | Marek Polacek <polacek@redhat.com> | 2021-01-21 19:22:01 -0500 |
commit | bca467e56fe111fa6d876656c60d5704065e83fe (patch) | |
tree | b3b2b30911d0fbfd08bf01044ab9a3319845aa98 /gcc/cp | |
parent | 070a1fb5f5254a08cd87783a1b51c3a3ac7ae18e (diff) | |
download | gcc-bca467e56fe111fa6d876656c60d5704065e83fe.zip gcc-bca467e56fe111fa6d876656c60d5704065e83fe.tar.gz gcc-bca467e56fe111fa6d876656c60d5704065e83fe.tar.bz2 |
c++: ICE with delayed noexcept and attribute used [PR97966]
Another ICE with delayed noexcept parsing, but a bit gnarlier.
A function definition marked with __attribute__((used)) ought to be
emitted even when it is not referenced in the TU. For a member function
template marked with __attribute__((used)) this means that it will
be instantiated: in instantiate_class_template_1 we have
11971 /* Instantiate members marked with attribute used. */
11972 if (r != error_mark_node && DECL_PRESERVE_P (r))
11973 mark_used (r);
It is not so surprising that this doesn't work well with delayed
noexcept parsing: when we're processing the function template we delay
the parsing, so the member "foo" is found, but then when we're
instantiating it, "foo" hasn't yet been seen, which creates a
discrepancy and a crash ensues. "foo" hasn't yet been seen because
instantiate_class_template_1 just loops over the class members and
instantiates right away.
To make it work, this patch uses a vector to keep track of members
marked with attribute used and uses it to instantiate such members
only after we're done with the class; in particular, after we have
called finish_member_declaration for each member. And we ought to
be verifying that we did emit such members, so I've added a bunch
of dg-finals.
gcc/cp/ChangeLog:
PR c++/97966
* pt.c (instantiate_class_template_1): Instantiate members
marked with attribute used only after we're done instantiating
the class.
gcc/testsuite/ChangeLog:
PR c++/97966
* g++.dg/cpp0x/noexcept63.C: New test.
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/pt.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 373f827..63a0a11 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -11895,6 +11895,9 @@ instantiate_class_template_1 (tree type) relative to the scope of the class. */ pop_to_parent_deferring_access_checks (); + /* A vector to hold members marked with attribute used. */ + auto_vec<tree> used; + /* Now members are processed in the order of declaration. */ for (member = CLASSTYPE_DECL_LIST (pattern); member; member = TREE_CHAIN (member)) @@ -11968,7 +11971,7 @@ instantiate_class_template_1 (tree type) finish_member_declaration (r); /* Instantiate members marked with attribute used. */ if (r != error_mark_node && DECL_PRESERVE_P (r)) - mark_used (r); + used.safe_push (r); if (TREE_CODE (r) == FUNCTION_DECL && DECL_OMP_DECLARE_REDUCTION_P (r)) cp_check_omp_declare_reduction (r); @@ -12034,7 +12037,7 @@ instantiate_class_template_1 (tree type) /*flags=*/0); /* Instantiate members marked with attribute used. */ if (r != error_mark_node && DECL_PRESERVE_P (r)) - mark_used (r); + used.safe_push (r); } else if (TREE_CODE (r) == FIELD_DECL) { @@ -12225,6 +12228,11 @@ instantiate_class_template_1 (tree type) if (TYPE_CONTAINS_VPTR_P (type) && CLASSTYPE_KEY_METHOD (type)) vec_safe_push (keyed_classes, type); + /* Now that we've gone through all the members, instantiate those + marked with attribute used. */ + for (tree x : used) + mark_used (x); + return type; } |