Get rid if Reference<Interface>

This change allows to have
std::vector<Reference<Type>*> getReferences()
                           ^
Thus we can make recursive lookup be like:
for ref : getReferences() { ref->lookup() }

The check that Interface expends only interfaces is moved to
Interface::validate.

Bug: 31827278
Test: mma
Test: new error test

Change-Id: I8e81b1bdf5658749d4b33d02e812a49765dc03bb
diff --git a/Interface.cpp b/Interface.cpp
index 9d785e7..79824ae 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -70,7 +70,7 @@
 };
 
 Interface::Interface(const char* localName, const Location& location, Scope* parent,
-                     const Reference<Interface>& superType)
+                     const Reference<Type>& superType)
     : Scope(localName, location, parent),
       mSuperType(superType),
       mIsJavaCompatibleInProgress(false) {}
@@ -508,6 +508,11 @@
 status_t Interface::validate() const {
     CHECK(isIBase() == mSuperType.isEmptyReference());
 
+    if (!isIBase() && !mSuperType->isInterface()) {
+        std::cerr << "ERROR: You can only extend interfaces at " << mSuperType.location() << "\n";
+        return UNKNOWN_ERROR;
+    }
+
     for (const auto* method : methods()) {
         status_t err = method->validate();
         if (err != OK) return err;
@@ -589,7 +594,13 @@
 }
 
 const Interface* Interface::superType() const {
-    return isIBase() ? nullptr : mSuperType;
+    if (isIBase()) return nullptr;
+    if (!mSuperType->isInterface()) {
+        // This is actually an error
+        // that would be caught in validate
+        return nullptr;
+    }
+    return static_cast<Interface*>(mSuperType.get());
 }
 
 std::vector<const Interface *> Interface::typeChain() const {
diff --git a/Interface.h b/Interface.h
index 16c77fe..b664fdf 100644
--- a/Interface.h
+++ b/Interface.h
@@ -30,7 +30,7 @@
 
 struct Interface : public Scope {
     Interface(const char* localName, const Location& location, Scope* parent,
-              const Reference<Interface>& superType);
+              const Reference<Type>& superType);
 
     bool addMethod(Method *method);
     bool addAllReservedMethods();
@@ -120,7 +120,7 @@
     bool isJavaCompatible() const override;
 
    private:
-    Reference<Interface> mSuperType;
+    Reference<Type> mSuperType;
 
     std::vector<Method*> mUserMethods;
     std::vector<Method*> mReservedMethods;
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index 3df9e79..61372e2 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -264,7 +264,7 @@
 %type<referenceToType> type enum_storage_type
 %type<referenceToType> array_type_base
 %type<arrayType> array_type
-%type<referenceToInterface> opt_extends
+%type<referenceToType> opt_extends
 %type<type> type_declaration type_declaration_body interface_declaration typedef_declaration
 %type<type> named_struct_or_union_declaration named_enum_declaration
 %type<type> compound_declaration annotated_compound_declaration
@@ -291,7 +291,6 @@
     const char *str;
     android::Type* type;
     android::Reference<android::Type>* referenceToType;
-    android::Reference<android::Interface>* referenceToInterface;
     android::ArrayType *arrayType;
     android::TemplatedType *templatedType;
     android::FQName *fqName;
@@ -553,24 +552,8 @@
     ;
 
 opt_extends
-    : /* empty */
-      {
-          $$ = nullptr;
-      }
-    | EXTENDS fqtype
-      {
-          // TODO(b/31827278)
-          // While deleting lookup calls, move this check
-          if (!(*$2)->isInterface()) {
-              std::cerr << "ERROR: You can only extend interfaces. at " << @2
-                        << "\n";
-
-              YYERROR;
-          }
-
-          $$ = new Reference<Interface>(
-              static_cast<Interface*>($2->get()), $2->location());
-      }
+    : /* empty */ { $$ = nullptr; }
+    | EXTENDS fqtype { $$ = $2; }
     ;
 
 interface_declarations
@@ -648,7 +631,7 @@
 interface_declaration
     : INTERFACE valid_type_name opt_extends
       {
-          Reference<Interface>* superType = $3;
+          Reference<Type>* superType = $3;
           bool isIBase = ast->package().package() == gIBasePackageFqName.string();
 
           if (isIBase) {
@@ -658,7 +641,7 @@
 
                   YYERROR;
               }
-              superType = new Reference<Interface>();
+              superType = new Reference<Type>();
           } else {
               if (!ast->addImport(gIBaseFqName.string().c_str())) {
                   std::cerr << "ERROR: Unable to automatically import '"
@@ -669,10 +652,10 @@
               }
 
               if (superType == nullptr) {
-                  superType = new Reference<Interface>(gIBaseFqName, convertYYLoc(@$));
+                  superType = new Reference<Type>(gIBaseFqName, convertYYLoc(@$));
                   Type* type = ast->lookupType(superType->getLookupFqName(), *scope);
                   CHECK(type != nullptr && type->isInterface());
-                  superType->set(static_cast<Interface*>(type));
+                  superType->set(type);
               }
           }
 
diff --git a/test/error_test/Android.bp b/test/error_test/Android.bp
index 83702d5..cf27294 100644
--- a/test/error_test/Android.bp
+++ b/test/error_test/Android.bp
@@ -33,6 +33,9 @@
          "!($(location hidl-gen) -L check -r test:system/tools/hidl/test/error_test" +
          "    test.enum_unique_field_names_extends@1.0  >/dev/null 2>&1)" +
          "&&" +
+         "!($(location hidl-gen) -L check -r test:system/tools/hidl/test/error_test" +
+         "    test.interface_extends_only_interface@1.0  >/dev/null 2>&1)" +
+         "&&" +
          "echo 'int main(){return 0;}' > $(genDir)/TODO_b_37575883.cpp",
     out: ["TODO_b_37575883.cpp"],
     srcs: [
diff --git a/test/error_test/interface_extends_only_interface/1.0/IFoo.hal b/test/error_test/interface_extends_only_interface/1.0/IFoo.hal
new file mode 100644
index 0000000..6b18b73
--- /dev/null
+++ b/test/error_test/interface_extends_only_interface/1.0/IFoo.hal
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.interface_extends_only_interface@1.0;
+
+interface IFoo extends IStruct /* struct, not interface */ {
+};
diff --git a/test/error_test/interface_extends_only_interface/1.0/types.hal b/test/error_test/interface_extends_only_interface/1.0/types.hal
new file mode 100644
index 0000000..dffd41e
--- /dev/null
+++ b/test/error_test/interface_extends_only_interface/1.0/types.hal
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.interface_extends_only_interface@1.0;
+
+struct IStruct {
+};