Merge "Revert "Add Reference type""
diff --git a/AST.cpp b/AST.cpp
index b9c3b9c..e33fbbf 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -175,7 +175,19 @@
     mImportedASTs.insert(ast);
 }
 
+bool AST::addTypeDef(const char* localName, Type* type, const Location& location,
+                     std::string* errorMsg, Scope* scope) {
+    // The reason we wrap the given type in a TypeDef is simply to suppress
+    // emitting any type definitions later on, since this is just an alias
+    // to a type defined elsewhere.
+    return addScopedTypeInternal(new TypeDef(localName, location, scope, type), errorMsg, scope);
+}
+
 bool AST::addScopedType(NamedType* type, std::string* errorMsg, Scope* scope) {
+    return addScopedTypeInternal(type, errorMsg, scope);
+}
+
+bool AST::addScopedTypeInternal(NamedType* type, std::string* errorMsg, Scope* scope) {
     bool success = scope->addType(type, errorMsg);
     if (!success) {
         return false;
diff --git a/AST.h b/AST.h
index c328434..8a89a6f 100644
--- a/AST.h
+++ b/AST.h
@@ -51,6 +51,10 @@
     bool containsInterfaces() const;
 
     // Returns true iff successful.
+    bool addTypeDef(const char* localName, Type* type, const Location& location,
+                    std::string* errorMsg, Scope* scope);
+
+    // Returns true iff successful.
     bool addScopedType(NamedType* type, std::string* errorMsg, Scope* scope);
 
     const std::string &getFilename() const;
@@ -143,6 +147,8 @@
     // used by the parser.
     size_t mSyntaxErrors = 0;
 
+    bool addScopedTypeInternal(NamedType* type, std::string* errorMsg, Scope* scope);
+
     // Helper functions for lookupType.
     Type* lookupTypeLocally(const FQName& fqName, Scope* scope);
     status_t lookupAutofilledType(const FQName &fqName, Type **returnedType);
diff --git a/Android.bp b/Android.bp
index 354bd37..ef388fc 100644
--- a/Android.bp
+++ b/Android.bp
@@ -80,7 +80,6 @@
         "NamedType.cpp",
         "PointerType.cpp",
         "FmqType.cpp",
-        "Reference.cpp",
         "RefType.cpp",
         "ScalarType.cpp",
         "Scope.cpp",
diff --git a/ArrayType.cpp b/ArrayType.cpp
index ccbccb6..382665b 100644
--- a/ArrayType.cpp
+++ b/ArrayType.cpp
@@ -29,9 +29,8 @@
     prependDimension(size);
 }
 
-ArrayType::ArrayType(const Reference<Type>& elementType, ConstantExpression* size)
+ArrayType::ArrayType(Type *elementType, ConstantExpression *size)
     : mElementType(elementType) {
-    CHECK(!elementType.isEmptyReference());
     prependDimension(size);
 }
 
@@ -55,7 +54,7 @@
     return mElementType->canCheckEquality();
 }
 
-Type* ArrayType::getElementType() const {
+Type *ArrayType::getElementType() const {
     return mElementType;
 }
 
diff --git a/ArrayType.h b/ArrayType.h
index ab0590c..05ba783 100644
--- a/ArrayType.h
+++ b/ArrayType.h
@@ -18,7 +18,6 @@
 
 #define ARRAY_TYPE_H_
 
-#include "Reference.h"
 #include "Type.h"
 
 #include <vector>
@@ -31,12 +30,12 @@
     // Extends existing array by adding another dimension.
     ArrayType(ArrayType *srcArray, ConstantExpression *size);
 
-    ArrayType(const Reference<Type>& elementType, ConstantExpression* size);
+    ArrayType(Type *elementType, ConstantExpression *size);
 
     bool isArray() const override;
     bool canCheckEquality() const override;
 
-    Type* getElementType() const;
+    Type *getElementType() const;
 
     void prependDimension(ConstantExpression *size);
     void appendDimension(ConstantExpression *size);
@@ -132,9 +131,9 @@
 
     void getAlignmentAndSize(size_t *align, size_t *size) const override;
 
-   private:
-    Reference<Type> mElementType;
-    std::vector<ConstantExpression*> mSizes;
+private:
+    Type *mElementType;
+    std::vector<ConstantExpression *> mSizes;
 
     size_t dimension() const;
 
diff --git a/CompoundType.cpp b/CompoundType.cpp
index da30747..b138d7b 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -1115,9 +1115,9 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-CompoundField::CompoundField(const char* name, const Reference<Type>& type)
-    : mName(name), mType(type) {
-    CHECK(!type.isEmptyReference());
+CompoundField::CompoundField(const char *name, Type *type)
+    : mName(name),
+      mType(type) {
 }
 
 std::string CompoundField::name() const {
@@ -1125,7 +1125,7 @@
 }
 
 const Type &CompoundField::type() const {
-    return *(mType.get());
+    return *mType;
 }
 
 }  // namespace android
diff --git a/CompoundType.h b/CompoundType.h
index 2674544..4917dec 100644
--- a/CompoundType.h
+++ b/CompoundType.h
@@ -18,7 +18,6 @@
 
 #define COMPOUND_TYPE_H_
 
-#include "Reference.h"
 #include "Scope.h"
 
 #include <vector>
@@ -148,14 +147,14 @@
 };
 
 struct CompoundField {
-    CompoundField(const char* name, const Reference<Type>& type);
+    CompoundField(const char *name, Type *type);
 
     std::string name() const;
     const Type &type() const;
 
 private:
     std::string mName;
-    Reference<Type> mType;
+    Type *mType;
 
     DISALLOW_COPY_AND_ASSIGN(CompoundField);
 };
