Hi,
this patch makes us to diagnoze correctly ODR violations such as:
$ cat tt.C                                                                      
enum test {val1};                                                               
enum test a;                                                                    
$ cat tt2.C                                                                     
enum test {val1, val2};                                                         
enum test b;                                                                    
$ ./xgcc -B ./ -O2 -flto tt.C tt2.C                                             
tt.C:1:6: warning: type 'test' violates one definition rule [-Wodr]             
 enum test {val1};                                                              
      ^                                                                         
tt2.C:1:6: note: an enum with mismatching number of values is defined in 
another translation unit
 enum test {val1, val2};                                                        
      ^                                                                         

OR

$ cat t.C
char a;
$ ./xgcc -B ./ -O2 t.C -o t1.o -fno-signed-char -c -flto
$ ./xgcc -B ./ -O2 t.C -o t2.o -fsigned-char -c -flto
$ ./xgcc -B ./ -O2 t1.o t2.o -flto -fno-signed-char  -flto
<built-in>: warning: type �char� violates one definition rule [-Wodr]
<built-in>: note: a type with different signedness is defined in another 
translation unit
t.C:1:6: warning: type of �a� does not match original declaration
 char a;
      ^
t.C:1:6: note: previously declared here
 char a;
      ^

The char signedness differences happen in Firefox.

Previously we would miss this because tree.c saves mangled name only for
aggregates.  This was useful optimization at a time we used the mangled name
only for type inhertiance graph construction.  I measured its effect at a time
Richard suggested it and the difference was sub 1% on memory use/LTO file sizes
that is hopefully acceptable. (most named types are class types, enums are quite
rare and integer types adds just constant number of new manglings).

One case we still do not handle well in all cases is mismatch in bulitin
types, such as -fsigned-char -fno-signed-char and/or -malign-double.  This is
caused by preloading these types and I guess it comes from bigger problem that
those types gets merged despite their differences.

Bootstrapped/regtested x86_64-linux, will commit it later today.

Honza

        * tree.c (need_assembler_name_p): Compute mangled name for
        non-builtin types.
        * ipa-devirt.c (odr_subtypes_equivalent_p): Non-aggregate types
        may match unnamed to named.
Index: tree.c
===================================================================
--- tree.c      (revision 222391)
+++ tree.c      (working copy)
@@ -5138,7 +5138,17 @@ need_assembler_name_p (tree decl)
       && DECL_NAME (decl)
       && decl == TYPE_NAME (TREE_TYPE (decl))
       && !is_lang_specific (TREE_TYPE (decl))
-      && AGGREGATE_TYPE_P (TREE_TYPE (decl))
+      /* Save some work. Names of builtin types are always derived from
+        properties of its main variant.  A special case are integer types
+        where mangling do make differences between char/signed char/unsigned
+        char etc.  Storing name for these makes e.g.
+        -fno-signed-char/-fsigned-char mismatches to be handled well.
+
+        See cp/mangle.c:write_builtin_type for details.  */
+      && (TREE_CODE (TREE_TYPE (decl)) != VOID_TYPE
+         && TREE_CODE (TREE_TYPE (decl)) != BOOLEAN_TYPE
+         && TREE_CODE (TREE_TYPE (decl)) != REAL_TYPE
+         && TREE_CODE (TREE_TYPE (decl)) != FIXED_POINT_TYPE)
       && !TYPE_ARTIFICIAL (TREE_TYPE (decl))
       && !variably_modified_type_p (TREE_TYPE (decl), NULL_TREE)
       && !type_in_anonymous_namespace_p (TREE_TYPE (decl)))
Index: ipa-devirt.c
===================================================================
--- ipa-devirt.c        (revision 222391)
+++ ipa-devirt.c        (working copy)
@@ -675,7 +675,8 @@ odr_subtypes_equivalent_p (tree t1, tree
      have to be compared structurally.  */
   if (TREE_CODE (t1) != TREE_CODE (t2))
     return false;
-  if ((TYPE_NAME (t1) == NULL_TREE) != (TYPE_NAME (t2) == NULL_TREE))
+  if (AGGREGATE_TYPE_P (t1)
+      && (TYPE_NAME (t1) == NULL_TREE) != (TYPE_NAME (t2) == NULL_TREE))
     return false;
 
   type_pair pair={t1,t2};

Reply via email to