aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2019-01-05 00:57:30 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2019-01-04 17:57:30 -0700
commit29d2485270f422a4b89bfa79e448843509cd0568 (patch)
treef1e8cf0a03dff36fd00f2c23d9cebce2ecbc3871 /gcc
parentf6be1179bb66624403d0f55620d67344d9d98c51 (diff)
downloadgcc-29d2485270f422a4b89bfa79e448843509cd0568.zip
gcc-29d2485270f422a4b89bfa79e448843509cd0568.tar.gz
gcc-29d2485270f422a4b89bfa79e448843509cd0568.tar.bz2
PR c/88546 - Copy attribute unusable for weakrefs
gcc/c-family/ChangeLog: 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. gcc/ChangeLog: PR c/88546 * attribs.c (decls_mismatched_attributes): Avoid warning for attribute leaf. gcc/testsuite/ChangeLog: 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. From-SVN: r267591
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/attribs.c6
-rw-r--r--gcc/c-family/ChangeLog7
-rw-r--r--gcc/c-family/c-attribs.c30
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-copy.C82
-rw-r--r--gcc/testsuite/gcc.dg/attr-copy-4.c2
-rw-r--r--gcc/testsuite/gcc.dg/attr-copy-6.c93
-rw-r--r--gcc/testsuite/gcc.dg/attr-copy-7.c76
9 files changed, 309 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 142323d..87be8ae 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -4,6 +4,12 @@
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
* doc/extend.texi (attribute alloc_align, alloc_size): Update.
diff --git a/gcc/attribs.c b/gcc/attribs.c
index 3b4084e..d9b6a04 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -1912,6 +1912,12 @@ decls_mismatched_attributes (tree tmpl, tree decl, tree attrlist,
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]))
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 55e6ee8..b407f1c 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,5 +1,12 @@
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
* c-attribs.c (positional_argument): Also accept enumerated types.
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 03978dd..c893baa 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -2461,6 +2461,12 @@ handle_copy_attribute (tree *node, tree name, tree args,
|| 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. */
@@ -2478,13 +2484,28 @@ handle_copy_attribute (tree *node, tree name, tree args,
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. */
@@ -4194,6 +4215,15 @@ has_attribute (location_t atloc, tree t, tree attr, tree (*convert)(tree))
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))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d0add03..b3f8d88 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,13 @@
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
* c-c++-common/attributes-4.c: New test.
diff --git a/gcc/testsuite/g++.dg/ext/attr-copy.C b/gcc/testsuite/g++.dg/ext/attr-copy.C
new file mode 100644
index 0000000..d475cd5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attr-copy.C
@@ -0,0 +1,82 @@
+/* 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" } }
diff --git a/gcc/testsuite/gcc.dg/attr-copy-4.c b/gcc/testsuite/gcc.dg/attr-copy-4.c
index 7020bad..1350a35 100644
--- a/gcc/testsuite/gcc.dg/attr-copy-4.c
+++ b/gcc/testsuite/gcc.dg/attr-copy-4.c
@@ -1,7 +1,7 @@
/* 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]
diff --git a/gcc/testsuite/gcc.dg/attr-copy-6.c b/gcc/testsuite/gcc.dg/attr-copy-6.c
new file mode 100644
index 0000000..17e714e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-copy-6.c
@@ -0,0 +1,93 @@
+/* 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 ();
+}
diff --git a/gcc/testsuite/gcc.dg/attr-copy-7.c b/gcc/testsuite/gcc.dg/attr-copy-7.c
new file mode 100644
index 0000000..a9c49bd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-copy-7.c
@@ -0,0 +1,76 @@
+/* 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" } }