aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2017-09-19 14:27:32 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2017-09-19 08:27:32 -0600
commite32d238855968bce82a6cca4655298c42185508d (patch)
tree486f69ae49356c806e6c4933d62a89e4f35ba897 /gcc
parentd14c60ad26f57ed6d32180a96cc27c7bf1d7f5b2 (diff)
downloadgcc-e32d238855968bce82a6cca4655298c42185508d.zip
gcc-e32d238855968bce82a6cca4655298c42185508d.tar.gz
gcc-e32d238855968bce82a6cca4655298c42185508d.tar.bz2
PR c/81854 - weak alias of an incompatible symbol accepted
gcc/ChangeLog: PR c/81854 * cgraphunit.c (handle_alias_pairs): Reject aliases between functions of incompatible types. gcc/testsuite/ChangeLog: PR c/81854 * gcc.dg/pr81854.c: New test. * g++.dg/ext/attr-ifunc-5.C: New test. * g++.dg/ext/attr-ifunc-1.C: Adjust. * g++.dg/ext/attr-ifunc-2.C: Same. * g++.dg/ext/attr-ifunc-3.C: Same. * g++.dg/ext/attr-ifunc-4.C: Same. * g++.old-deja/g++.abi/vtable2.C: Same. * gcc.dg/attr-ifunc-1.c: Same. From-SVN: r252976
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/cgraphunit.c67
-rw-r--r--gcc/testsuite/ChangeLog12
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-ifunc-1.C30
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-ifunc-2.C13
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-ifunc-3.C13
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-ifunc-4.C13
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-ifunc-5.C29
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vtable2.C5
-rw-r--r--gcc/testsuite/gcc.dg/attr-ifunc-1.c8
-rw-r--r--gcc/testsuite/gcc.dg/pr81854.c63
11 files changed, 221 insertions, 38 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d2a7c14..e08ae4c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2017-09-18 Martin Sebor <msebor@redhat.com>
+
+ PR c/81854
+ * cgraphunit.c (handle_alias_pairs): Reject aliases between functions
+ of incompatible types.
+
2017-09-19 Will Schmidt <will_schmidt@vnet.ibm.com>
* config/rs6000/rs6000.c (rs6000_gimple_fold_builtin): Add handling
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index a287f0d..8c1acf7 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1352,6 +1352,66 @@ handle_alias_pairs (void)
if (TREE_CODE (p->decl) == FUNCTION_DECL
&& target_node && is_a <cgraph_node *> (target_node))
{
+ tree t1 = TREE_TYPE (p->decl);
+ tree t2 = TREE_TYPE (target_node->decl);
+
+ if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (p->decl)))
+ {
+ t2 = TREE_TYPE (t2);
+ if (POINTER_TYPE_P (t2))
+ {
+ t2 = TREE_TYPE (t2);
+ if (!FUNC_OR_METHOD_TYPE_P (t2))
+ {
+ if (warning_at (DECL_SOURCE_LOCATION (p->decl),
+ OPT_Wattributes,
+ "%q+D %<ifunc%> resolver should return "
+ "a function pointer",
+ p->decl))
+ inform (DECL_SOURCE_LOCATION (target_node->decl),
+ "resolver declaration here");
+
+ t2 = NULL_TREE;
+ }
+ }
+ else
+ {
+ /* Deal with static member function pointers. */
+ if (TREE_CODE (t2) == RECORD_TYPE
+ && TYPE_FIELDS (t2)
+ && TREE_CODE (TREE_TYPE (TYPE_FIELDS (t2))) == POINTER_TYPE
+ && (TREE_CODE (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (t2))))
+ == METHOD_TYPE))
+ t2 = TREE_TYPE (TREE_TYPE (TYPE_FIELDS (t2)));
+ else
+ {
+ error ("%q+D %<ifunc%> resolver must return a function "
+ "pointer",
+ p->decl);
+ inform (DECL_SOURCE_LOCATION (target_node->decl),
+ "resolver declaration here");
+
+ t2 = NULL_TREE;
+ }
+ }
+ }
+
+ if (t2
+ && (!FUNC_OR_METHOD_TYPE_P (t2)
+ || (prototype_p (t1)
+ && prototype_p (t2)
+ && !types_compatible_p (t1, t2))))
+ {
+ /* Warn for incompatibilities. Avoid warning for functions
+ without a prototype to make it possible to declare aliases
+ without knowing the exact type, as libstdc++ does. */
+ if (warning_at (DECL_SOURCE_LOCATION (p->decl), OPT_Wattributes,
+ "%q+D alias between functions of incompatible "
+ "types %qT and %qT", p->decl, t1, t2))
+ inform (DECL_SOURCE_LOCATION (target_node->decl),
+ "aliased declaration here");
+ }
+
cgraph_node *src_node = cgraph_node::get (p->decl);
if (src_node && src_node->definition)
src_node->reset ();
@@ -1366,10 +1426,11 @@ handle_alias_pairs (void)
}
else
{
- error ("%q+D alias in between function and variable is not supported",
+ error ("%q+D alias between function and variable is not supported",
p->decl);
- warning (0, "%q+D aliased declaration",
- target_node->decl);
+ inform (DECL_SOURCE_LOCATION (target_node->decl),
+ "aliased declaration here");
+
alias_pairs->unordered_remove (i);
}
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a69bce3..27fc7ba 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,15 @@
+2017-09-18 Martin Sebor <msebor@redhat.com>
+
+ PR c/81854
+ * gcc.dg/pr81854.c: New test.
+ * g++.dg/ext/attr-ifunc-5.C: New test.
+ * g++.dg/ext/attr-ifunc-1.C: Adjust.
+ * g++.dg/ext/attr-ifunc-2.C: Same.
+ * g++.dg/ext/attr-ifunc-3.C: Same.
+ * g++.dg/ext/attr-ifunc-4.C: Same.
+ * g++.old-deja/g++.abi/vtable2.C: Same.
+ * gcc.dg/attr-ifunc-1.c: Same.
+
2017-09-19 Will Schmidt <will_schmidt@vnet.ibm.com>
* gcc.target/powerpc/fold-vec-ld-misc.c: New.
diff --git a/gcc/testsuite/g++.dg/ext/attr-ifunc-1.C b/gcc/testsuite/g++.dg/ext/attr-ifunc-1.C
index d41fa7d..2c7bba1 100644
--- a/gcc/testsuite/g++.dg/ext/attr-ifunc-1.C
+++ b/gcc/testsuite/g++.dg/ext/attr-ifunc-1.C
@@ -2,33 +2,41 @@
/* { dg-require-ifunc "" } */
/* { dg-options "-Wno-pmf-conversions" } */
-#include <stdio.h>
-
struct Klass
{
int implementation ();
int magic ();
- static void *resolver ();
+
+ typedef int (Klass::*MemFuncPtr)();
+
+ static MemFuncPtr resolver ();
};
+Klass::MemFuncPtr p = &Klass::implementation;
+
int Klass::implementation (void)
{
- printf ("'ere I am JH\n");
- return 0;
+ __builtin_printf ("'ere I am JH\n");
+ return 1234;
}
-void *Klass::resolver (void)
+
+Klass::MemFuncPtr Klass::resolver (void)
{
- int (Klass::*pmf) () = &Klass::implementation;
-
- return (void *)(int (*)(Klass *))(((Klass *)0)->*pmf);
+ return &Klass::implementation;
}
+int f (void) __attribute__ ((ifunc ("foo")));
+
+typedef int (F)(void);
+extern "C" F* foo () { return 0; }
+
+
int Klass::magic (void) __attribute__ ((ifunc ("_ZN5Klass8resolverEv")));
int main ()
{
Klass obj;
-
- return obj.magic () != 0;
+
+ return !(obj.magic () == 1234);
}
diff --git a/gcc/testsuite/g++.dg/ext/attr-ifunc-2.C b/gcc/testsuite/g++.dg/ext/attr-ifunc-2.C
index e205a2a..49872e0 100644
--- a/gcc/testsuite/g++.dg/ext/attr-ifunc-2.C
+++ b/gcc/testsuite/g++.dg/ext/attr-ifunc-2.C
@@ -8,7 +8,10 @@ struct Klass
{
int implementation ();
int magic ();
- static void *resolver ();
+
+ typedef int (Klass::*MemFuncPtr)();
+
+ static MemFuncPtr resolver ();
};
int Klass::implementation (void)
@@ -17,11 +20,9 @@ int Klass::implementation (void)
return 0;
}
-void *Klass::resolver (void)
+Klass::memFuncPtr Klass::resolver (void)
{
- int (Klass::*pmf) () = &Klass::implementation;
-
- return (void *)(int (*)(Klass *))(((Klass *)0)->*pmf);
+ return &Klass::implementation;
}
int Klass::magic (void) __attribute__ ((ifunc ("_ZN5Klass8resolverEv")));
@@ -33,6 +34,6 @@ struct Klassier : Klass
int main ()
{
Klassier obj;
-
+
return obj.magic () != 0;
}
diff --git a/gcc/testsuite/g++.dg/ext/attr-ifunc-3.C b/gcc/testsuite/g++.dg/ext/attr-ifunc-3.C
index ba65976..04206a1 100644
--- a/gcc/testsuite/g++.dg/ext/attr-ifunc-3.C
+++ b/gcc/testsuite/g++.dg/ext/attr-ifunc-3.C
@@ -8,7 +8,10 @@ struct Klass
{
int implementation ();
int magic ();
- static void *resolver ();
+
+ typedef int (Klass::*MemFuncPtr)();
+
+ static MemFuncPtr resolver ();
};
int Klass::implementation (void)
@@ -17,11 +20,9 @@ int Klass::implementation (void)
return 0;
}
-void *Klass::resolver (void)
+Klass::MemFuncPtr Klass::resolver (void)
{
- int (Klass::*pmf) () = &Klass::implementation;
-
- return (void *)(int (*)(Klass *))(((Klass *)0)->*pmf);
+ return &Klass::implementation;
}
int Klass::magic (void) __attribute__ ((ifunc ("_ZN5Klass8resolverEv")));
@@ -34,6 +35,6 @@ int Foo (Klass &obj, int (Klass::*pmf) ())
int main ()
{
Klass obj;
-
+
return Foo (obj, &Klass::magic) != 0;
}
diff --git a/gcc/testsuite/g++.dg/ext/attr-ifunc-4.C b/gcc/testsuite/g++.dg/ext/attr-ifunc-4.C
index 0cae410..b8d8e58 100644
--- a/gcc/testsuite/g++.dg/ext/attr-ifunc-4.C
+++ b/gcc/testsuite/g++.dg/ext/attr-ifunc-4.C
@@ -13,7 +13,10 @@ struct Klassier : Klass
{
int implementation ();
int magic ();
- static void *resolver ();
+
+ typedef int (Klass::*MemFuncPtr)();
+
+ static MemFuncPtr resolver ();
};
int Klassier::implementation (void)
@@ -22,11 +25,9 @@ int Klassier::implementation (void)
return 0;
}
-void *Klassier::resolver (void)
+Klassier::MemFuncPtr Klassier::resolver (void)
{
- int (Klassier::*pmf) () = &Klassier::implementation;
-
- return (void *)(int (*)(Klassier *))(((Klassier *)0)->*pmf);
+ return &Klassier::implementation;
}
int Klassier::magic (void) __attribute__ ((ifunc ("_ZN8Klassier8resolverEv")));
@@ -39,6 +40,6 @@ int __attribute__ ((weak)) Foo (Klass &base)
int main ()
{
Klassier obj;
-
+
return Foo (obj) != 0;
}
diff --git a/gcc/testsuite/g++.dg/ext/attr-ifunc-5.C b/gcc/testsuite/g++.dg/ext/attr-ifunc-5.C
new file mode 100644
index 0000000..05855dd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attr-ifunc-5.C
@@ -0,0 +1,29 @@
+// PR c/81854 - weak alias of an incompatible symbol accepted
+// { dg-do compile }
+// { dg-require-ifunc "" } */
+
+struct Klass
+{
+ int implementation ();
+ const char* magic ();
+
+ typedef int (Klass::*MemFuncPtr)();
+
+ static MemFuncPtr resolver ();
+};
+
+int Klass::implementation (void)
+{
+ return 0;
+}
+
+const char* __attribute__ ((ifunc ("_ZN5Klass8resolverEv")))
+ Klass::magic (); // { dg-warning "alias between functions of incompatible types" }
+
+
+
+Klass::MemFuncPtr
+Klass::resolver (void) // { dg-message "aliased declaration here" }
+{
+ return &Klass::implementation;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable2.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable2.C
index 3022875..2c88a95 100644
--- a/gcc/testsuite/g++.old-deja/g++.abi/vtable2.C
+++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable2.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-fno-strict-aliasing" }
+// { dg-options "-Wno-attributes -fno-strict-aliasing" }
// Origin: Mark Mitchell <mark@codesourcery.com>
#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
@@ -126,7 +126,8 @@ void S4::s1 ()
extern "C" {
/* We can use weakref here without dg-require-weak, because we know
the symbols are defined, so we don't actually issue the .weak
- directives. */
+ directives. The references to the incompatible virtual S3::s3()
+ and S4::s1() trigger -Wattributes. */
static void S3_s3 () __attribute__((__weakref__ ("_ZN2S32s3Ev")));
static void S4_s1 () __attribute__((__weakref__ ("_ZN2S42s1Ev")));
}
diff --git a/gcc/testsuite/gcc.dg/attr-ifunc-1.c b/gcc/testsuite/gcc.dg/attr-ifunc-1.c
index f9c6482..3f7450e 100644
--- a/gcc/testsuite/gcc.dg/attr-ifunc-1.c
+++ b/gcc/testsuite/gcc.dg/attr-ifunc-1.c
@@ -2,17 +2,17 @@
/* { dg-require-ifunc "" } */
/* { dg-options "" } */
-#include <stdio.h>
+typedef int F (void);
static int implementation (void)
{
- printf ("'ere I am JH\n");
+ __builtin_printf ("'ere I am JH\n");
return 0;
}
-static void *resolver (void)
+static F* resolver (void)
{
- return (void *)implementation;
+ return implementation;
}
extern int magic (void) __attribute__ ((ifunc ("resolver")));
diff --git a/gcc/testsuite/gcc.dg/pr81854.c b/gcc/testsuite/gcc.dg/pr81854.c
new file mode 100644
index 0000000..4b0f4da
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr81854.c
@@ -0,0 +1,63 @@
+/* PR c/81854 - weak alias of an incompatible symbol accepted
+ { dg-do compile } */
+
+const char* __attribute__ ((weak, alias ("f0_target")))
+f0 (void); /* { dg-error "alias between function and variable" } */
+
+int f0_target; /* { dg-message "aliased declaration here" } */
+
+
+const char* __attribute__ ((weak, alias ("f1_target")))
+f1 (void); /* { dg-warning "alias between functions of incompatible types" } */
+
+void f1_target (int *p) /* { dg-message "aliased declaration here" } */
+{
+ *p = 0;
+}
+
+
+const char* __attribute__ ((alias ("f2_target")))
+f2 (void*); /* { dg-warning "alias between functions of incompatible types" } */
+
+const char* f2_target (int i) /* { dg-message "aliased declaration here" } */
+{
+ (void)&i;
+ return 0;
+}
+
+
+int __attribute__ ((ifunc ("f3_resolver")))
+f3 (void); /* { dg-error ".ifunc. resolver must return a function pointer" } */
+
+int f3_resolver (void) /* { dg-message "resolver declaration here" } */
+{
+ return 0;
+}
+
+
+int __attribute__ ((ifunc ("f4_resolver")))
+f4 (void); /* { dg-warning ".ifunc. resolver should return a function pointer" } */
+
+void* f4_resolver (void) /* { dg-message "resolver declaration here" } */
+{
+ return 0;
+}
+
+
+int __attribute__ ((ifunc ("f5_resolver")))
+f5 (void); /* { dg-warning "alias between functions of incompatible types" } */
+
+typedef void F5 (void);
+F5* f5_resolver (void) /* { dg-message "aliased declaration here" } */
+{
+ return 0;
+}
+
+const char* __attribute__ ((ifunc ("f6_resolver")))
+f6 (void);
+
+typedef const char* F6 (void);
+F6* f6_resolver (void)
+{
+ return 0;
+}