AAPT2: Allow compatible duplicate Attributes

If a resource XML file defines two compatible Attributes, they should
be merged without throwing an error. Ex:

<declare-styleable>
  <attr name="conflict" format="string" />
</declare-styleable>

<declare-styleable>
  <attr name="conflict" format="string|reference" />
</declare-styleable>

In this case, string|reference and string are the same, so these should
merge correctly.

Bug: 65699599
Test: make aapt2_tests
Test: make AaptBasicTest
Change-Id: I7b0f956d2332f7f0b458acd59ca0a606b2cfdf95
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
index a782cd3..77cee06 100644
--- a/tools/aapt2/ResourceValues.cpp
+++ b/tools/aapt2/ResourceValues.cpp
@@ -507,17 +507,10 @@
   }
 }
 
-Attribute::Attribute()
-    : type_mask(0u),
-      min_int(std::numeric_limits<int32_t>::min()),
-      max_int(std::numeric_limits<int32_t>::max()) {
-}
-
-Attribute::Attribute(bool w, uint32_t t)
+Attribute::Attribute(uint32_t t)
     : type_mask(t),
       min_int(std::numeric_limits<int32_t>::min()),
       max_int(std::numeric_limits<int32_t>::max()) {
-  weak_ = w;
 }
 
 std::ostream& operator<<(std::ostream& out, const Attribute::Symbol& s) {
@@ -568,6 +561,20 @@
                     });
 }
 
+bool Attribute::IsCompatibleWith(const Attribute& attr) const {
+  // If the high bits are set on any of these attribute type masks, then they are incompatible.
+  // We don't check that flags and enums are identical.
+  if ((type_mask & ~android::ResTable_map::TYPE_ANY) != 0 ||
+      (attr.type_mask & ~android::ResTable_map::TYPE_ANY) != 0) {
+    return false;
+  }
+
+  // Every attribute accepts a reference.
+  uint32_t this_type_mask = type_mask | android::ResTable_map::TYPE_REFERENCE;
+  uint32_t that_type_mask = attr.type_mask | android::ResTable_map::TYPE_REFERENCE;
+  return this_type_mask == that_type_mask;
+}
+
 Attribute* Attribute::Clone(StringPool* /*new_pool*/) const {
   return new Attribute(*this);
 }