[PATCH] [PR c++/84943] allow folding of array indexing indirect_ref

Alexandre Oliva aoliva@redhat.com
Tue Apr 3 07:44:00 GMT 2018


On Apr  2, 2018, Jason Merrill <jason@redhat.com> wrote:

> On Sat, Mar 31, 2018 at 2:24 AM, Alexandre Oliva <aoliva@redhat.com> wrote:
>> On Mar 30, 2018, Jason Merrill <jason@redhat.com> wrote:
>> 
>>> I don't think we need this; if arg is overloaded, we take the
>>> type_unknown_p early exit, so the code lower down is always dealing
>>> with a single function.
>> 
>> Aah, that's why it seemed to me that we had already resolved overloads
>> when we got there.
>> 
>> As a bonus, I added the tf_conv test before another mark_used call I'd
>> missed in the previous patch.

> What if we check tf_conv in mark_used itself rather than at all the call sites?

There are other uses of mark_used, but presumably we want them all to
be more conservative under tf_conv, so...  Here's what I'm testing.  Ok
if it passes?


[PR c++/84943] mark function as used when taking its address

fn[0]() ICEd because we would fold the INDIRECT_REF used for the
array indexing while building the address for the call, after not
finding the decl hiding there at first.  But the decl would be exposed
by the folding, and then lower layers would complain we had the decl,
after all, but it wasn't one of the artificial or special functions
that could be called without being marked as used.

This patch arranges for a FUNCTION_DECL to be marked as used when
taking its address, just like we already did when taking the address
of a static function to call it as a member function (i.e. using the
obj.fn() notation).  However, we shouldn't mark functions as used when
just performing overload resolution, lest we might instantiate
templates we shouldn't, as in g++.dg/overload/template1.C, so we
adjust mark_used to return early when testing conversions.


for  gcc/cp/ChangeLog

	PR c++/84943
	* typeck.c (cp_build_addr_expr_1): Mark FUNCTION_DECL as
	used.
	* decl2.c (mark_used): Return without effects if tf_conv.

for  gcc/testsuite/ChangeLog

	PR c++/84943
	* g++.dg/pr84943.C: New.
	* g++.dg/pr84943-2.C: New.
---
 gcc/cp/decl2.c                   |    6 ++++
 gcc/cp/typeck.c                  |    3 ++
 gcc/testsuite/g++.dg/pr84943-2.C |   64 ++++++++++++++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/pr84943.C   |    8 +++++
 4 files changed, 81 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/pr84943-2.C
 create mode 100644 gcc/testsuite/g++.dg/pr84943.C

diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index fa753749e1a6..740e85b35617 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -5201,6 +5201,12 @@ maybe_instantiate_decl (tree decl)
 bool
 mark_used (tree decl, tsubst_flags_t complain)
 {
+  /* If we're just testing conversions or resolving overloads, we
+     don't want any permanent effects like forcing functions to be
+     output or instantiating templates.  */
+  if ((complain & tf_conv))
+    return false;
+
   /* If DECL is a BASELINK for a single function, then treat it just
      like the DECL for the function.  Otherwise, if the BASELINK is
      for an overloaded function, we don't know which function was
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index d454c6c5a295..bd67b82fcc65 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -5971,6 +5971,9 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain)
      so we can just form an ADDR_EXPR with the correct type.  */
   if (processing_template_decl || TREE_CODE (arg) != COMPONENT_REF)
     {
+      if (TREE_CODE (arg) == FUNCTION_DECL
+	  && !mark_used (arg, complain) && !(complain & tf_error))
+	return error_mark_node;
       val = build_address (arg);
       if (TREE_CODE (arg) == OFFSET_REF)
 	PTRMEM_OK_P (val) = PTRMEM_OK_P (arg);
diff --git a/gcc/testsuite/g++.dg/pr84943-2.C b/gcc/testsuite/g++.dg/pr84943-2.C
new file mode 100644
index 000000000000..d1ef012b9155
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr84943-2.C
@@ -0,0 +1,64 @@
+// { dg-do run }
+
+// Avoid -pedantic-error default
+// { dg-options "" }
+
+// Make sure the functions referenced by various forms of
+// address-taking are marked as used and compiled in.
+
+static void ac() {}
+void a() {
+  ac[0](); // { dg-warning "arithmetic" }
+}
+
+static void bc() {}
+void b() {
+  (&*&*&*&bc)();
+}
+
+template <typename U> U cc() {}
+void (*c())() {
+  return cc;
+}
+
+template <typename T>
+struct x {
+  void a(int);
+  template <typename U> static U a(x*) {}
+  static void a(long) {}
+  static void a(void *) {}
+  static void a() {
+    void (*p0)(void*) = x().a;
+    p0(0);
+    void (*p1)(long) = a;
+    p1(0);
+    void (*p2)() = a;
+    p2();
+    void (*p3)(x*) = a;
+    p3(0);
+  }
+};
+
+struct z {
+  void a(int);
+  template <typename U> static U a(z*) {}
+  static void a(long) {}
+  static void a(void *) {}
+  static void a() {
+    void (*p0)(void*) = z().a;
+    p0(0);
+    void (*p1)(long) = a;
+    p1(0);
+    void (*p2)() = a;
+    p2();
+    void (*p3)(z*) = a;
+    p3(0);
+  }
+};
+
+int main(int argc, char *argv[]) {
+  if (argc > 1) {
+    x<void>().a();
+    z().a();
+  }
+}
diff --git a/gcc/testsuite/g++.dg/pr84943.C b/gcc/testsuite/g++.dg/pr84943.C
new file mode 100644
index 000000000000..36f75a164119
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr84943.C
@@ -0,0 +1,8 @@
+// { dg-do compile }
+
+// Avoid -pedantic-error default
+// { dg-options "" }
+
+void a() {
+  a[0](); // { dg-warning "arithmetic" }
+}


-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer



More information about the Gcc-patches mailing list