public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c++: ICE with delayed noexcept and attribute used [PR97966]
@ 2021-01-13  2:13 Marek Polacek
  2021-01-19 20:37 ` Jason Merrill
  0 siblings, 1 reply; 6+ messages in thread
From: Marek Polacek @ 2021-01-13  2:13 UTC (permalink / raw)
  To: GCC Patches, Jason Merrill

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 a 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.

It stands to reason to disable delayed noexcept parsing when the
function is marked with used (clang++ also rejects).  Unfortunately
we can't just use lookup_attribute when parsing and check if "used"
is there and if so, clear CP_PARSER_FLAGS_DELAY_NOEXCEPT, because
we accept attributes following the noexcept-specifier, like this:

  void g() noexcept(...) __attribute__((used));

Oh well.  This patch should handle various forms of attributes in
one place.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/10?

gcc/cp/ChangeLog:

	PR c++/97966
	* parser.c (cp_parser_save_default_args): Don't delay parsing of
	the noexcept-specifier of a function marked with attribute used.

gcc/testsuite/ChangeLog:

	PR c++/97966
	* g++.dg/cpp0x/noexcept63.C: New test.
---
 gcc/cp/parser.c                         | 20 +++++++++-
 gcc/testsuite/g++.dg/cpp0x/noexcept63.C | 49 +++++++++++++++++++++++++
 2 files changed, 68 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept63.C

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c713852fe93..07ab966e099 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -30880,7 +30880,25 @@ cp_parser_save_default_args (cp_parser* parser, tree decl)
   /* Remember if there is a noexcept-specifier to post process.  */
   tree spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl));
   if (UNPARSED_NOEXCEPT_SPEC_P (spec))
-    vec_safe_push (unparsed_noexcepts, decl);
+    {
+      /* Don't actually delay parsing of the noexcept-specifier of
+	 a member function marked with attribute used.  */
+      if (__builtin_expect (DECL_PRESERVE_P (decl), 0))
+	{
+	  auto cleanup = make_temp_override
+	    (parser->local_variables_forbidden_p);
+	  if (DECL_THIS_STATIC (decl))
+	    parser->local_variables_forbidden_p |= THIS_FORBIDDEN;
+	  inject_this_parameter (current_class_type, TYPE_UNQUALIFIED);
+	  spec = cp_parser_late_noexcept_specifier (parser,
+						    TREE_PURPOSE (spec));
+	  if (spec == error_mark_node)
+	    spec = NULL_TREE;
+	  fixup_deferred_exception_variants (TREE_TYPE (decl), spec);
+	}
+      else
+	vec_safe_push (unparsed_noexcepts, decl);
+    }
 }
 
 /* DEFAULT_ARG contains the saved tokens for the initializer of DECL,
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept63.C b/gcc/testsuite/g++.dg/cpp0x/noexcept63.C
new file mode 100644
index 00000000000..8efeac93a30
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept63.C
@@ -0,0 +1,49 @@
+// PR c++/97966
+// { dg-do compile { target c++11 } }
+
+template <int>
+struct S1 {
+  __attribute__((used)) S1() noexcept(noexcept(this->foo())); // { dg-error "has no member" }
+  void foo();
+};
+
+template <int>
+struct S2 {
+  __attribute__((used)) void bar() noexcept(noexcept(this->foo())); // { dg-error "has no member" }
+  void foo();
+};
+
+template <int>
+struct S3 {
+  void __attribute__((used)) bar() noexcept(noexcept(this->foo())); // { dg-error "has no member" }
+  void foo();
+};
+
+template <int>
+struct S4 {
+  [[gnu::used]] void bar() noexcept(noexcept(this->foo())); // { dg-error "has no member" }
+  void foo();
+};
+
+template <int>
+struct S5 {
+  void bar() noexcept(noexcept(this->foo())) __attribute__((used)); // { dg-error "has no member" }
+  void foo();
+};
+
+template <int>
+struct S6 {
+  static void bar() noexcept(noexcept(this->foo())) __attribute__((used)); // { dg-error ".this. may not be used in this context" }
+  void foo();
+};
+
+void
+g ()
+{
+  S1<1> s1;
+  S2<1> s2;
+  S3<1> s3;
+  S4<1> s4;
+  S5<1> s5;
+  S6<1> s6;
+}

base-commit: cfaaa6a1ca744c1a93fa08a3e7ab2a821383cac1
-- 
2.29.2


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-01-21 23:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-13  2:13 [PATCH] c++: ICE with delayed noexcept and attribute used [PR97966] Marek Polacek
2021-01-19 20:37 ` Jason Merrill
2021-01-21  0:49   ` [PATCH v2] " Marek Polacek
2021-01-21  6:55     ` Jason Merrill
2021-01-21 15:39       ` [PATCH v3] " Marek Polacek
2021-01-21 22:59         ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).