From: Martin Sebor Date: Tue, 19 Sep 2017 14:27:32 +0000 (+0000) Subject: PR c/81854 - weak alias of an incompatible symbol accepted X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e32d238855968bce82a6cca4655298c42185508d;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d2a7c14a873..e08ae4c3f4a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2017-09-18 Martin Sebor + + PR c/81854 + * cgraphunit.c (handle_alias_pairs): Reject aliases between functions + of incompatible types. + 2017-09-19 Will Schmidt * config/rs6000/rs6000.c (rs6000_gimple_fold_builtin): Add handling diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index a287f0dfd44..8c1acf770b9 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 (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 % 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 % 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 a69bce3177f..27fc7bad752 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2017-09-18 Martin Sebor + + 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 * 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 d41fa7d3267..2c7bba12959 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 - 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 e205a2a6a8d..49872e0cbea 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 ba65976b964..04206a126e8 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 0cae41028b5..b8d8e5879b4 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 00000000000..05855dd20c0 --- /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 30228756f12..2c88a95800b 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 #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 f9c6482298c..3f7450e2c69 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 +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 00000000000..4b0f4da0f81 --- /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; +}