[PR c++/84943] mark function as used when taking its address
authorAlexandre Oliva <aoliva@redhat.com>
Wed, 4 Apr 2018 03:40:29 +0000 (03:40 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Wed, 4 Apr 2018 03:40:29 +0000 (03:40 +0000)
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.

From-SVN: r259067

gcc/cp/ChangeLog
gcc/cp/decl2.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/pr84943-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/pr84943.C [new file with mode: 0644]

index 4a9f9995d2438972588f76c458e7a5e4dd829f25..46f05c8661e28df589e1f00d632a2a5269b3b86d 100644 (file)
@@ -1,3 +1,10 @@
+2018-04-04  Alexandre Oliva <aoliva@redhat.com>
+
+       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.
+
 2018-04-03  Jason Merrill  <jason@redhat.com>
 
        PR c++/85092 - C++17 ICE with unused list constructor.
index fa753749e1a6b63f2497f529e35cdb211fca883c..6ae6cef78dda0de2b536173285d3e8d3fa8ef514 100644 (file)
@@ -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 true;
+
   /* 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
index e33f2c34c7f9f49f8338e8b9d447547d5126319c..2b7a771bbeb300178617097dc004f7c607ca98c7 100644 (file)
@@ -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);
index de14495bf9ae50e918152d1996e8ce2a74d6975c..95cd7c8392d979316502a0f3abe8b83ce2147c66 100644 (file)
@@ -1,3 +1,9 @@
+2018-04-04  Alexandre Oliva <aoliva@redhat.com>
+
+       PR c++/84943
+       * g++.dg/pr84943.C: New.
+       * g++.dg/pr84943-2.C: New.
+
 2018-04-03  Jakub Jelinek  <jakub@redhat.com>
 
        PR rtl-optimization/85167
diff --git a/gcc/testsuite/g++.dg/pr84943-2.C b/gcc/testsuite/g++.dg/pr84943-2.C
new file mode 100644 (file)
index 0000000..d1ef012
--- /dev/null
@@ -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 (file)
index 0000000..36f75a1
--- /dev/null
@@ -0,0 +1,8 @@
+// { dg-do compile }
+
+// Avoid -pedantic-error default
+// { dg-options "" }
+
+void a() {
+  a[0](); // { dg-warning "arithmetic" }
+}