Commit e32d2388 by Martin Sebor Committed by Martin Sebor

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
parent d14c60ad
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> 2017-09-19 Will Schmidt <will_schmidt@vnet.ibm.com>
* config/rs6000/rs6000.c (rs6000_gimple_fold_builtin): Add handling * config/rs6000/rs6000.c (rs6000_gimple_fold_builtin): Add handling
......
...@@ -1352,6 +1352,66 @@ handle_alias_pairs (void) ...@@ -1352,6 +1352,66 @@ handle_alias_pairs (void)
if (TREE_CODE (p->decl) == FUNCTION_DECL if (TREE_CODE (p->decl) == FUNCTION_DECL
&& target_node && is_a <cgraph_node *> (target_node)) && 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); cgraph_node *src_node = cgraph_node::get (p->decl);
if (src_node && src_node->definition) if (src_node && src_node->definition)
src_node->reset (); src_node->reset ();
...@@ -1366,10 +1426,11 @@ handle_alias_pairs (void) ...@@ -1366,10 +1426,11 @@ handle_alias_pairs (void)
} }
else 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); p->decl);
warning (0, "%q+D aliased declaration", inform (DECL_SOURCE_LOCATION (target_node->decl),
target_node->decl); "aliased declaration here");
alias_pairs->unordered_remove (i); alias_pairs->unordered_remove (i);
} }
} }
......
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> 2017-09-19 Will Schmidt <will_schmidt@vnet.ibm.com>
* gcc.target/powerpc/fold-vec-ld-misc.c: New. * gcc.target/powerpc/fold-vec-ld-misc.c: New.
......
...@@ -2,33 +2,41 @@ ...@@ -2,33 +2,41 @@
/* { dg-require-ifunc "" } */ /* { dg-require-ifunc "" } */
/* { dg-options "-Wno-pmf-conversions" } */ /* { dg-options "-Wno-pmf-conversions" } */
#include <stdio.h>
struct Klass struct Klass
{ {
int implementation (); int implementation ();
int magic (); int magic ();
static void *resolver ();
typedef int (Klass::*MemFuncPtr)();
static MemFuncPtr resolver ();
}; };
Klass::MemFuncPtr p = &Klass::implementation;
int Klass::implementation (void) int Klass::implementation (void)
{ {
printf ("'ere I am JH\n"); __builtin_printf ("'ere I am JH\n");
return 0; return 1234;
} }
void *Klass::resolver (void)
Klass::MemFuncPtr Klass::resolver (void)
{ {
int (Klass::*pmf) () = &Klass::implementation; return &Klass::implementation;
return (void *)(int (*)(Klass *))(((Klass *)0)->*pmf);
} }
int f (void) __attribute__ ((ifunc ("foo")));
typedef int (F)(void);
extern "C" F* foo () { return 0; }
int Klass::magic (void) __attribute__ ((ifunc ("_ZN5Klass8resolverEv"))); int Klass::magic (void) __attribute__ ((ifunc ("_ZN5Klass8resolverEv")));
int main () int main ()
{ {
Klass obj; Klass obj;
return obj.magic () != 0; return !(obj.magic () == 1234);
} }
...@@ -8,7 +8,10 @@ struct Klass ...@@ -8,7 +8,10 @@ struct Klass
{ {
int implementation (); int implementation ();
int magic (); int magic ();
static void *resolver ();
typedef int (Klass::*MemFuncPtr)();
static MemFuncPtr resolver ();
}; };
int Klass::implementation (void) int Klass::implementation (void)
...@@ -17,11 +20,9 @@ int Klass::implementation (void) ...@@ -17,11 +20,9 @@ int Klass::implementation (void)
return 0; return 0;
} }
void *Klass::resolver (void) Klass::memFuncPtr Klass::resolver (void)
{ {
int (Klass::*pmf) () = &Klass::implementation; return &Klass::implementation;
return (void *)(int (*)(Klass *))(((Klass *)0)->*pmf);
} }
int Klass::magic (void) __attribute__ ((ifunc ("_ZN5Klass8resolverEv"))); int Klass::magic (void) __attribute__ ((ifunc ("_ZN5Klass8resolverEv")));
...@@ -33,6 +34,6 @@ struct Klassier : Klass ...@@ -33,6 +34,6 @@ struct Klassier : Klass
int main () int main ()
{ {
Klassier obj; Klassier obj;
return obj.magic () != 0; return obj.magic () != 0;
} }
...@@ -8,7 +8,10 @@ struct Klass ...@@ -8,7 +8,10 @@ struct Klass
{ {
int implementation (); int implementation ();
int magic (); int magic ();
static void *resolver ();
typedef int (Klass::*MemFuncPtr)();
static MemFuncPtr resolver ();
}; };
int Klass::implementation (void) int Klass::implementation (void)
...@@ -17,11 +20,9 @@ int Klass::implementation (void) ...@@ -17,11 +20,9 @@ int Klass::implementation (void)
return 0; return 0;
} }
void *Klass::resolver (void) Klass::MemFuncPtr Klass::resolver (void)
{ {
int (Klass::*pmf) () = &Klass::implementation; return &Klass::implementation;
return (void *)(int (*)(Klass *))(((Klass *)0)->*pmf);
} }
int Klass::magic (void) __attribute__ ((ifunc ("_ZN5Klass8resolverEv"))); int Klass::magic (void) __attribute__ ((ifunc ("_ZN5Klass8resolverEv")));
...@@ -34,6 +35,6 @@ int Foo (Klass &obj, int (Klass::*pmf) ()) ...@@ -34,6 +35,6 @@ int Foo (Klass &obj, int (Klass::*pmf) ())
int main () int main ()
{ {
Klass obj; Klass obj;
return Foo (obj, &Klass::magic) != 0; return Foo (obj, &Klass::magic) != 0;
} }
...@@ -13,7 +13,10 @@ struct Klassier : Klass ...@@ -13,7 +13,10 @@ struct Klassier : Klass
{ {
int implementation (); int implementation ();
int magic (); int magic ();
static void *resolver ();
typedef int (Klass::*MemFuncPtr)();
static MemFuncPtr resolver ();
}; };
int Klassier::implementation (void) int Klassier::implementation (void)
...@@ -22,11 +25,9 @@ int Klassier::implementation (void) ...@@ -22,11 +25,9 @@ int Klassier::implementation (void)
return 0; return 0;
} }
void *Klassier::resolver (void) Klassier::MemFuncPtr Klassier::resolver (void)
{ {
int (Klassier::*pmf) () = &Klassier::implementation; return &Klassier::implementation;
return (void *)(int (*)(Klassier *))(((Klassier *)0)->*pmf);
} }
int Klassier::magic (void) __attribute__ ((ifunc ("_ZN8Klassier8resolverEv"))); int Klassier::magic (void) __attribute__ ((ifunc ("_ZN8Klassier8resolverEv")));
...@@ -39,6 +40,6 @@ int __attribute__ ((weak)) Foo (Klass &base) ...@@ -39,6 +40,6 @@ int __attribute__ ((weak)) Foo (Klass &base)
int main () int main ()
{ {
Klassier obj; Klassier obj;
return Foo (obj) != 0; return Foo (obj) != 0;
} }
// 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;
}
// { dg-do run } // { dg-do run }
// { dg-options "-fno-strict-aliasing" } // { dg-options "-Wno-attributes -fno-strict-aliasing" }
// Origin: Mark Mitchell <mark@codesourcery.com> // Origin: Mark Mitchell <mark@codesourcery.com>
#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 #if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
...@@ -126,7 +126,8 @@ void S4::s1 () ...@@ -126,7 +126,8 @@ void S4::s1 ()
extern "C" { extern "C" {
/* We can use weakref here without dg-require-weak, because we know /* We can use weakref here without dg-require-weak, because we know
the symbols are defined, so we don't actually issue the .weak 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 S3_s3 () __attribute__((__weakref__ ("_ZN2S32s3Ev")));
static void S4_s1 () __attribute__((__weakref__ ("_ZN2S42s1Ev"))); static void S4_s1 () __attribute__((__weakref__ ("_ZN2S42s1Ev")));
} }
......
...@@ -2,17 +2,17 @@ ...@@ -2,17 +2,17 @@
/* { dg-require-ifunc "" } */ /* { dg-require-ifunc "" } */
/* { dg-options "" } */ /* { dg-options "" } */
#include <stdio.h> typedef int F (void);
static int implementation (void) static int implementation (void)
{ {
printf ("'ere I am JH\n"); __builtin_printf ("'ere I am JH\n");
return 0; return 0;
} }
static void *resolver (void) static F* resolver (void)
{ {
return (void *)implementation; return implementation;
} }
extern int magic (void) __attribute__ ((ifunc ("resolver"))); extern int magic (void) __attribute__ ((ifunc ("resolver")));
......
/* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment