Fix two bugs in operand_equal_p
authorJan Hubicka <jh@suse.cz>
Thu, 19 Nov 2020 19:16:26 +0000 (20:16 +0100)
committerJan Hubicka <jh@suse.cz>
Thu, 19 Nov 2020 19:16:26 +0000 (20:16 +0100)
* fold-const.c (operand_compare::operand_equal_p): Fix thinko in
COMPONENT_REF handling and guard types_same_for_odr by
virtual_method_call_p.
(operand_compare::hash_operand): Likewise.

gcc/fold-const.c

index 820b08d26fd4d25d5f98f9e42d15d5b630b51f42..c2cf1a94f945c9525e5b20584916d1c0abd4c146 100644 (file)
@@ -3314,30 +3314,34 @@ operand_compare::operand_equal_p (const_tree arg0, const_tree arg1,
             may be NULL when we're called to compare MEM_EXPRs.  */
          if (!OP_SAME_WITH_NULL (0))
            return false;
-         /* Most of time we only need to compare FIELD_DECLs for equality.
-            However when determining address look into actual offsets.
-            These may match for unions and unshared record types.  */
-         flags &= ~OEP_ADDRESS_OF;
-         if (!OP_SAME (1))
-           {
-             if (flags & OEP_ADDRESS_OF)
-               {
-                 if (TREE_OPERAND (arg0, 2)
-                     || TREE_OPERAND (arg1, 2))
-                   return OP_SAME_WITH_NULL (2);
-                 tree field0 = TREE_OPERAND (arg0, 1);
-                 tree field1 = TREE_OPERAND (arg1, 1);
-
-                 if (!operand_equal_p (DECL_FIELD_OFFSET (field0),
-                                       DECL_FIELD_OFFSET (field1), flags)
-                     || !operand_equal_p (DECL_FIELD_BIT_OFFSET (field0),
-                                          DECL_FIELD_BIT_OFFSET (field1),
-                                          flags))
-                   return false;
-               }
-             else
-               return false;
-           }
+         {
+           bool compare_address = flags & OEP_ADDRESS_OF;
+
+           /* Most of time we only need to compare FIELD_DECLs for equality.
+              However when determining address look into actual offsets.
+              These may match for unions and unshared record types.  */
+           flags &= ~OEP_ADDRESS_OF;
+           if (!OP_SAME (1))
+             {
+               if (compare_address)
+                 {
+                   if (TREE_OPERAND (arg0, 2)
+                       || TREE_OPERAND (arg1, 2))
+                     return OP_SAME_WITH_NULL (2);
+                   tree field0 = TREE_OPERAND (arg0, 1);
+                   tree field1 = TREE_OPERAND (arg1, 1);
+
+                   if (!operand_equal_p (DECL_FIELD_OFFSET (field0),
+                                         DECL_FIELD_OFFSET (field1), flags)
+                       || !operand_equal_p (DECL_FIELD_BIT_OFFSET (field0),
+                                            DECL_FIELD_BIT_OFFSET (field1),
+                                            flags))
+                     return false;
+                 }
+               else
+                 return false;
+             }
+         }
          return OP_SAME_WITH_NULL (2);
 
        case BIT_FIELD_REF:
@@ -3436,10 +3440,14 @@ operand_compare::operand_equal_p (const_tree arg0, const_tree arg1,
        if (!operand_equal_p (OBJ_TYPE_REF_OBJECT (arg0),
                              OBJ_TYPE_REF_OBJECT (arg1), flags))
          return false;
-       if (!types_same_for_odr (obj_type_ref_class (arg0),
-                                obj_type_ref_class (arg1)))
-         return false;
-       return true;
+       if (virtual_method_call_p (arg0))
+         {
+           if (!virtual_method_call_p (arg1))
+             return false;
+           return types_same_for_odr (obj_type_ref_class (arg0),
+                                      obj_type_ref_class (arg1));
+         }
+       return false;
 
        default:
          return false;
@@ -3866,6 +3874,8 @@ operand_compare::hash_operand (const_tree t, inchash::hash &hstate,
              flags &= ~OEP_ADDRESS_OF;
              inchash::add_expr (OBJ_TYPE_REF_TOKEN (t), hstate, flags);
              inchash::add_expr (OBJ_TYPE_REF_OBJECT (t), hstate, flags);
+             if (!virtual_method_call_p (t))
+               return;
              if (tree c = obj_type_ref_class (t))
                {
                  c = TYPE_NAME (TYPE_MAIN_VARIANT (c));