* params.def (hot-bb-count-ws-permille): Set to 990.
+2019-01-04 Martin Sebor <msebor@redhat.com>
+
+ PR c/88546
+ * attribs.c (decls_mismatched_attributes): Avoid warning for attribute
+ leaf.
+
2019-01-04 Martin Sebor <msebor@redhat.com>
PR c/88363
for (unsigned i = 0; blacklist[i]; ++i)
{
+ /* Attribute leaf only applies to extern functions. Avoid mentioning
+ it when it's missing from a static declaration. */
+ if (!TREE_PUBLIC (decl)
+ && !strcmp ("leaf", blacklist[i]))
+ continue;
+
for (unsigned j = 0; j != 2; ++j)
{
if (!has_attribute (tmpls[j], tmpl_attrs[j], blacklist[i]))
+2019-01-04 Martin Sebor <msebor@redhat.com>
+
+ PR c/88546
+ * c-attribs.c (handle_copy_attribute): Avoid copying attribute leaf.
+ Handle C++ empty throw specification and C11 _Noreturn.
+ (has_attribute): Also handle C11 _Noreturn.
+
2019-01-04 Martin Sebor <msebor@redhat.com>
PR c/88363
|| is_attribute_p ("weakref", atname))
continue;
+ /* Attribute leaf only applies to extern functions.
+ Avoid copying it to static ones. */
+ if (!TREE_PUBLIC (decl)
+ && is_attribute_p ("leaf", atname))
+ continue;
+
tree atargs = TREE_VALUE (at);
/* Create a copy of just the one attribute ar AT, including
its argumentsm and add it to DECL. */
return NULL_TREE;
}
+ /* A function declared with attribute nothrow has the attribute
+ attached to it, but a C++ throw() function does not. */
+ if (TREE_NOTHROW (ref))
+ TREE_NOTHROW (decl) = true;
+
+ /* Similarly, a function declared with attribute noreturn has it
+ attached on to it, but a C11 _Noreturn function does not. */
tree reftype = ref;
+ if (DECL_P (ref)
+ && TREE_THIS_VOLATILE (ref)
+ && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (reftype)))
+ TREE_THIS_VOLATILE (decl) = true;
+
if (DECL_P (ref) || EXPR_P (ref))
reftype = TREE_TYPE (ref);
if (POINTER_TYPE_P (reftype))
reftype = TREE_TYPE (reftype);
+ if (!TYPE_P (reftype))
+ return NULL_TREE;
+
tree attrs = TYPE_ATTRIBUTES (reftype);
/* Copy type attributes from REF to DECL. */
if (expr && DECL_P (expr))
found_match = TREE_READONLY (expr);
}
+ else if (!strcmp ("noreturn", namestr))
+ {
+ /* C11 _Noreturn sets the volatile bit without attaching
+ an attribute to the decl. */
+ if (expr
+ && DECL_P (expr)
+ && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (expr)))
+ found_match = TREE_THIS_VOLATILE (expr);
+ }
else if (!strcmp ("pure", namestr))
{
if (expr && DECL_P (expr))
+2019-01-04 Martin Sebor <msebor@redhat.com>
+
+ PR c/88546
+ * g++.dg/ext/attr-copy.C: New test.
+ * gcc.dg/attr-copy-4.c: Disable macro expansion tracking.
+ * gcc.dg/attr-copy-6.c: New test.
+ * gcc.dg/attr-copy-7.c: New test.
+
2019-01-04 Martin Sebor <msebor@redhat.com>
PR c/88363
--- /dev/null
+/* PR middle-end/88546 - Copy attribute unusable for weakrefs
+ { dg-do compile }
+ { dg-options "-O1 -Wall -fdump-tree-optimized" }
+ { dg-require-weak "" } */
+
+#define ATTR(...) __attribute__ ((__VA_ARGS__))
+#define ASRT(expr) _Static_assert (expr, #expr)
+
+extern "C" {
+
+ ATTR (leaf, nothrow) int
+ fnothrow ()
+ {
+ return 0;
+ }
+
+ static __typeof__ (fnothrow)
+ ATTR (weakref ("fnothrow"), copy (fnothrow))
+ alias_fnothrow;
+
+
+ ATTR (leaf) int
+ fthrow_none () throw ()
+ {
+ return 0;
+ }
+
+ // Verify that no warning is issued for the alias having less
+ // restrictive attributes than the target: nothrow.
+ static __typeof (fthrow_none)
+ ATTR (weakref ("fthrow_none"), copy (fthrow_none))
+ alias_fthrow_none;
+
+ // Same as above but with no definition of the target.
+ ATTR (leaf) int
+ fthrow_none_nodef () throw ();
+
+ static __typeof (fthrow_none_nodef)
+ ATTR (weakref ("fthrow_none_nodef"), copy (fthrow_none_nodef))
+ alias_fthrow_none_nodef;
+
+ // And again but without using typeof to make sure the nothrow
+ // bit is copied by attribute copy alone.
+ static int
+ ATTR (weakref ("fthrow_none_nodef"), copy (fthrow_none_nodef))
+ alias_fthrow_none_nodef_func ();
+}
+
+
+struct UsrClass
+{
+ ~UsrClass ();
+};
+
+// Verify that the nothrow attribute/bit was copied to the alias and
+// that no exception handling code is emitted in any of these calls.
+
+int call_alias_fnothrow ()
+{
+ UsrClass usr;
+ return alias_fnothrow ();
+}
+
+int call_alias_fthrow_none ()
+{
+ UsrClass usr;
+ return alias_fthrow_none ();
+}
+
+int call_alias_fthrow_none_nodef ()
+{
+ UsrClass usr;
+ return alias_fthrow_none_nodef ();
+}
+
+int call_alias_fthrow_none_nodef_func ()
+{
+ UsrClass usr;
+ return alias_fthrow_none_nodef_func ();
+}
+
+// { dg-final { scan-tree-dump-not "__builtin_unwind" "optimized" } }
/* PR middle-end/81824 - Warn for missing attributes with function aliases
Exercise attribute copy for types.
{ dg-do compile }
- { dg-options "-O2 -Wall" } */
+ { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */
#define Assert(expr) typedef char AssertExpr[2 * !!(expr) - 1]
--- /dev/null
+/* PR middle-end/88546 - Copy attribute unusable for weakrefs
+ { dg-do compile }
+ { dg-options "-O2 -Wall" }
+ { dg-require-weak "" } */
+
+#define ATTR(...) __attribute__ ((__VA_ARGS__))
+#define ASRT(expr) _Static_assert (expr, #expr)
+
+/* Variable that is local to this translation unit but that can
+ be modified from other units by calling reset_unit_local(). */
+static int unit_local;
+
+void reset_unit_local (void)
+{
+ unit_local = 0;
+}
+
+/* Attribute leaf implies that fleaf() doesn't modify unit_local(). */
+ATTR (leaf, returns_nonnull)
+void* fleaf_retnz (void);
+
+/* Verify both attributes have been applied. */
+ASRT (__builtin_has_attribute (fleaf_retnz, leaf));
+ASRT (__builtin_has_attribute (fleaf_retnz, returns_nonnull));
+
+/* Verify that attribute leaf has the expected effect. */
+void call_fleaf_retnz (void)
+{
+ int i = unit_local;
+ void *p = fleaf_retnz ();
+
+ /* Expect both tests to be folded to false and the calls eliminated. */
+ extern void call_fleaf_retnz_test_leaf_eliminated (void);
+ if (i != unit_local)
+ call_fleaf_retnz_test_leaf_eliminated ();
+
+ extern void call_fleaf_retnz_test_nonnull_eliminated (void);
+ if (p == 0)
+ call_fleaf_retnz_test_nonnull_eliminated ();
+}
+
+
+/* Verify that attribute copy copies the returns_nonnull attribute
+ but doesn't try to copy attribute leaf which only applies to extern
+ function. */
+static ATTR (copy (fleaf_retnz), weakref ("fleaf_retnz"))
+void* fweakref_fleaf_retnz_copy (void);
+
+ASRT (!__builtin_has_attribute (fweakref_fleaf_retnz_copy, leaf));
+ASRT (__builtin_has_attribute (fweakref_fleaf_retnz_copy, returns_nonnull));
+
+void call_fweakref_fleaf_retnz_copy (void)
+{
+ int i = unit_local;
+ void *p = fweakref_fleaf_retnz_copy ();
+
+ /* Since leaf is not copied, expect the following test not to be
+ folded and the call to be emitted. */
+ extern void call_fweakref_test_leaf_emitted (void);
+ if (i != unit_local)
+ call_fweakref_test_leaf_emitted ();
+
+ /* Expect the following test to be folded to false and the call
+ eliminated. */
+ extern void call_fweakref_fleaf_nonnull_eliminated (void);
+ if (p == 0)
+ call_fweakref_fleaf_nonnull_eliminated ();
+}
+
+/* This is reduced from libgfortran/runtime/error.c. Verify it
+ doesn't trigger warnings and that the noreturn bit is copied
+ to the alias by verifying that calling the alias in a non-void
+ function with no return statement isn't diagnosed. */
+
+extern _Noreturn void fnoreturn (void);
+
+extern __typeof (fnoreturn)
+ ATTR (visibility ("hidden"))
+ fnoreturn __asm__ ("fnoreturn_name");
+
+void fnoreturn (void)
+{
+ __builtin_abort ();
+}
+
+extern __typeof (fnoreturn)
+ ATTR (alias ("fnoreturn_name"), copy (fnoreturn))
+ fnoreturn_alias;
+
+int call_fnoreturn_alias (void)
+{
+ fnoreturn_alias ();
+}
--- /dev/null
+/* PR middle-end/88546 - Copy attribute unusable for weakrefs
+ Verify that attribute noreturn (represented as volatile on function
+ decls) is interpreted correctly and doesn't affect variables.
+ { dg-do compile }
+ { dg-options "-O1 -Wall -fdump-tree-optimized" }*/
+
+#define ATTR(...) __attribute__ ((__VA_ARGS__))
+#define ASRT(expr) _Static_assert (expr, #expr)
+
+ATTR (noreturn) void fnoreturn (void);
+ATTR (copy (fnoreturn)) void fnoreturn_copy (void);
+ASRT (__builtin_has_attribute (fnoreturn_copy, noreturn));
+
+int call_fnoreturn_copy (void)
+{
+ fnoreturn_copy ();
+ fnoreturn_copy (); // should be eliminated
+}
+
+// { dg-final { scan-tree-dump-times "fnoreturn_copy \\(\\);" 1 "optimized" } }
+
+
+_Noreturn void f_Noreturn (void);
+ATTR (copy (f_Noreturn)) void f_Noreturn_copy (void);
+ASRT (__builtin_has_attribute (f_Noreturn_copy, noreturn));
+
+int call_f_Noreturn_copy (void)
+{
+ f_Noreturn_copy ();
+ f_Noreturn_copy (); // should be eliminated
+}
+
+// { dg-final { scan-tree-dump-times "f_Noreturn_copy \\(\\);" 1 "optimized" } }
+
+
+// Verify the combination of both is accepted and works too,
+// just for fun.
+ATTR (noreturn) _Noreturn void fnoreturn_Noreturn (void);
+ATTR (copy (fnoreturn_Noreturn)) void fnoreturn_Noreturn_copy (void);
+ASRT (__builtin_has_attribute (fnoreturn_Noreturn_copy, noreturn));
+
+int call_fnoreturn_Noreturn_copy (void)
+{
+ fnoreturn_Noreturn_copy ();
+ fnoreturn_Noreturn_copy (); // should be eliminated
+}
+
+// { dg-final { scan-tree-dump-times "fnoreturn_Noreturn_copy \\(\\);" 1 "optimized" } }
+
+
+typedef void func_t (void);
+
+ATTR (noreturn) func_t func_noreturn;
+ATTR (copy (func_noreturn)) func_t func_noreturn_copy;
+ASRT (__builtin_has_attribute (func_noreturn_copy, noreturn));
+
+int call_func_noreturn_copy (void)
+{
+ func_noreturn_copy ();
+ func_noreturn_copy (); // should be eliminated
+}
+
+// { dg-final { scan-tree-dump-times "func_noreturn_copy \\(\\);" 1 "optimized" } }
+
+
+// Finally, verify that the volatile bit isn't copied for variables.
+extern volatile int vi;
+
+int read_nonvolatile (void)
+{
+ ATTR (copy (vi)) int i = 0;
+
+ return i + i; // should be folded to return 0;
+}
+
+// { dg-final { scan-tree-dump-times "return 0;" 1 "optimized" } }
# define __gthrw_pragma(pragma)
# endif
# define __gthrw2(name,name2,type) \
- static __typeof(type) name __attribute__ ((__weakref__(#name2))); \
+ static __typeof(type) name \
+ __attribute__ ((__weakref__(#name2), __copy__ (type))); \
__gthrw_pragma(weak type)
# define __gthrw_(name) __gthrw_ ## name
#else
# define iexport(x) iexport1(x, IPREFIX(x))
# define iexport1(x,y) iexport2(x,y)
# define iexport2(x,y) \
- extern __typeof(x) PREFIX(x) __attribute__((__alias__(#y)))
+ extern __typeof(x) PREFIX(x) __attribute__((__alias__(#y), __copy__ (x)))
#else
# define export_proto(x) sym_rename(x, PREFIX(x))
# define export_proto_np(x) extern char swallow_semicolon