diff --git a/EnumType.cpp b/EnumType.cpp
index 9f70287..fb8545f 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -17,7 +17,6 @@
 #include "EnumType.h"
 
 #include "Annotation.h"
-#include "Location.h"
 #include "ScalarType.h"
 
 #include <inttypes.h>
@@ -26,12 +25,11 @@
 
 namespace android {
 
-EnumType::EnumType(const char* localName, const Location& location,
-                   const Reference<Type>& storageType, Scope* parent)
+EnumType::EnumType(const char* localName, const Location& location, Type* storageType,
+                   Scope* parent)
     : Scope(localName, location, parent), mValues(), mStorageType(storageType) {
-    BitFieldType* bitfieldType = new BitFieldType();
-    bitfieldType->setElementType(Reference<Type>(this, Location()));
-    mBitfieldType.set(bitfieldType);
+    mBitfieldType = new BitFieldType();
+    mBitfieldType->setElementType(this);
 }
 
 const Type *EnumType::storageType() const {
@@ -101,7 +99,7 @@
     return "TYPE_ENUM";
 }
 
-BitFieldType* EnumType::getBitfieldType() const {
+BitFieldType *EnumType::getBitfieldType() const {
     return mBitfieldType;
 }
 
@@ -724,7 +722,7 @@
     return "mask" + (mElementType == nullptr ? "" : (" of " + mElementType->typeName()));
 }
 
-bool BitFieldType::isCompatibleElementType(Type* elementType) const {
+bool BitFieldType::isCompatibleElementType(Type *elementType) const {
     return elementType->isEnum();
 }
 
@@ -766,8 +764,8 @@
     out << "scalar_type: \""
         << mElementType->resolveToScalarType()->getVtsScalarType()
         << "\"\n";
-    out << "predefined_type: \"" << static_cast<NamedType*>(mElementType.get())->fullName()
-        << "\"\n";
+    out << "predefined_type: \""
+        << static_cast<NamedType *>(mElementType)->fullName() << "\"\n";
     return OK;
 }
 
@@ -792,9 +790,9 @@
             true /* needsCast */);
 }
 
-EnumType* BitFieldType::getEnumType() const {
+EnumType *BitFieldType::getEnumType() const {
     CHECK(mElementType->isEnum());
-    return static_cast<EnumType*>(mElementType.get());
+    return static_cast<EnumType *>(mElementType);
 }
 
 // a bitfield maps to the underlying scalar type in C++, so operator<< is
diff --git a/EnumType.h b/EnumType.h
index 35db597..d829292 100644
--- a/EnumType.h
+++ b/EnumType.h
@@ -19,7 +19,6 @@
 #define ENUM_TYPE_H_
 
 #include "ConstantExpression.h"
-#include "Reference.h"
 #include "Scope.h"
 
 #include <vector>
@@ -30,8 +29,7 @@
 struct BitFieldType;
 
 struct EnumType : public Scope {
-    EnumType(const char* localName, const Location& location, const Reference<Type>& storageType,
-             Scope* parent);
+    EnumType(const char* localName, const Location& location, Type* storageType, Scope* parent);
 
     const Type *storageType() const;
     const std::vector<EnumValue *> &values() const;
@@ -114,10 +112,8 @@
             const std::string &op) const;
 
     std::vector<EnumValue *> mValues;
-    Reference<Type> mStorageType;
-    // TODO(b/64272670): Dot not store BitFieldType as it is not owned.
-    // It is kept here to avoid const-cast (BitFieldType owns non-const EnumType).
-    Reference<BitFieldType> mBitfieldType;
+    Type *mStorageType;
+    BitFieldType *mBitfieldType;
 
     DISALLOW_COPY_AND_ASSIGN(EnumType);
 };
