aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2018-04-04 03:40:29 +0000
committerAlexandre Oliva <aoliva@gcc.gnu.org>2018-04-04 03:40:29 +0000
commit24d21a0bc07ee2c9b041504956834be3bba7e746 (patch)
treef4ccbb78b6d042b7a3a6aaf99f9c3ad3a86e65d8 /gcc
parent30feb954d0fb8f6e3797f997de3a5daef6c19247 (diff)
downloadgcc-24d21a0bc07ee2c9b041504956834be3bba7e746.zip
gcc-24d21a0bc07ee2c9b041504956834be3bba7e746.tar.gz
gcc-24d21a0bc07ee2c9b041504956834be3bba7e746.tar.bz2
[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. From-SVN: r259067
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/decl2.c6
-rw-r--r--gcc/cp/typeck.c3
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/pr84943-2.C64
-rw-r--r--gcc/testsuite/g++.dg/pr84943.C8
6 files changed, 94 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 4a9f999..46f05c8 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index fa75374..6ae6cef 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 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
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index e33f2c3..2b7a771 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/ChangeLog b/gcc/testsuite/ChangeLog
index de14495..95cd7c8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..d1ef012
--- /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 0000000..36f75a1
--- /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" }
+}