mirror of git://gcc.gnu.org/git/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
This commit is contained in:
parent
d14c60ad26
commit
e32d238855
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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")));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
Loading…
Reference in New Issue