aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2017-10-12 17:37:56 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2017-10-12 11:37:56 -0600
commit7a866e7e316df13b04a84a8d5426b43d016573ea (patch)
tree0aa083148a64517b691539878d5b1cfcead20175 /gcc/testsuite
parente95c91292876830c8e36b0a55f0c03d1247aaccb (diff)
downloadgcc-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/ChangeLog16
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-ifunc-1.C34
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-ifunc-2.C12
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-ifunc-3.C23
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-ifunc-4.C12
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-ifunc-5.C45
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vtable2.C2
-rw-r--r--gcc/testsuite/gcc.dg/pr81854.c29
-rw-r--r--gcc/testsuite/lib/target-supports.exp4
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