Transparent alias suport part 11: fix warning and error attributes with LTO

Jan Hubicka hubicka@ucw.cz
Thu Dec 10 23:12:00 GMT 2015


Hi,
this patch makes lto-symtab to not merge decls where warning and error
attributes mismatch and finally clears up the invalid wanring compiling
testcase from PR 61886.

So it took only 11 patches and year and half to fix this beast...

I am now finished with merging the original transparent alias patchset.  I am
going to do some bigger scale testing with LTO decl and tree merging disabled
and also try to provoke some wrong code from PTA that ought to need an update
(to track global vars correctly) but for some reason nothing I tested so far
cares.  This does not affect the existing uses of warning/error attributes
in glibc, so I think the fix for PR ipa/61886 does not need to wait for that.

Bootstrapped/regtested x86_64-linux, will commit it after lto-bootstrap
converges.

Honza

	PR ipa/61886
	* lto-symtab.c (lto_symtab_merge_p): Avoid merging across different
	values of error and warning attributes.
	* gcc.dg/lto/pr61886_0.c: New testcase
Index: lto/lto-symtab.c
===================================================================
--- lto/lto-symtab.c	(revision 231539)
+++ lto/lto-symtab.c	(working copy)
@@ -511,19 +511,59 @@ static bool
 lto_symtab_merge_p (tree prevailing, tree decl)
 {
   if (TREE_CODE (prevailing) != TREE_CODE (decl))
-    return false;
+    {
+      if (symtab->dump_file)
+	fprintf (symtab->dump_file, "Not merging decls; "
+		 "TREE_CODE mismatch\n");
+      return false;
+    }
   if (TREE_CODE (prevailing) == FUNCTION_DECL)
     {
       if (DECL_BUILT_IN (prevailing) != DECL_BUILT_IN (decl))
-	return false;
+	{
+          if (symtab->dump_file)
+	    fprintf (symtab->dump_file, "Not merging decls; "
+		     "DECL_BUILT_IN mismatch\n");
+	  return false;
+	}
       if (DECL_BUILT_IN (prevailing)
 	  && (DECL_BUILT_IN_CLASS (prevailing) != DECL_BUILT_IN_CLASS (decl)
 	      || DECL_FUNCTION_CODE (prevailing) != DECL_FUNCTION_CODE (decl)))
-	return false;
+	{
+          if (symtab->dump_file)
+	    fprintf (symtab->dump_file, "Not merging decls; "
+		     "DECL_BUILT_IN_CLASS or CODE mismatch\n");
+	  return false;
+	}
+    }
+  if (DECL_ATTRIBUTES (prevailing) != DECL_ATTRIBUTES (decl))
+    {
+      tree prev_attr = lookup_attribute ("error", DECL_ATTRIBUTES (prevailing));
+      tree attr = lookup_attribute ("error", DECL_ATTRIBUTES (decl));
+      if ((prev_attr == NULL) != (attr == NULL)
+	  || (prev_attr
+	      && TREE_VALUE (TREE_VALUE (prev_attr))
+		 != TREE_VALUE (TREE_VALUE (attr))))
+	{
+          if (symtab->dump_file)
+	    fprintf (symtab->dump_file, "Not merging decls; "
+		     "error attribute mismatch\n");
+	  return false;
+	}
+
+      prev_attr = lookup_attribute ("warning", DECL_ATTRIBUTES (prevailing));
+      attr = lookup_attribute ("warning", DECL_ATTRIBUTES (decl));
+      if ((prev_attr == NULL) != (attr == NULL)
+	  || (prev_attr
+	      && TREE_VALUE (TREE_VALUE (prev_attr))
+		 != TREE_VALUE (TREE_VALUE (attr))))
+	{
+          if (symtab->dump_file)
+	    fprintf (symtab->dump_file, "Not merging decls; "
+		     "warning attribute mismatch\n");
+	  return false;
+	}
     }
-  /* There are several other cases where merging can not be done, but until
-     aliasing code is fixed to support aliases it we can not really return
-     false on non-readonly var, yet.  */
   return true;
 }
 
Index: testsuite/gcc.dg/lto/pr61886_0.c
===================================================================
--- testsuite/gcc.dg/lto/pr61886_0.c	(revision 0)
+++ testsuite/gcc.dg/lto/pr61886_0.c	(revision 0)
@@ -0,0 +1,33 @@
+/* { dg-lto-do link } */
+/* { dg-lto-options { { -flto -O2 -Werror } } } */
+
+typedef __SIZE_TYPE__ size_t;
+typedef struct _IO_FILE FILE;
+
+extern size_t __fread_chk (void *__restrict __ptr, size_t __ptrlen, size_t __size, size_t __n, FILE *__restrict __stream) __asm__ ("" "__fread_chk")      __attribute__ ((__warn_unused_result__));
+extern size_t __fread_chk_warn (void *__restrict __ptr, size_t __ptrlen, size_t __size, size_t __n, FILE *__restrict __stream) __asm__ ("" "__fread_chk")      __attribute__ ((__warn_unused_result__)) __attribute__((__warning__ ("fread called with bigger size * nmemb than length " "of destination buffer")));
+
+extern __inline __attribute__ ((__always_inline__)) __attribute__ ((__gnu_inline__)) __attribute__ ((__artificial__)) __attribute__ ((__warn_unused_result__))
+size_t
+fread (void *__restrict __ptr, size_t __size, size_t __n,
+       FILE *__restrict __stream)
+{
+  if (__builtin_object_size (__ptr, 0) != (size_t) -1)
+    {
+      if (!__builtin_constant_p (__size)
+          || !__builtin_constant_p (__n)
+          || (__size | __n) >= (((size_t) 1) << (8 * sizeof (size_t) / 2)))
+        return __fread_chk (__ptr, __builtin_object_size (__ptr, 0), __size, __n, __stream);
+      if (__size * __n > __builtin_object_size (__ptr, 0))
+        return __fread_chk_warn (__ptr, __builtin_object_size (__ptr, 0), __size, __n, __stream);
+    }
+}
+
+volatile size_t nmemb;
+FILE *fp;
+int main ()
+{
+  char file_contents[4096];
+  /* We shouldn't get this resolved to a call to __fread_chk_warn.  */
+  return fread (file_contents, 1, nmemb, fp);
+}



More information about the Gcc-patches mailing list