Move type-related stuff ouside of parsing

3 new passes: resolving inheritance, evaluating constant expressions and
validation.

`resolveInheritance` completes type fields definition which depends on
type base class (so it needs to be looked up before this pass). That
includes interface method serial autofill and enum value autofill.

`evaluate` evaluates constant expressions. This pass depends on the
previous one as enum autofill creates new expressions (+1s).

`validate` proceedes all type-related checks.

`callForReference` is a special way of calling passes for types:
it is used for types that are defined in reference.
Currently that is only array type (size is defined in reference only)
and template type as it could contain an array.
We need such special way to avoid cyclic evaluate call:
struct S { S[42] arr; };

Test: full build, device boot
Test: hidl_test
Test: full build on mac
Test: generated files differ only in constant expression comments

Change-Id: I499e62ae41c52cc86b13d0014eed790454137af6
diff --git a/Interface.cpp b/Interface.cpp
index 208a83d..f55be18 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -30,6 +30,7 @@
 #include <iostream>
 #include <memory>
 #include <sstream>
+#include <unordered_map>
 
 #include <android-base/logging.h>
 #include <hidl-hash/Hash.h>
@@ -454,28 +455,89 @@
     }
 
     CHECK(!method->isHidlReserved());
-    if (lookupMethod(method->name()) != nullptr) {
-        LOG(ERROR) << "Redefinition of method " << method->name();
-        return false;
-    }
-    size_t serial = FIRST_CALL_TRANSACTION;
-
-    serial += userDefinedMethods().size();
-
-    const Interface* ancestor = superType();
-    while (ancestor != nullptr) {
-        serial += ancestor->userDefinedMethods().size();
-        ancestor = ancestor->superType();
-    }
-
-    CHECK(serial <= LAST_CALL_TRANSACTION) << "More than "
-            << LAST_CALL_TRANSACTION << " methods are not allowed.";
-    method->setSerialId(serial);
     mUserMethods.push_back(method);
 
     return true;
 }
 
+status_t Interface::resolveInheritance() {
+    size_t serial = FIRST_CALL_TRANSACTION;
+    for (const auto* ancestor : superTypeChain()) {
+        serial += ancestor->mUserMethods.size();
+    }
+
+    for (Method* method : mUserMethods) {
+        if (serial > LAST_CALL_TRANSACTION) {
+            std::cerr << "ERROR: More than " << LAST_CALL_TRANSACTION
+                      << " methods (including super and reserved) are not allowed at " << location()
+                      << "\n";
+            return UNKNOWN_ERROR;
+        }
+
+        method->setSerialId(serial);
+        serial++;
+    }
+
+    return Scope::resolveInheritance();
+}
+
+status_t Interface::evaluate() {
+    for (auto* method : methods()) {
+        status_t err = method->evaluate();
+        if (err != OK) return err;
+    }
+
+    return Scope::evaluate();
+}
+
+status_t Interface::validate() const {
+    CHECK(isIBase() == mSuperType.isEmptyReference());
+
+    for (const auto* method : methods()) {
+        status_t err = method->validate();
+        if (err != OK) return err;
+    }
+
+    status_t err = validateUniqueNames();
+    if (err != OK) return err;
+
+    return Scope::validate();
+}
+
+status_t Interface::validateUniqueNames() const {
+    std::unordered_map<std::string, const Interface*> registeredMethodNames;
+    for (auto const& tuple : allSuperMethodsFromRoot()) {
+        // No need to check super method uniqueness
+        registeredMethodNames[tuple.method()->name()] = tuple.interface();
+    }
+
+    for (const Method* method : mUserMethods) {
+        auto registered = registeredMethodNames.find(method->name());
+
+        if (registered != registeredMethodNames.end()) {
+            const Interface* definedInType = registered->second;
+
+            if (definedInType == this) {
+                // Defined in this interface
+                std::cerr << "ERROR: Redefinition of method '" << method->name() << "'";
+            } else if (definedInType->isIBase()) {
+                // Defined in IBase
+                std::cerr << "ERROR: Redefinition of reserved method '" << method->name() << "'";
+            } else {
+                // Defined in super not IBase
+                std::cerr << "ERROR: Redefinition of method '" << method->name()
+                          << "'' defined in interface '" << definedInType->fullName() << "'";
+            }
+            std::cerr << " at " << method->location() << "\n";
+            return UNKNOWN_ERROR;
+        }
+
+        registeredMethodNames[method->name()] = this;
+    }
+
+    return OK;
+}
+
 bool Interface::addAllReservedMethods() {
     // use a sorted map to insert them in serial ID order.
     std::map<int32_t, Method *> reservedMethodsById;