+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
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 ();
}
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);
}
}
+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.
/* { 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);
}
{
int implementation ();
int magic ();
- static void *resolver ();
+
+ typedef int (Klass::*MemFuncPtr)();
+
+ static MemFuncPtr resolver ();
};
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")));
int main ()
{
Klassier obj;
-
+
return obj.magic () != 0;
}
{
int implementation ();
int magic ();
- static void *resolver ();
+
+ typedef int (Klass::*MemFuncPtr)();
+
+ static MemFuncPtr resolver ();
};
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")));
int main ()
{
Klass obj;
-
+
return Foo (obj, &Klass::magic) != 0;
}
{
int implementation ();
int magic ();
- static void *resolver ();
+
+ typedef int (Klass::*MemFuncPtr)();
+
+ static MemFuncPtr resolver ();
};
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")));
int main ()
{
Klassier obj;
-
+
return Foo (obj) != 0;
}
--- /dev/null
+// 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-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
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")));
}
/* { 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")));
--- /dev/null
+/* 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;
+}