diff options
author | Martin Sebor <msebor@redhat.com> | 2017-10-12 17:37:56 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2017-10-12 11:37:56 -0600 |
commit | 7a866e7e316df13b04a84a8d5426b43d016573ea (patch) | |
tree | 0aa083148a64517b691539878d5b1cfcead20175 /gcc/testsuite | |
parent | e95c91292876830c8e36b0a55f0c03d1247aaccb (diff) | |
download | gcc-7a866e7e316df13b04a84a8d5426b43d016573ea.zip gcc-7a866e7e316df13b04a84a8d5426b43d016573ea.tar.gz gcc-7a866e7e316df13b04a84a8d5426b43d016573ea.tar.bz2 |
PR c/82301 - Updated test case g++.dg/ext/attr-ifunc-1.C (and others) in r253041 segfault on powerpc64
PR c/82301 - Updated test case g++.dg/ext/attr-ifunc-1.C (and others) in r253041 segfault on powerpc64
PR c/82435 - new __attribute__((alias)) warning gets in the way
gcc/ChangeLog:
PR other/82301
PR c/82435
* cgraphunit.c (maybe_diag_incompatible_alias): New function.
(handle_alias_pairs): Call it.
* common.opt (-Wattribute-alias): New option.
* doc/extend.texi (ifunc attribute): Discuss C++ specifics.
* doc/invoke.texi (-Wattribute-alias): Document.
gcc/testsuite/ChangeLog:
PR other/82301
PR c/82435
* g++.dg/ext/attr-ifunc-1.C: Update.
* 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++.dg/ext/attr-ifunc-5.C: Same.
* g++.dg/ext/attr-ifunc-6.C: New test.
* g++.old-deja/g++.abi/vtable2.C: Update.
* gcc.dg/attr-ifunc-6.c: New test.
* gcc.dg/attr-ifunc-7.c: New test.
* gcc.dg/pr81854.c: Update.
* lib/target-supports.exp: Update.
From-SVN: r253688
Diffstat (limited to 'gcc/testsuite')
-rw-r--r-- | gcc/testsuite/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/attr-ifunc-1.C | 34 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/attr-ifunc-2.C | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/attr-ifunc-3.C | 23 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/attr-ifunc-4.C | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/attr-ifunc-5.C | 45 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.abi/vtable2.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr81854.c | 29 | ||||
-rw-r--r-- | gcc/testsuite/lib/target-supports.exp | 4 |
9 files changed, 129 insertions, 48 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 47b3f78..a910f8a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,19 @@ +2017-10-12 Martin Sebor <msebor@redhat.com> + + PR other/82301 + PR c/82435 + * g++.dg/ext/attr-ifunc-1.C: Update. + * 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++.dg/ext/attr-ifunc-5.C: Same. + * g++.dg/ext/attr-ifunc-6.C: New test. + * g++.old-deja/g++.abi/vtable2.C: Update. + * gcc.dg/attr-ifunc-6.c: New test. + * gcc.dg/attr-ifunc-7.c: New test. + * gcc.dg/pr81854.c: Update. + * lib/target-supports.exp: Update. + 2017-10-12 David Malcolm <dmalcolm@redhat.com> * g++.dg/parse/pragma2.C: Update to reflect reinstatement of the diff --git a/gcc/testsuite/g++.dg/ext/attr-ifunc-1.C b/gcc/testsuite/g++.dg/ext/attr-ifunc-1.C index 2c7bba1..4a29e8b 100644 --- a/gcc/testsuite/g++.dg/ext/attr-ifunc-1.C +++ b/gcc/testsuite/g++.dg/ext/attr-ifunc-1.C @@ -4,26 +4,33 @@ struct Klass { + int a[4]; + int implementation (); int magic (); - typedef int (Klass::*MemFuncPtr)(); + /* An ifunc resolver must return a pointer to an ordinary (non-member) + function. To make it possible to use ifunc with member functions, + the resolver must convert a member function pointer to an ordinary + function pointer (slicing off the high word). */ + typedef int Func (Klass*); - static MemFuncPtr resolver (); + static Func* resolver (); }; -Klass::MemFuncPtr p = &Klass::implementation; - -int Klass::implementation (void) +int Klass::implementation () { __builtin_printf ("'ere I am JH\n"); - return 1234; + return a[0] + a[1] + a[2] + a[3]; } - -Klass::MemFuncPtr Klass::resolver (void) +Klass::Func* Klass::resolver (void) { - return &Klass::implementation; + /* GCC guarantees this conversion to be safe and the resulting pointer + usable to call the member function using ordinary (i.e., non-member) + function call syntax. */ + + return reinterpret_cast<Func*>(&Klass::implementation); } int f (void) __attribute__ ((ifunc ("foo"))); @@ -32,11 +39,16 @@ typedef int (F)(void); extern "C" F* foo () { return 0; } -int Klass::magic (void) __attribute__ ((ifunc ("_ZN5Klass8resolverEv"))); +int Klass::magic () __attribute__ ((ifunc ("_ZN5Klass8resolverEv"))); int main () { Klass obj; - return !(obj.magic () == 1234); + obj.a[0] = 1; + obj.a[1] = 2; + obj.a[2] = 3; + obj.a[3] = 4; + + return !(obj.magic () == 10); } diff --git a/gcc/testsuite/g++.dg/ext/attr-ifunc-2.C b/gcc/testsuite/g++.dg/ext/attr-ifunc-2.C index 1fc940b..e5be3d2 100644 --- a/gcc/testsuite/g++.dg/ext/attr-ifunc-2.C +++ b/gcc/testsuite/g++.dg/ext/attr-ifunc-2.C @@ -9,9 +9,9 @@ struct Klass int implementation (); int magic (); - typedef int (Klass::*MemFuncPtr)(); + typedef int Func (Klass*); - static MemFuncPtr resolver (); + static Func* resolver (); }; int Klass::implementation (void) @@ -20,9 +20,13 @@ int Klass::implementation (void) return 0; } -Klass::MemFuncPtr Klass::resolver (void) +Klass::Func* Klass::resolver (void) { - return &Klass::implementation; + /* GCC guarantees this conversion to be safe and the resulting pointer + usable to call the member function using ordinary (i.e., non-member) + function call syntax. */ + + return reinterpret_cast<Func*>(&Klass::implementation); } int Klass::magic (void) __attribute__ ((ifunc ("_ZN5Klass8resolverEv"))); diff --git a/gcc/testsuite/g++.dg/ext/attr-ifunc-3.C b/gcc/testsuite/g++.dg/ext/attr-ifunc-3.C index 04206a1..6d49424 100644 --- a/gcc/testsuite/g++.dg/ext/attr-ifunc-3.C +++ b/gcc/testsuite/g++.dg/ext/attr-ifunc-3.C @@ -6,23 +6,29 @@ struct Klass { + int a[4]; + int implementation (); int magic (); - typedef int (Klass::*MemFuncPtr)(); + typedef int Func (Klass*); - static MemFuncPtr resolver (); + static Func* resolver (); }; int Klass::implementation (void) { printf ("'ere I am JH\n"); - return 0; + return a[0] + a[1] + a[2] + a[3]; } -Klass::MemFuncPtr Klass::resolver (void) +Klass::Func* Klass::resolver () { - return &Klass::implementation; + /* GCC guarantees this conversion to be safe and the resulting pointer + usable to call the member function using ordinary (i.e., non-member) + function call syntax. */ + + return reinterpret_cast<Func*>(&Klass::implementation); } int Klass::magic (void) __attribute__ ((ifunc ("_ZN5Klass8resolverEv"))); @@ -36,5 +42,10 @@ int main () { Klass obj; - return Foo (obj, &Klass::magic) != 0; + obj.a[0] = 1; + obj.a[1] = 2; + obj.a[2] = 3; + obj.a[3] = 4; + + return Foo (obj, &Klass::magic) != 10; } diff --git a/gcc/testsuite/g++.dg/ext/attr-ifunc-4.C b/gcc/testsuite/g++.dg/ext/attr-ifunc-4.C index 3127193..f71dc3b 100644 --- a/gcc/testsuite/g++.dg/ext/attr-ifunc-4.C +++ b/gcc/testsuite/g++.dg/ext/attr-ifunc-4.C @@ -14,9 +14,9 @@ struct Klassier : Klass int implementation (); int magic (); - typedef int (Klassier::*MemFuncPtr)(); + typedef int Func (Klass*); - static MemFuncPtr resolver (); + static Func* resolver (); }; int Klassier::implementation (void) @@ -25,9 +25,13 @@ int Klassier::implementation (void) return 0; } -Klassier::MemFuncPtr Klassier::resolver (void) +Klassier::Func* Klassier::resolver () { - return &Klassier::implementation; + /* GCC guarantees this conversion to be safe and the resulting pointer + usable to call the member function using ordinary (i.e., non-member) + function call syntax. */ + + return reinterpret_cast<Func*>(&Klassier::implementation); } int Klassier::magic (void) __attribute__ ((ifunc ("_ZN8Klassier8resolverEv"))); diff --git a/gcc/testsuite/g++.dg/ext/attr-ifunc-5.C b/gcc/testsuite/g++.dg/ext/attr-ifunc-5.C index 05855dd..fd8bcff 100644 --- a/gcc/testsuite/g++.dg/ext/attr-ifunc-5.C +++ b/gcc/testsuite/g++.dg/ext/attr-ifunc-5.C @@ -1,15 +1,21 @@ // PR c/81854 - weak alias of an incompatible symbol accepted // { dg-do compile } // { dg-require-ifunc "" } */ +// { dg-options "-Wextra -Wno-pmf-conversions" } struct Klass { int implementation (); - const char* magic (); + int good_magic (); + int iffy_magic (); + const char* bad_magic (); + typedef int (Func)(Klass*); typedef int (Klass::*MemFuncPtr)(); - static MemFuncPtr resolver (); + static Func* good_resolver (); + static void* iffy_resolver (); + static MemFuncPtr bad_resolver (); }; int Klass::implementation (void) @@ -17,13 +23,42 @@ int Klass::implementation (void) return 0; } -const char* __attribute__ ((ifunc ("_ZN5Klass8resolverEv"))) - Klass::magic (); // { dg-warning "alias between functions of incompatible types" } +// Verify no warning for the expected/compatible declaration. +int __attribute__ ((ifunc ("_ZN5Klass13good_resolverEv"))) +Klass::good_magic (); + +Klass::Func* +Klass::good_resolver (void) +{ + MemFuncPtr mfp = &Klass::implementation; + + return reinterpret_cast<Func*>(mfp); +} + + +// Verify a warning for the unsafe declaration. + +int __attribute__ ((ifunc ("_ZN5Klass13iffy_resolverEv"))) +Klass::iffy_magic (); // { dg-message "resolver indirect function declared here" } + +void* +Klass::iffy_resolver (void) // { dg-warning ".ifunc. resolver for .int Klass::iffy_magic\\(\\). should return .int \\(\\*\\)\\(Klass\\*\\)." } +{ + MemFuncPtr mfp = &Klass::implementation; + + return reinterpret_cast<void*>(mfp); +} + + +// Verify an error for an incompatible declaration. + +const char* __attribute__ ((ifunc ("_ZN5Klass12bad_resolverEv"))) +Klass::bad_magic (); // { dg-message "resolver indirect function declared here" } Klass::MemFuncPtr -Klass::resolver (void) // { dg-message "aliased declaration here" } +Klass::bad_resolver (void) // { dg-error ".ifunc. resolver for .const char\\* Klass::bad_magic\\(\\). must return .const char\\* \\(\\*\\)\\(Klass\\*\\)." } { 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 2c88a95..96533e0 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 "-Wno-attributes -fno-strict-aliasing" } +// { dg-options "-Wno-attribute-alias -fno-strict-aliasing" } // Origin: Mark Mitchell <mark@codesourcery.com> #if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 diff --git a/gcc/testsuite/gcc.dg/pr81854.c b/gcc/testsuite/gcc.dg/pr81854.c index b8499f8..1021a81 100644 --- a/gcc/testsuite/gcc.dg/pr81854.c +++ b/gcc/testsuite/gcc.dg/pr81854.c @@ -1,6 +1,7 @@ /* PR c/81854 - weak alias of an incompatible symbol accepted { dg-do compile } - { dg-require-ifunc "" } */ + { dg-require-ifunc "" } + { dg-options "-Wextra" } */ const char* __attribute__ ((weak, alias ("f0_target"))) f0 (void); /* { dg-error "alias between function and variable" } */ @@ -26,39 +27,37 @@ const char* f2_target (int i) /* { dg-message "aliased declaration here" } */ return 0; } - int __attribute__ ((ifunc ("f3_resolver"))) -f3 (void); /* { dg-error ".ifunc. resolver must return a function pointer" } */ +f3 (void); /* { dg-message "resolver indirect function declared here" } */ -int f3_resolver (void) /* { dg-message "resolver declaration here" } */ +void* f3_resolver (void) /* { dg-warning "ifunc. resolver for .f3. should return .int \\(\\*\\)\\(void\\)." } */ { return 0; } int __attribute__ ((ifunc ("f4_resolver"))) -f4 (void); /* { dg-warning ".ifunc. resolver should return a function pointer" } */ +f4 (void); /* { dg-message "resolver indirect function declared here" } */ -void* f4_resolver (void) /* { dg-message "resolver declaration here" } */ +typedef void F4 (void); +F4* f4_resolver (void) /* { dg-warning ".ifunc. resolver for .f4. should return .int \\(\\*\\)\\(void\\)" } */ { return 0; } +const char* __attribute__ ((ifunc ("f5_resolver"))) +f5 (void); -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" } */ +typedef const char* F5 (void); +F5* f5_resolver (void) { return 0; } -const char* __attribute__ ((ifunc ("f6_resolver"))) -f6 (void); +int __attribute__ ((ifunc ("f6_resolver"))) +f6 (void); /* { dg-message "resolver indirect function declared here" } */ -typedef const char* F6 (void); -F6* f6_resolver (void) +int f6_resolver (void) /* { dg-error ".ifunc. resolver for 'f6' must return .int \\(\\*\\)\\(void\\)." } */ { return 0; } diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index fbe8f2a..4f9bf46 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -440,8 +440,8 @@ proc check_ifunc_available { } { extern "C" { #endif typedef void F (void); - F* g() {} - void f() __attribute__((ifunc("g"))); + F* g (void) {} + void f () __attribute__ ((ifunc ("g"))); #ifdef __cplusplus } #endif |