diff --git a/Interface.cpp b/Interface.cpp
index 805d81c..1adf92d 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -68,10 +68,8 @@
 };
 
 Interface::Interface(const char* localName, const Location& location, Scope* parent,
-                     const Reference<Interface>& superType)
-    : Scope(localName, location, parent),
-      mSuperType(superType),
-      mIsJavaCompatibleInProgress(false) {}
+                     Interface* super)
+    : Scope(localName, location, parent), mSuperType(super), mIsJavaCompatibleInProgress(false) {}
 
 std::string Interface::typeName() const {
     return "interface " + localName();
@@ -463,7 +461,7 @@
 
     serial += userDefinedMethods().size();
 
-    const Interface* ancestor = superType();
+    const Interface *ancestor = mSuperType;
     while (ancestor != nullptr) {
         serial += ancestor->userDefinedMethods().size();
         ancestor = ancestor->superType();
@@ -512,8 +510,8 @@
     return true;
 }
 
-const Interface* Interface::superType() const {
-    return isIBase() ? nullptr : mSuperType;
+const Interface *Interface::superType() const {
+    return mSuperType;
 }
 
 std::vector<const Interface *> Interface::typeChain() const {
@@ -521,13 +519,13 @@
     const Interface *iface = this;
     while (iface != nullptr) {
         v.push_back(iface);
-        iface = iface->superType();
+        iface = iface->mSuperType;
     }
     return v;
 }
 
 std::vector<const Interface *> Interface::superTypeChain() const {
-    return isIBase() ? std::vector<const Interface*>() : superType()->typeChain();
+    return superType()->typeChain(); // should work even if superType is nullptr
 }
 
 bool Interface::isElidableType() const {
@@ -892,7 +890,7 @@
         return true;
     }
 
-    if (superType() != nullptr && !superType()->isJavaCompatible()) {
+    if (mSuperType != nullptr && !mSuperType->isJavaCompatible()) {
         mIsJavaCompatibleInProgress = false;
         return false;
     }
diff --git a/Interface.h b/Interface.h
index 9d6e50d..b37dc60 100644
--- a/Interface.h
+++ b/Interface.h
@@ -18,10 +18,8 @@
 
 #define INTERFACE_H_
 
-#include <vector>
-
-#include "Reference.h"
 #include "Scope.h"
+#include <vector>
 
 namespace android {
 
@@ -29,8 +27,7 @@
 struct InterfaceAndMethod;
 
 struct Interface : public Scope {
-    Interface(const char* localName, const Location& location, Scope* parent,
-              const Reference<Interface>& superType);
+    Interface(const char* localName, const Location& location, Scope* parent, Interface* super);
 
     bool addMethod(Method *method);
     bool addAllReservedMethods();
@@ -38,10 +35,11 @@
     bool isElidableType() const override;
     bool isInterface() const override;
     bool isBinder() const override;
+    bool isRootType() const { return mSuperType == nullptr; }
     bool isIBase() const { return fqName() == gIBaseFqName; }
     std::string typeName() const override;
 
-    const Interface* superType() const;
+    const Interface *superType() const;
 
     Method *lookupMethod(std::string name) const;
     // Super type chain to root type.
@@ -111,24 +109,21 @@
 
     bool isJavaCompatible() const override;
 
-   private:
-    Reference<Interface> mSuperType;
-
-    std::vector<Method*> mUserMethods;
-    std::vector<Method*> mReservedMethods;
-
+private:
+    Interface *mSuperType;
+    std::vector<Method *> mUserMethods;
+    std::vector<Method *> mReservedMethods;
     mutable bool mIsJavaCompatibleInProgress;
-
-    bool fillPingMethod(Method* method) const;
-    bool fillDescriptorChainMethod(Method* method) const;
-    bool fillGetDescriptorMethod(Method* method) const;
-    bool fillHashChainMethod(Method* method) const;
-    bool fillSyspropsChangedMethod(Method* method) const;
-    bool fillLinkToDeathMethod(Method* method) const;
-    bool fillUnlinkToDeathMethod(Method* method) const;
-    bool fillSetHALInstrumentationMethod(Method* method) const;
-    bool fillGetDebugInfoMethod(Method* method) const;
-    bool fillDebugMethod(Method* method) const;
+    bool fillPingMethod(Method *method) const;
+    bool fillDescriptorChainMethod(Method *method) const;
+    bool fillGetDescriptorMethod(Method *method) const;
+    bool fillHashChainMethod(Method *method) const;
+    bool fillSyspropsChangedMethod(Method *method) const;
+    bool fillLinkToDeathMethod(Method *method) const;
+    bool fillUnlinkToDeathMethod(Method *method) const;
+    bool fillSetHALInstrumentationMethod(Method *method) const;
+    bool fillGetDebugInfoMethod(Method *method) const;
+    bool fillDebugMethod(Method *method) const;
 
     DISALLOW_COPY_AND_ASSIGN(Interface);
 };
@@ -140,8 +135,7 @@
           mMethod(method) {}
     Method *method() const { return mMethod; }
     const Interface *interface() const { return mInterface; }
-
-   private:
+private:
     // do not own these objects.
     const Interface *mInterface;
     Method *mMethod;
diff --git a/Location.h b/Location.h
index 994b03e..84dfc0e 100644
--- a/Location.h
+++ b/Location.h
@@ -17,28 +17,27 @@
 #ifndef LOCATION_H_
 #define LOCATION_H_
 
-#include <stdint.h>
 #include <iostream>
+#include <stdint.h>
 #include <string>
 
 // Mimics for yy::location and yy::position
 namespace android {
 
 struct Position {
-    Position() = default;
     Position(std::string f, size_t l, size_t c)
             : mFilename(f), mLine(l), mColumn(c) {}
     inline const std::string &filename() const { return mFilename; }
     inline size_t line() const { return mLine; }
     inline size_t column() const { return mColumn; }
 
-   private:
+private:
     // File name to which this position refers.
-    std::string mFilename;
+    const std::string mFilename;
     // Current line number.
-    size_t mLine;
+    const size_t mLine;
     // Current column number.
-    size_t mColumn;
+    const size_t mColumn;
 };
 
 inline std::ostream& operator<< (std::ostream& ostr, const Position& pos) {
@@ -49,30 +48,20 @@
 }
 
 struct Location {
-    Location() = default;
-    Location(const Position& begin, const Position& end) { setLocation(begin, end); }
+    Location (Position begin, Position end)
+            : mBegin(begin), mEnd(end) {}
+    inline const Position &begin() const { return mBegin; }
+    inline const Position &end() const { return mEnd; }
 
-    void setLocation(const Position& begin, const Position& end) {
-        mIsValid = true;
-        mBegin = begin;
-        mEnd = end;
-    }
-
-    bool isValid() const { return mIsValid; }
-    const Position& begin() const { return mBegin; }
-    const Position& end() const { return mEnd; }
-
-    static Location startOf(const std::string& path) {
+    inline static Location startOf(const std::string &path) {
         return Location(Position(path, 1, 1), Position(path, 1, 1));
     }
 
-   private:
-    bool mIsValid = false;
-
+private:
     // Beginning of the located region.
-    Position mBegin;
+    const Position mBegin;
     // End of the located region.
-    Position mEnd;
+    const Position mEnd;
 };
 
 inline std::ostream& operator<< (std::ostream& ostr, const Location& loc) {
diff --git a/Method.cpp b/Method.cpp
index 5a3e248..6c0ebf5 100644
--- a/Method.cpp
+++ b/Method.cpp
@@ -242,14 +242,17 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-TypedVar::TypedVar(const char* name, const Reference<Type>& type) : mName(name), mType(type) {}
+TypedVar::TypedVar(const char *name, Type *type)
+    : mName(name),
+      mType(type) {
+}
 
 std::string TypedVar::name() const {
     return mName;
 }
 
 const Type &TypedVar::type() const {
-    return *(mType.get());
+    return *mType;
 }
 
 bool TypedVar::isJavaCompatible() const {
diff --git a/Method.h b/Method.h
index b77c66f..6d7664b 100644
--- a/Method.h
+++ b/Method.h
@@ -26,8 +26,6 @@
 #include <string>
 #include <vector>
 
-#include "Reference.h"
-
 namespace android {
 
 struct Annotation;
@@ -116,7 +114,7 @@
 };
 
 struct TypedVar {
-    TypedVar(const char* name, const Reference<Type>& type);
+    TypedVar(const char *name, Type *type);
 
     std::string name() const;
     const Type &type() const;
@@ -125,7 +123,7 @@
 
 private:
     std::string mName;
-    Reference<Type> mType;
+    Type *mType;
 
     DISALLOW_COPY_AND_ASSIGN(TypedVar);
 };
diff --git a/Reference.cpp b/Reference.cpp
deleted file mode 100644
index 4b53da7..0000000
--- a/Reference.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.
- */
-
-/* TODO(b/31827278)
- * There would be no necessity to have cast specializations as all of them
- * will occure only during parsing (before looking up).
- */
-
-#include "Reference.h"
-
-#include "Interface.h"
-#include "Type.h"
-
-namespace android {
-
-template <>
-template <>
-Reference<Interface>::Reference(const Reference<Type>& ref)
-    : mFqName(ref.mFqName), mLocation(ref.mLocation) {
-    if (ref.isResolved()) {
-        CHECK(ref->isInterface());
-        mResolved = static_cast<Interface*>(ref.get());
-    }
-}
-
-}  // namespace android
diff --git a/Reference.h b/Reference.h
deleted file mode 100644
index e83004a..0000000
--- a/Reference.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef REFERENCE_H_
-
-#define REFERENCE_H_
-
-#include <android-base/logging.h>
-#include <hidl-util/FQName.h>
-
-#include "Location.h"
-
-namespace android {
-
-/**
- * Reference placeholder
- */
-template <class T>
-struct Reference {
-    Reference() = default;
-
-    Reference(const FQName& fqName, const Location& location)
-        : mResolved(nullptr), mFqName(fqName), mLocation(location) {}
-
-    Reference(T* type, const Location& location) : mResolved(type), mLocation(location) {
-        CHECK(type != nullptr);
-    }
-
-    Reference(const Reference& ref)
-        : mResolved(ref.mResolved), mFqName(ref.mFqName), mLocation(ref.mLocation) {}
-
-    /* Storing type cast, valid only before resolving */
-    template <class OtherT>
-    Reference(const Reference<OtherT>& ref)
-        : mResolved(nullptr), mFqName(ref.mFqName), mLocation(ref.mLocation) {
-        CHECK(!ref.isResolved());
-    }
-
-    /* Returns true iff referred type is resolved
-       Referred type's field might be not resolved */
-    bool isResolved() const { return mResolved != nullptr; }
-
-    operator T*() const { return get(); }
-
-    T* operator->() const { return get(); }
-
-    T* get() const {
-        CHECK(mResolved != nullptr);
-        return mResolved;
-    }
-
-    void set(T* resolved) {
-        CHECK(!isResolved());
-        CHECK(resolved != nullptr);
-        mResolved = resolved;
-    }
-
-    /* Returns true iff this is reference to null:
-       not resolved and has not name for lookup */
-    bool isEmptyReference() const { return !isResolved() && !hasLookupFqName(); }
-
-    const FQName& getLookupFqName() const {
-        CHECK(hasLookupFqName());
-        return mFqName;
-    }
-
-    bool hasLocation() const { return mLocation.isValid(); }
-
-    const Location& getLocation() const {
-        CHECK(hasLocation());
-        return mLocation;
-    }
-
-   private:
-    /* Referred type */
-    T* mResolved = nullptr;
-    /* Reference name for lookup */
-    FQName mFqName;
-    /* Reference location is mainly used for printing errors */
-    Location mLocation;
-
-    bool hasLookupFqName() const {
-        // Valid only while not resolved to prevent confusion when
-        // ref.hasLookupFqName() is false while ref,get()->fqName is valid.
-        CHECK(!isResolved());
-        return mFqName.isValid();
-    }
-
-    template <class OtherT>
-    friend struct Reference;
-};
-
-}  // namespace android
-
-#endif  // REFERENCE_H_
diff --git a/Type.cpp b/Type.cpp
index 6512fd7..ea8df98 100644
--- a/Type.cpp
+++ b/Type.cpp
@@ -470,18 +470,16 @@
 
 ////////////////////////////////////////
 
-TemplatedType::TemplatedType() {}
+TemplatedType::TemplatedType() : mElementType(nullptr) {
+}
 
-void TemplatedType::setElementType(const Reference<Type>& elementType) {
-    // can only be set once.
-    CHECK(mElementType.isEmptyReference());
-    CHECK(!elementType.isEmptyReference());
-
+void TemplatedType::setElementType(Type *elementType) {
+    CHECK(mElementType == nullptr); // can only be set once.
     CHECK(isCompatibleElementType(elementType));
     mElementType = elementType;
 }
 
-Type* TemplatedType::getElementType() const {
+Type *TemplatedType::getElementType() const {
     return mElementType;
 }
 
@@ -514,6 +512,5 @@
     out << "}\n";
     return OK;
 }
-
 }  // namespace android
 
diff --git a/Type.h b/Type.h
index f4769ba..8e139d4 100644
--- a/Type.h
+++ b/Type.h
@@ -24,8 +24,6 @@
 #include <vector>
 #include <set>
 
-#include "Reference.h"
-
 namespace android {
 
 struct Annotation;
@@ -257,17 +255,16 @@
 
 /* Base type for VectorType and RefType. */
 struct TemplatedType : public Type {
-    void setElementType(const Reference<Type>& elementType);
-    Type* getElementType() const;
+    void setElementType(Type *elementType);
+    Type *getElementType() const;
     bool isTemplatedType() const override;
-    virtual bool isCompatibleElementType(Type* elementType) const = 0;
+    virtual bool isCompatibleElementType(Type *elementType) const = 0;
     status_t emitVtsTypeDeclarations(Formatter &out) const override;
     status_t emitVtsAttributeType(Formatter &out) const override;
 protected:
     TemplatedType();
-    Reference<Type> mElementType;
-
-   private:
+    Type *mElementType;
+private:
     DISALLOW_COPY_AND_ASSIGN(TemplatedType);
 };
 
diff --git a/TypeDef.cpp b/TypeDef.cpp
index f470711..f419efe 100644
--- a/TypeDef.cpp
+++ b/TypeDef.cpp
@@ -21,8 +21,7 @@
 
 namespace android {
 
-TypeDef::TypeDef(const char* localName, const Location& location, Scope* parent,
-                 const Reference<Type>& type)
+TypeDef::TypeDef(const char* localName, const Location& location, Scope* parent, Type* type)
     : NamedType(localName, location, parent), mReferencedType(type) {}
 
 const ScalarType *TypeDef::resolveToScalarType() const {
@@ -30,7 +29,7 @@
     return NULL;
 }
 
-Type* TypeDef::referencedType() const {
+Type *TypeDef::referencedType() const {
     return mReferencedType;
 }
 
diff --git a/TypeDef.h b/TypeDef.h
index e6af502..7914363 100644
--- a/TypeDef.h
+++ b/TypeDef.h
@@ -23,14 +23,13 @@
 namespace android {
 
 struct TypeDef : public NamedType {
-    TypeDef(const char* localName, const Location& location, Scope* parent,
-            const Reference<Type>& type);
+    TypeDef(const char* localName, const Location& location, Scope* parent, Type* type);
 
     const ScalarType *resolveToScalarType() const override;
 
     std::string typeName() const override;
 
-    Type* referencedType() const;
+    Type *referencedType() const;
 
     bool isInterface() const override;
     bool isEnum() const override;
@@ -40,8 +39,8 @@
 
     status_t emitTypeDeclarations(Formatter &out) const override;
 
-   private:
-    Reference<Type> mReferencedType;
+private:
+    Type *mReferencedType;
 
     DISALLOW_COPY_AND_ASSIGN(TypeDef);
 };
diff --git a/VectorType.cpp b/VectorType.cpp
index 50ceef0..4d1dae8 100644
--- a/VectorType.cpp
+++ b/VectorType.cpp
@@ -725,7 +725,7 @@
     }
 
     if (mElementType->isArray()) {
-        return static_cast<ArrayType*>(mElementType.get())->countDimensions() == 1;
+        return static_cast<ArrayType *>(mElementType)->countDimensions() == 1;
     }
 
     if (mElementType->isVector()) {
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index daee8d2..d67638e 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -16,8 +16,8 @@
 
 %{
 
-#include "AST.h"
 #include "Annotation.h"
+#include "AST.h"
 #include "ArrayType.h"
 #include "CompoundType.h"
 #include "ConstantExpression.h"
@@ -25,10 +25,9 @@
 #include "Interface.h"
 #include "Location.h"
 #include "Method.h"
-#include "RefType.h"
 #include "Scope.h"
-#include "TypeDef.h"
 #include "VectorType.h"
+#include "RefType.h"
 
 #include "hidl-gen_y.h"
 
@@ -258,13 +257,13 @@
 %type<str> error_stmt error
 %type<str> package
 %type<fqName> fqname
-%type<referenceToType> fqtype
+%type<type> fqtype
 %type<str> valid_identifier valid_type_name
 
-%type<referenceToType> type enum_storage_type
-%type<referenceToType> array_type_base
+%type<type> type enum_storage_type
+%type<type> array_type_base
 %type<arrayType> array_type
-%type<referenceToInterface> opt_extends
+%type<type> 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
@@ -289,9 +288,7 @@
 
 %union {
     const char *str;
-    android::Type* type;
-    android::Reference<android::Type>* referenceToType;
-    android::Reference<android::Interface>* referenceToInterface;
+    android::Type *type;
     android::ArrayType *arrayType;
     android::TemplatedType *templatedType;
     android::FQName *fqName;
@@ -486,9 +483,7 @@
 fqtype
     : fqname
       {
-          $$ = new Reference<Type>(*$1, convertYYLoc(@1));
-
-          Type* type = ast->lookupType($$->getLookupFqName(), *scope);
+          $$ = ast->lookupType(*($1), *scope);
           if ($$ == NULL) {
               std::cerr << "ERROR: Failed to lookup type '" << $1->string() << "' at "
                         << @1
@@ -496,13 +491,8 @@
 
               YYERROR;
           }
-
-          $$->set(type);
       }
     | TYPE
-      {
-          $$ = new Reference<Type>($1, convertYYLoc(@1));
-      }
     ;
 
 package
@@ -553,28 +543,17 @@
     ;
 
 opt_extends
-    : /* empty */
-      {
-          $$ = nullptr;
-      }
-    | EXTENDS fqtype
-      {
-          if (!(*$2)->isInterface()) {
-              std::cerr << "ERROR: You can only extend interfaces. at " << @2
-                        << "\n";
-
-              YYERROR;
-          }
-          $$ = new Reference<Interface>(*$2);
-      }
+    : /* empty */ { $$ = NULL; }
+    | EXTENDS fqtype { $$ = $2; }
 
 interface_declarations
     : /* empty */
     | interface_declarations type_declaration
       {
           std::string errorMsg;
-          if ($2 != nullptr && $2->isNamedType() &&
-              !isValidInterfaceField(static_cast<NamedType*>($2)->localName().c_str(),
+          if ($2 != nullptr &&
+              $2->isNamedType() &&
+              !isValidInterfaceField(static_cast<NamedType *>($2)->localName().c_str(),
                     &errorMsg)) {
               std::cerr << "ERROR: " << errorMsg << " at "
                         << @2 << "\n";
@@ -598,7 +577,7 @@
                 YYERROR;
             }
 
-            Interface *iface = static_cast<Interface*>(*scope);
+            Interface *iface = static_cast<Interface *>(*scope);
             if (!iface->addMethod($2)) {
                 std::cerr << "ERROR: Unable to add method '" << $2->name()
                           << "' at " << @2 << "\n";
@@ -619,7 +598,7 @@
 type_declaration
     : opt_annotations type_declaration_body
       {
-          if (!$2->isTypeDef()) {
+          if ($2 != nullptr) {
               $2->setAnnotations($1);
           } else if (!$1->empty()) {
               // Since typedefs are always resolved to their target it makes
@@ -644,18 +623,9 @@
 interface_declaration
     : INTERFACE valid_type_name opt_extends
       {
-          Reference<Interface>* superType = $3;
-          bool isIBase = ast->package().package() == gIBasePackageFqName.string();
+          Type *parent = $3;
 
-          if (isIBase) {
-              if (superType != nullptr) {
-                  std::cerr << "ERROR: IBase must not extend any interface. at " << @3
-                        << "\n";
-
-                  YYERROR;
-              }
-              superType = new Reference<Interface>();
-          } else {
+          if (ast->package().package() != gIBasePackageFqName.string()) {
               if (!ast->addImport(gIBaseFqName.string().c_str())) {
                   std::cerr << "ERROR: Unable to automatically import '"
                             << gIBaseFqName.string()
@@ -663,15 +633,18 @@
                             << "\n";
                   YYERROR;
               }
-
-              if (superType == nullptr) {
-                  superType = new Reference<Interface>(gIBaseFqName, convertYYLoc(@$));
-                  Type* type = ast->lookupType(superType->getLookupFqName(), *scope);
-                  CHECK(type != nullptr && type->isInterface());
-                  superType->set(static_cast<Interface*>(type));
+              if (parent == nullptr) {
+                parent = ast->lookupType(gIBaseFqName, *scope);
               }
           }
 
+          if (parent != NULL && !parent->isInterface()) {
+              std::cerr << "ERROR: You can only extend interfaces. at " << @3
+                        << "\n";
+
+              YYERROR;
+          }
+
           if ($2[0] != 'I') {
               std::cerr << "ERROR: All interface names must start with an 'I' "
                         << "prefix. at " << @2 << "\n";
@@ -687,7 +660,8 @@
           }
 
           Interface* iface = new Interface(
-              $2, convertYYLoc(@2), *scope, *superType);
+              $2, convertYYLoc(@2), *scope,
+              static_cast<Interface *>(parent));
 
           // Register interface immediately so it can be referenced inside
           // definition.
@@ -723,18 +697,13 @@
 typedef_declaration
     : TYPEDEF type valid_type_name
       {
-          // The reason we wrap the given type in a TypeDef is simply to suppress
-          // emitting any type definitions later on, since this is just an alias
-          // to a type defined elsewhere.
-          TypeDef* typeDef = new TypeDef($3, convertYYLoc(@2), *scope, *$2);
-
           std::string errorMsg;
-          if (!ast->addScopedType(typeDef, &errorMsg, *scope)) {
+          if (!ast->addTypeDef($3, $2, convertYYLoc(@3), &errorMsg, *scope)) {
               std::cerr << "ERROR: " << errorMsg << " at " << @3 << "\n";
               YYERROR;
           }
 
-          $$ = typeDef;
+          $$ = nullptr;
       }
     ;
 
@@ -765,13 +734,11 @@
                       *(static_cast<EnumValue *>(iden)->constExpr()), $1->string());
           } else {
               std::string errorMsg;
-              EnumValue* v = ast->lookupEnumValue(*$1, &errorMsg, *scope);
+              EnumValue *v = ast->lookupEnumValue(*($1), &errorMsg, *scope);
               if(v == nullptr) {
                   std::cerr << "ERROR: " << errorMsg << " at " << @1 << ".\n";
                   YYERROR;
               }
-
-              // TODO: Support Reference
               $$ = new ConstantExpression(*(v->constExpr()), $1->string());
           }
       }
@@ -851,7 +818,7 @@
       }
     ;
 
-typed_var : type valid_identifier { $$ = new TypedVar($2, *$1); }
+typed_var : type valid_identifier { $$ = new TypedVar($2, $1); }
     ;
 
 
@@ -902,8 +869,7 @@
       {
           $$ = $1;
 
-          // Compound declaration or error
-          if ($2 != nullptr) {
+          if ($2 != NULL) {
               $$->push_back($2);
           }
       }
@@ -921,28 +887,27 @@
                       << @2 << "\n";
             YYERROR;
         }
-        $$ = new CompoundField($2, *$1);
+        $$ = new CompoundField($2, $1);
       }
     | annotated_compound_declaration ';'
       {
         std::string errorMsg;
         if ((*scope)->isCompoundType() &&
             static_cast<CompoundType *>(*scope)->style() == CompoundType::STYLE_STRUCT &&
-            $1 != nullptr && $1->isNamedType() &&
-            !isValidStructField(static_cast<NamedType*>($1)->localName().c_str(), &errorMsg)) {
+            $1 != nullptr &&
+            $1->isNamedType() &&
+            !isValidStructField(static_cast<NamedType *>($1)->localName().c_str(), &errorMsg)) {
             std::cerr << "ERROR: " << errorMsg << " at "
                       << @2 << "\n";
             YYERROR;
         }
-        // Returns fields only
-        $$ = nullptr;
+        $$ = NULL;
       }
     ;
 
 annotated_compound_declaration
     : opt_annotations compound_declaration
       {
-          CHECK($2 != nullptr);
           $2->setAnnotations($1);
           $$ = $2;
       }
@@ -958,9 +923,9 @@
       {
           $$ = $2;
 
-          if ($$ != NULL && !(*$$)->isValidEnumStorageType()) {
+          if ($$ != NULL && !$$->isValidEnumStorageType()) {
               std::cerr << "ERROR: Invalid enum storage type ("
-                        << (*$2)->typeName()
+                        << $2->typeName()
                         << ") specified. at "
                         << @2 << "\n";
 
@@ -977,7 +942,7 @@
 named_enum_declaration
     : ENUM valid_type_name enum_storage_type
       {
-          enterScope(ast, scope, new EnumType($2, convertYYLoc(@2), *$3, *scope));
+          enterScope(ast, scope, new EnumType($2, convertYYLoc(@2), $3, *scope));
       }
       enum_declaration_body
       {
@@ -1038,50 +1003,48 @@
     : fqtype { $$ = $1; }
     | TEMPLATED '<' type '>'
       {
-          if (!$1->isCompatibleElementType($3->get())) {
-              std::cerr << "ERROR: " << $1->typeName() << " of " << (*$3)->typeName()
-                        << " is not supported. at " << @3 << "\n";
-
-              YYERROR;
-          }
-          $1->setElementType(*$3);
-          $$ = new Reference<Type>($1, convertYYLoc(@1));
-      }
-    | TEMPLATED '<' TEMPLATED '<' type RSHIFT
-      {
-          if (!$3->isCompatibleElementType($5->get())) {
-              std::cerr << "ERROR: " << $3->typeName() << " of " << (*$5)->typeName()
-                        << " is not supported. at " << @5 << "\n";
-
-              YYERROR;
-          }
-          $3->setElementType(*$5);
           if (!$1->isCompatibleElementType($3)) {
               std::cerr << "ERROR: " << $1->typeName() << " of " << $3->typeName()
                         << " is not supported. at " << @3 << "\n";
 
               YYERROR;
           }
-          $1->setElementType(Reference<Type>($3, convertYYLoc(@3)));
-          $$ = new Reference<Type>($1, convertYYLoc(@1));
+          $1->setElementType($3);
+          $$ = $1;
+      }
+    | TEMPLATED '<' TEMPLATED '<' type RSHIFT
+      {
+          if (!$3->isCompatibleElementType($5)) {
+              std::cerr << "ERROR: " << $3->typeName() << " of " << $5->typeName()
+                        << " is not supported. at " << @3 << "\n";
+
+              YYERROR;
+          }
+          $3->setElementType($5);
+          if (!$1->isCompatibleElementType($3)) {
+              std::cerr << "ERROR: " << $1->typeName() << " of " << $3->typeName()
+                        << " is not supported. at " << @3 << "\n";
+
+              YYERROR;
+          }
+          $1->setElementType($3);
+          $$ = $1;
       }
     ;
 
 array_type
     : array_type_base '[' const_expr ']'
       {
-          Reference<Type> type = *$1;
-
-          if (type->isBinder()) {
+          if ($1->isBinder()) {
               std::cerr << "ERROR: Arrays of interface types are not supported."
                         << " at " << @1 << "\n";
 
               YYERROR;
           }
-          if (type.isResolved() && type->isArray()) {
-              $$ = new ArrayType(static_cast<ArrayType*>(type.get()), $3);
+          if ($1->isArray()) {
+              $$ = new ArrayType(static_cast<ArrayType *>($1), $3);
           } else {
-              $$ = new ArrayType(type, $3);
+              $$ = new ArrayType($1, $3);
           }
       }
     | array_type '[' const_expr ']'
@@ -1093,25 +1056,20 @@
 
 type
     : array_type_base { $$ = $1; }
-    | array_type { $$ = new Reference<Type>($1, convertYYLoc(@1)); }
-    | annotated_compound_declaration
-      {
-          $$ = new Reference<Type>($1, convertYYLoc(@1));
-      }
+    | array_type { $$ = $1; }
+    | annotated_compound_declaration { $$ = $1; }
     | INTERFACE
       {
           // "interface" is a synonym of android.hidl.base@1.0::IBase
-          $$ = new Reference<Type>(gIBaseFqName, convertYYLoc(@1));
-          Type* type = ast->lookupType($$->getLookupFqName(), *scope);
-          if (type == nullptr) {
+          $$ = ast->lookupType(gIBaseFqName, *scope);
+          if ($$ == nullptr) {
               std::cerr << "ERROR: Cannot find "
                         << gIBaseFqName.string()
                         << " at " << @1 << "\n";
 
               YYERROR;
-          }
-          $$->set(type);
       }
+    }
     ;
 
 %%