Make recursive methods in Type work with cyclic AST

Fixes Type::canCheckEquality, Type::needsResolveReferences,
Type::isJavaCompatible, Type:containsPointer.

Adds set of visited Types to these functions to prevent
infinite recursion.

deep versions of these functions *do not* guarantee the correct
return value, but non-deep versions do:
We need to find al least one path from requested vertex
to "bad" vertex (ie. which is not java compatible).

Fixes a bug with containsPointer (containsPointer returned true
if inner type contained a pointer), so more structures get
__attribute__ aligned and static_assert generated for
struct fields.

This change is required for forward reference, as current
implementations assume that the graph is acyclic.

Potential future work: to reduce theoretical complexity of
described actions (square to linear).

Bug: 31827278

Test: mma
Test: output not changed in
  out/soong/.intermediates/hardware/interfaces

Change-Id: I3dbdd1605f9317637241057b12de6031125abf7b
diff --git a/CompoundType.cpp b/CompoundType.cpp
index 0254a6c..d70bc78 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -91,12 +91,12 @@
     return true;
 }
 
-bool CompoundType::canCheckEquality() const {
+bool CompoundType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const {
     if (mStyle == STYLE_UNION) {
         return false;
     }
-    for (const auto &field : *mFields) {
-        if (!field->type().canCheckEquality()) {
+    for (const auto* field : *mFields) {
+        if (!field->get()->canCheckEquality(visited)) {
             return false;
         }
     }
@@ -988,18 +988,18 @@
     return false;
 }
 
-bool CompoundType::needsResolveReferences() const {
+bool CompoundType::deepNeedsResolveReferences(std::unordered_set<const Type*>* visited) const {
     if (mStyle != STYLE_STRUCT) {
         return false;
     }
 
     for (const auto &field : *mFields) {
-        if (field->type().needsResolveReferences()) {
+        if (field->type().needsResolveReferences(visited)) {
             return true;
         }
     }
 
-    return false;
+    return Scope::deepNeedsResolveReferences(visited);
 }
 
 bool CompoundType::resultNeedsDeref() const {
@@ -1066,32 +1066,28 @@
     return OK;
 }
 
-bool CompoundType::isJavaCompatible() const {
-    if (mStyle != STYLE_STRUCT || !Scope::isJavaCompatible()) {
+bool CompoundType::deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const {
+    if (mStyle != STYLE_STRUCT) {
         return false;
     }
 
-    for (const auto &field : *mFields) {
-        if (!field->type().isJavaCompatible()) {
+    for (const auto* field : *mFields) {
+        if (!field->get()->isJavaCompatible(visited)) {
             return false;
         }
     }
 
-    return true;
+    return Scope::deepIsJavaCompatible(visited);
 }
 
-bool CompoundType::containsPointer() const {
-    if (Scope::containsPointer()) {
-        return true;
-    }
-
-    for (const auto &field : *mFields) {
-        if (field->type().containsPointer()) {
+bool CompoundType::deepContainsPointer(std::unordered_set<const Type*>* visited) const {
+    for (const auto* field : *mFields) {
+        if (field->get()->containsPointer(visited)) {
             return true;
         }
     }
 
-    return false;
+    return Scope::deepContainsPointer(visited);
 }
 
 void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {