Make Type::getReferences return pointer

This change makes it able to add lookups as one more tree pass,
as it requires to change Type inside of references.

This change require getReferences to become non-const, so from now
we maintain const and non-const versions of recursive pass and getting
dependencies.

Bug: 31827278
Test: mma
Change-Id: I201533db5ca0bd30fbad34ef71ed2bd210c607e4
diff --git a/Annotation.cpp b/Annotation.cpp
index cade080..e5a66b0 100644
--- a/Annotation.cpp
+++ b/Annotation.cpp
@@ -19,6 +19,7 @@
 #include <android-base/logging.h>
 #include <hidl-util/Formatter.h>
 #include <hidl-util/StringHelper.h>
+#include <algorithm>
 #include <vector>
 
 namespace android {
@@ -29,7 +30,15 @@
     return mName;
 }
 
-std::vector<ConstantExpression*> AnnotationParam::getConstantExpressions() const {
+std::vector<ConstantExpression*> AnnotationParam::getConstantExpressions() {
+    const auto& constRet = static_cast<const AnnotationParam*>(this)->getConstantExpressions();
+    std::vector<ConstantExpression*> ret(constRet.size());
+    std::transform(constRet.begin(), constRet.end(), ret.begin(),
+                   [](const auto* ce) { return const_cast<ConstantExpression*>(ce); });
+    return ret;
+}
+
+std::vector<const ConstantExpression*> AnnotationParam::getConstantExpressions() const {
     return {};
 }
 
@@ -95,8 +104,11 @@
     return convertToString(mValues->at(0));
 }
 
-std::vector<ConstantExpression*> ConstantExpressionAnnotationParam::getConstantExpressions() const {
-    return *mValues;
+std::vector<const ConstantExpression*> ConstantExpressionAnnotationParam::getConstantExpressions()
+    const {
+    std::vector<const ConstantExpression*> ret;
+    ret.insert(ret.end(), mValues->begin(), mValues->end());
+    return ret;
 }
 
 Annotation::Annotation(const char* name, AnnotationParamVector* params)
@@ -120,8 +132,16 @@
     return nullptr;
 }
 
-std::vector<ConstantExpression*> Annotation::getConstantExpressions() const {
-    std::vector<ConstantExpression*> ret;
+std::vector<ConstantExpression*> Annotation::getConstantExpressions() {
+    const auto& constRet = static_cast<const Annotation*>(this)->getConstantExpressions();
+    std::vector<ConstantExpression*> ret(constRet.size());
+    std::transform(constRet.begin(), constRet.end(), ret.begin(),
+                   [](const auto* ce) { return const_cast<ConstantExpression*>(ce); });
+    return ret;
+}
+
+std::vector<const ConstantExpression*> Annotation::getConstantExpressions() const {
+    std::vector<const ConstantExpression*> ret;
     for (const auto* param : *mParams) {
         const auto& retParam = param->getConstantExpressions();
         ret.insert(ret.end(), retParam.begin(), retParam.end());
diff --git a/Annotation.h b/Annotation.h
index 0688b05..dfeb59e 100644
--- a/Annotation.h
+++ b/Annotation.h
@@ -43,7 +43,8 @@
     /* Returns value interpretted as a boolean */
     bool getSingleBool() const;
 
-    virtual std::vector<ConstantExpression*> getConstantExpressions() const;
+    std::vector<ConstantExpression*> getConstantExpressions();
+    virtual std::vector<const ConstantExpression*> getConstantExpressions() const;
 
    protected:
     const std::string mName;
@@ -68,7 +69,7 @@
     std::vector<std::string> getValues() const override;
     std::string getSingleValue() const override;
 
-    std::vector<ConstantExpression*> getConstantExpressions() const override;
+    std::vector<const ConstantExpression*> getConstantExpressions() const override;
 
    private:
     std::vector<ConstantExpression*>* const mValues;
@@ -83,7 +84,8 @@
     const AnnotationParamVector &params() const;
     const AnnotationParam *getParam(const std::string &name) const;
 
-    std::vector<ConstantExpression*> getConstantExpressions() const;
+    std::vector<ConstantExpression*> getConstantExpressions();
+    std::vector<const ConstantExpression*> getConstantExpressions() const;
 
     void dump(Formatter &out) const;
 
diff --git a/ArrayType.cpp b/ArrayType.cpp
index 2ef07b0..977a0aa 100644
--- a/ArrayType.cpp
+++ b/ArrayType.cpp
@@ -67,12 +67,14 @@
     return std::to_string(dimension()) + "d array of " + mElementType->typeName();
 }
 
-std::vector<Reference<Type>> ArrayType::getReferences() const {
-    return {mElementType};
+std::vector<const Reference<Type>*> ArrayType::getReferences() const {
+    return {&mElementType};
 }
 
-std::vector<ConstantExpression*> ArrayType::getConstantExpressions() const {
-    return mSizes;
+std::vector<const ConstantExpression*> ArrayType::getConstantExpressions() const {
+    std::vector<const ConstantExpression*> ret;
+    ret.insert(ret.end(), mSizes.begin(), mSizes.end());
+    return ret;
 }
 
 status_t ArrayType::validate() const {
diff --git a/ArrayType.h b/ArrayType.h
index 97b83a0..45f46e0 100644
--- a/ArrayType.h
+++ b/ArrayType.h
@@ -44,9 +44,9 @@
 
     std::string typeName() const override;
 
-    std::vector<Reference<Type>> getReferences() const override;
+    std::vector<const Reference<Type>*> getReferences() const override;
 
-    std::vector<ConstantExpression*> getConstantExpressions() const override;
+    std::vector<const ConstantExpression*> getConstantExpressions() const override;
 
     status_t validate() const override;
 
diff --git a/CompoundType.cpp b/CompoundType.cpp
index 2123602..154b837 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -37,11 +37,9 @@
     mFields = fields;
 }
 
-std::vector<Reference<Type>> CompoundType::getReferences() const {
-    std::vector<Reference<Type>> ret;
-    for (const auto* field : *mFields) {
-        ret.push_back(*field);
-    }
+std::vector<const Reference<Type>*> CompoundType::getReferences() const {
+    std::vector<const Reference<Type>*> ret;
+    ret.insert(ret.begin(), mFields->begin(), mFields->end());
     return ret;
 }
 
diff --git a/CompoundType.h b/CompoundType.h
index c375984..1c0159b 100644
--- a/CompoundType.h
+++ b/CompoundType.h
@@ -43,7 +43,7 @@
 
     std::string typeName() const override;
 
-    std::vector<Reference<Type>> getReferences() const override;
+    std::vector<const Reference<Type>*> getReferences() const override;
 
     status_t validate() const override;
     status_t validateUniqueNames() const;
diff --git a/ConstantExpression.cpp b/ConstantExpression.cpp
index b6a6824..4de9f0d 100644
--- a/ConstantExpression.cpp
+++ b/ConstantExpression.cpp
@@ -16,11 +16,12 @@
 
 #include "ConstantExpression.h"
 
-#include <stdio.h>
-#include <string>
-#include <android-base/parseint.h>
 #include <android-base/logging.h>
+#include <android-base/parseint.h>
+#include <stdio.h>
+#include <algorithm>
 #include <sstream>
+#include <string>
 
 #include "EnumType.h"
 #include "Scope.h"  // LocalIdentifier
@@ -438,6 +439,14 @@
     return this->cast<size_t>();
 }
 
+std::vector<ConstantExpression*> ConstantExpression::getConstantExpressions() {
+    const auto& constRet = static_cast<const ConstantExpression*>(this)->getConstantExpressions();
+    std::vector<ConstantExpression*> ret(constRet.size());
+    std::transform(constRet.begin(), constRet.end(), ret.begin(),
+                   [](const auto* ce) { return const_cast<ConstantExpression*>(ce); });
+    return ret;
+}
+
 status_t ConstantExpression::recursivePass(const std::function<status_t(ConstantExpression*)>& func,
                                            std::unordered_set<const ConstantExpression*>* visited) {
     if (mIsPostParseCompleted) return OK;
@@ -457,19 +466,40 @@
     return OK;
 }
 
+status_t ConstantExpression::recursivePass(
+    const std::function<status_t(const ConstantExpression*)>& func,
+    std::unordered_set<const ConstantExpression*>* visited) const {
+
+    if (mIsPostParseCompleted) return OK;
+
+    if (visited->find(this) != visited->end()) return OK;
+    visited->insert(this);
+
+    for (const auto* nextCE : getConstantExpressions()) {
+        status_t err = nextCE->recursivePass(func, visited);
+        if (err != OK) return err;
+    }
+
+    // Unlike types, constant expressions need to be proceeded after dependencies
+    status_t err = func(this);
+    if (err != OK) return err;
+
+    return OK;
+}
+
 void ConstantExpression::setPostParseCompleted() {
     CHECK(!mIsPostParseCompleted);
     mIsPostParseCompleted = true;
 }
 
-std::vector<ConstantExpression*> LiteralConstantExpression::getConstantExpressions() const {
+std::vector<const ConstantExpression*> LiteralConstantExpression::getConstantExpressions() const {
     return {};
 }
 
 UnaryConstantExpression::UnaryConstantExpression(const std::string& op, ConstantExpression* value)
     : mUnary(value), mOp(op) {}
 
-std::vector<ConstantExpression*> UnaryConstantExpression::getConstantExpressions() const {
+std::vector<const ConstantExpression*> UnaryConstantExpression::getConstantExpressions() const {
     return {mUnary};
 }
 
@@ -477,7 +507,7 @@
                                                    ConstantExpression* rval)
     : mLval(lval), mRval(rval), mOp(op) {}
 
-std::vector<ConstantExpression*> BinaryConstantExpression::getConstantExpressions() const {
+std::vector<const ConstantExpression*> BinaryConstantExpression::getConstantExpressions() const {
     return {mLval, mRval};
 }
 
@@ -486,7 +516,7 @@
                                                      ConstantExpression* falseVal)
     : mCond(cond), mTrueVal(trueVal), mFalseVal(falseVal) {}
 
-std::vector<ConstantExpression*> TernaryConstantExpression::getConstantExpressions() const {
+std::vector<const ConstantExpression*> TernaryConstantExpression::getConstantExpressions() const {
     return {mCond, mTrueVal, mFalseVal};
 }
 
@@ -497,7 +527,7 @@
     mTrivialDescription = mExpr.empty();
 }
 
-std::vector<ConstantExpression*> ReferenceConstantExpression::getConstantExpressions() const {
+std::vector<const ConstantExpression*> ReferenceConstantExpression::getConstantExpressions() const {
     CHECK(mReference->constExpr() != nullptr);
     return {mReference->constExpr()};
 }
diff --git a/ConstantExpression.h b/ConstantExpression.h
index ab17a4a..28fe42c 100644
--- a/ConstantExpression.h
+++ b/ConstantExpression.h
@@ -53,12 +53,15 @@
     // Used to provide lookup and lazy evaluation
     status_t recursivePass(const std::function<status_t(ConstantExpression*)>& func,
                            std::unordered_set<const ConstantExpression*>* visited);
+    status_t recursivePass(const std::function<status_t(const ConstantExpression*)>& func,
+                           std::unordered_set<const ConstantExpression*>* visited) const;
 
     // Evaluates current constant expression
     // Doesn't call recursive evaluation, so must be called after dependencies
     virtual void evaluate() = 0;
 
-    virtual std::vector<ConstantExpression*> getConstantExpressions() const = 0;
+    std::vector<ConstantExpression*> getConstantExpressions();
+    virtual std::vector<const ConstantExpression*> getConstantExpressions() const = 0;
 
     /* Returns true iff the value has already been evaluated. */
     bool isEvaluated() const;
@@ -127,13 +130,13 @@
     LiteralConstantExpression(ScalarType::Kind kind, uint64_t value);
     LiteralConstantExpression(const std::string& value);
     void evaluate() override;
-    std::vector<ConstantExpression*> getConstantExpressions() const override;
+    std::vector<const ConstantExpression*> getConstantExpressions() const override;
 };
 
 struct UnaryConstantExpression : public ConstantExpression {
     UnaryConstantExpression(const std::string& mOp, ConstantExpression* value);
     void evaluate() override;
-    std::vector<ConstantExpression*> getConstantExpressions() const override;
+    std::vector<const ConstantExpression*> getConstantExpressions() const override;
 
    private:
     ConstantExpression* const mUnary;
@@ -144,7 +147,7 @@
     BinaryConstantExpression(ConstantExpression* lval, const std::string& op,
                              ConstantExpression* rval);
     void evaluate() override;
-    std::vector<ConstantExpression*> getConstantExpressions() const override;
+    std::vector<const ConstantExpression*> getConstantExpressions() const override;
 
    private:
     ConstantExpression* const mLval;
@@ -156,7 +159,7 @@
     TernaryConstantExpression(ConstantExpression* cond, ConstantExpression* trueVal,
                               ConstantExpression* falseVal);
     void evaluate() override;
-    std::vector<ConstantExpression*> getConstantExpressions() const override;
+    std::vector<const ConstantExpression*> getConstantExpressions() const override;
 
    private:
     ConstantExpression* const mCond;
@@ -167,7 +170,7 @@
 struct ReferenceConstantExpression : public ConstantExpression {
     ReferenceConstantExpression(const Reference<LocalIdentifier>& value, const std::string& expr);
     void evaluate() override;
-    std::vector<ConstantExpression*> getConstantExpressions() const override;
+    std::vector<const ConstantExpression*> getConstantExpressions() const override;
 
    private:
     Reference<LocalIdentifier> mReference;
diff --git a/EnumType.cpp b/EnumType.cpp
index bc5f3f3..e4fc37c 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -68,12 +68,12 @@
     return Scope::resolveInheritance();
 }
 
-std::vector<Reference<Type>> EnumType::getReferences() const {
-    return {mStorageType};
+std::vector<const Reference<Type>*> EnumType::getReferences() const {
+    return {&mStorageType};
 }
 
-std::vector<ConstantExpression*> EnumType::getConstantExpressions() const {
-    std::vector<ConstantExpression*> ret;
+std::vector<const ConstantExpression*> EnumType::getConstantExpressions() const {
+    std::vector<const ConstantExpression*> ret;
     for (const auto* value : mValues) {
         ret.push_back(value->constExpr());
     }
diff --git a/EnumType.h b/EnumType.h
index 05a85d5..cc1e6c1 100644
--- a/EnumType.h
+++ b/EnumType.h
@@ -60,8 +60,8 @@
     // Return the type that corresponds to bitfield<T>.
     BitFieldType *getBitfieldType() const;
 
-    std::vector<Reference<Type>> getReferences() const override;
-    std::vector<ConstantExpression*> getConstantExpressions() const override;
+    std::vector<const Reference<Type>*> getReferences() const override;
+    std::vector<const ConstantExpression*> getConstantExpressions() const override;
 
     status_t resolveInheritance() override;
     status_t validate() const override;
diff --git a/Interface.cpp b/Interface.cpp
index 8eb5907..7f33928 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -460,11 +460,11 @@
     return true;
 }
 
-std::vector<Reference<Type>> Interface::getReferences() const {
-    std::vector<Reference<Type>> ret;
+std::vector<const Reference<Type>*> Interface::getReferences() const {
+    std::vector<const Reference<Type>*> ret;
 
     if (superType() != nullptr) {
-        ret.push_back(mSuperType);
+        ret.push_back(&mSuperType);
     }
 
     for (const auto* method : methods()) {
@@ -475,8 +475,8 @@
     return ret;
 }
 
-std::vector<ConstantExpression*> Interface::getConstantExpressions() const {
-    std::vector<ConstantExpression*> ret;
+std::vector<const ConstantExpression*> Interface::getConstantExpressions() const {
+    std::vector<const ConstantExpression*> ret;
     for (const auto* method : methods()) {
         const auto& retMethod = method->getConstantExpressions();
         ret.insert(ret.end(), retMethod.begin(), retMethod.end());
@@ -484,7 +484,7 @@
     return ret;
 }
 
-std::vector<Reference<Type>> Interface::getStrongReferences() const {
+std::vector<const Reference<Type>*> Interface::getStrongReferences() const {
     // Interface is a special case as a reference:
     // its definiton must be completed for extension but
     // not necessary for other references.
@@ -492,9 +492,9 @@
     // method declaration appears only in interface, we may assume
     // that all references in method definitions are acyclic.
 
-    std::vector<Reference<Type>> ret;
+    std::vector<const Reference<Type>*> ret;
     if (superType() != nullptr) {
-        ret.push_back(mSuperType);
+        ret.push_back(&mSuperType);
     }
     return ret;
 }
diff --git a/Interface.h b/Interface.h
index ebb75cc..02b0f4d 100644
--- a/Interface.h
+++ b/Interface.h
@@ -86,10 +86,10 @@
     std::string getJavaType(bool forInitializer) const override;
     std::string getVtsType() const override;
 
-    std::vector<Reference<Type>> getReferences() const override;
-    std::vector<Reference<Type>> getStrongReferences() const override;
+    std::vector<const Reference<Type>*> getReferences() const override;
+    std::vector<const Reference<Type>*> getStrongReferences() const override;
 
-    std::vector<ConstantExpression*> getConstantExpressions() const override;
+    std::vector<const ConstantExpression*> getConstantExpressions() const override;
 
     status_t resolveInheritance() override;
     status_t validate() const override;
diff --git a/Method.cpp b/Method.cpp
index 3c353f8..2ea02c1 100644
--- a/Method.cpp
+++ b/Method.cpp
@@ -69,19 +69,31 @@
     return *mAnnotations;
 }
 
-std::vector<Reference<Type>> Method::getReferences() const {
-    std::vector<Reference<Type>> ret;
-    for (const auto* arg : *mArgs) {
-        ret.push_back(*arg);
-    }
-    for (const auto* result : *mResults) {
-        ret.push_back(*result);
-    }
+std::vector<Reference<Type>*> Method::getReferences() {
+    const auto& constRet = static_cast<const Method*>(this)->getReferences();
+    std::vector<Reference<Type>*> ret(constRet.size());
+    std::transform(constRet.begin(), constRet.end(), ret.begin(),
+                   [](const auto* ref) { return const_cast<Reference<Type>*>(ref); });
     return ret;
 }
 
-std::vector<ConstantExpression*> Method::getConstantExpressions() const {
-    std::vector<ConstantExpression*> ret;
+std::vector<const Reference<Type>*> Method::getReferences() const {
+    std::vector<const Reference<Type>*> ret;
+    ret.insert(ret.end(), mArgs->begin(), mArgs->end());
+    ret.insert(ret.end(), mResults->begin(), mResults->end());
+    return ret;
+}
+
+std::vector<ConstantExpression*> Method::getConstantExpressions() {
+    const auto& constRet = static_cast<const Method*>(this)->getConstantExpressions();
+    std::vector<ConstantExpression*> ret(constRet.size());
+    std::transform(constRet.begin(), constRet.end(), ret.begin(),
+                   [](const auto* ce) { return const_cast<ConstantExpression*>(ce); });
+    return ret;
+}
+
+std::vector<const ConstantExpression*> Method::getConstantExpressions() const {
+    std::vector<const ConstantExpression*> ret;
     for (const auto* annotation : *mAnnotations) {
         const auto& retAnnotation = annotation->getConstantExpressions();
         ret.insert(ret.end(), retAnnotation.begin(), retAnnotation.end());
diff --git a/Method.h b/Method.h
index 8a4db1a..9ba14a8 100644
--- a/Method.h
+++ b/Method.h
@@ -66,9 +66,11 @@
     bool isHiddenFromJava() const;
     const std::vector<Annotation *> &annotations() const;
 
-    std::vector<Reference<Type>> getReferences() const;
+    std::vector<Reference<Type>*> getReferences();
+    std::vector<const Reference<Type>*> getReferences() const;
 
-    std::vector<ConstantExpression*> getConstantExpressions() const;
+    std::vector<ConstantExpression*> getConstantExpressions();
+    std::vector<const ConstantExpression*> getConstantExpressions() const;
 
     // Make a copy with the same name, args, results, oneway, annotations.
     // Implementations, serial are not copied.
diff --git a/RefType.cpp b/RefType.cpp
index aa35455..0a5b3fa 100644
--- a/RefType.cpp
+++ b/RefType.cpp
@@ -31,7 +31,7 @@
     return "ref" + (mElementType == nullptr ? "" : (" of " + mElementType->typeName()));
 }
 
-std::vector<Reference<Type>> RefType::getStrongReferences() const {
+std::vector<const Reference<Type>*> RefType::getStrongReferences() const {
     return {};
 }
 
diff --git a/RefType.h b/RefType.h
index bf5e7e6..6445207 100644
--- a/RefType.h
+++ b/RefType.h
@@ -31,7 +31,7 @@
     std::string typeName() const override;
     bool isCompatibleElementType(Type *elementType) const override;
 
-    std::vector<Reference<Type>> getStrongReferences() const override;
+    std::vector<const Reference<Type>*> getStrongReferences() const override;
 
     std::string getCppType(StorageMode mode,
                            bool specifyNamespaces) const override;
diff --git a/Scope.cpp b/Scope.cpp
index fb9d339..cd245f8 100644
--- a/Scope.cpp
+++ b/Scope.cpp
@@ -115,16 +115,14 @@
     mAnnotations = *annotations;
 }
 
-std::vector<Type*> Scope::getDefinedTypes() const {
-    std::vector<Type*> ret;
-    for (auto* type : mTypes) {
-        ret.push_back(type);
-    }
+std::vector<const Type*> Scope::getDefinedTypes() const {
+    std::vector<const Type*> ret;
+    ret.insert(ret.end(), mTypes.begin(), mTypes.end());
     return ret;
 }
 
-std::vector<ConstantExpression*> Scope::getConstantExpressions() const {
-    std::vector<ConstantExpression*> ret;
+std::vector<const ConstantExpression*> Scope::getConstantExpressions() const {
+    std::vector<const ConstantExpression*> ret;
     for (const auto* annotation : mAnnotations) {
         const auto& retAnnotation = annotation->getConstantExpressions();
         ret.insert(ret.end(), retAnnotation.begin(), retAnnotation.end());
diff --git a/Scope.h b/Scope.h
index 15bf01b..e200fdc 100644
--- a/Scope.h
+++ b/Scope.h
@@ -54,9 +54,9 @@
 
     void setAnnotations(std::vector<Annotation*>* annotations);
 
-    std::vector<Type*> getDefinedTypes() const override;
+    std::vector<const Type*> getDefinedTypes() const override;
 
-    std::vector<ConstantExpression*> getConstantExpressions() const override;
+    std::vector<const ConstantExpression*> getConstantExpressions() const override;
 
     status_t emitTypeDeclarations(Formatter &out) const override;
     status_t emitGlobalTypeDeclarations(Formatter &out) const override;
diff --git a/Type.cpp b/Type.cpp
index 53edf8b..b7436eb 100644
--- a/Type.cpp
+++ b/Type.cpp
@@ -20,8 +20,9 @@
 #include "NamedType.h"
 #include "ScalarType.h"
 
-#include <hidl-util/Formatter.h>
 #include <android-base/logging.h>
+#include <hidl-util/Formatter.h>
+#include <algorithm>
 
 namespace android {
 
@@ -93,19 +94,51 @@
     return false;
 }
 
-std::vector<Type*> Type::getDefinedTypes() const {
+std::vector<Type*> Type::getDefinedTypes() {
+    const auto& constRet = static_cast<const Type*>(this)->getDefinedTypes();
+    std::vector<Type*> ret(constRet.size());
+    std::transform(constRet.begin(), constRet.end(), ret.begin(),
+                   [](const auto* type) { return const_cast<Type*>(type); });
+    return ret;
+}
+
+std::vector<const Type*> Type::getDefinedTypes() const {
     return {};
 }
 
-std::vector<Reference<Type>> Type::getReferences() const {
+std::vector<Reference<Type>*> Type::getReferences() {
+    const auto& constRet = static_cast<const Type*>(this)->getReferences();
+    std::vector<Reference<Type>*> ret(constRet.size());
+    std::transform(constRet.begin(), constRet.end(), ret.begin(),
+                   [](const auto* ref) { return const_cast<Reference<Type>*>(ref); });
+    return ret;
+}
+
+std::vector<const Reference<Type>*> Type::getReferences() const {
     return {};
 }
 
-std::vector<ConstantExpression*> Type::getConstantExpressions() const {
+std::vector<ConstantExpression*> Type::getConstantExpressions() {
+    const auto& constRet = static_cast<const Type*>(this)->getConstantExpressions();
+    std::vector<ConstantExpression*> ret(constRet.size());
+    std::transform(constRet.begin(), constRet.end(), ret.begin(),
+                   [](const auto* ce) { return const_cast<ConstantExpression*>(ce); });
+    return ret;
+}
+
+std::vector<const ConstantExpression*> Type::getConstantExpressions() const {
     return {};
 }
 
-std::vector<Reference<Type>> Type::getStrongReferences() const {
+std::vector<Reference<Type>*> Type::getStrongReferences() {
+    const auto& constRet = static_cast<const Type*>(this)->getStrongReferences();
+    std::vector<Reference<Type>*> ret(constRet.size());
+    std::transform(constRet.begin(), constRet.end(), ret.begin(),
+                   [](const auto* ref) { return const_cast<Reference<Type>*>(ref); });
+    return ret;
+}
+
+std::vector<const Reference<Type>*> Type::getStrongReferences() const {
     return getReferences();
 }
 
@@ -124,8 +157,8 @@
         if (err != OK) return err;
     }
 
-    for (const auto& nextType : getReferences()) {
-        err = nextType->recursivePass(func, visited);
+    for (auto* nextRef : getReferences()) {
+        err = (*nextRef)->recursivePass(func, visited);
         if (err != OK) return err;
     }
 
@@ -147,8 +180,8 @@
         if (err != OK) return err;
     }
 
-    for (const auto& nextRef : getReferences()) {
-        const auto* nextType = nextRef.get();
+    for (const auto* nextRef : getReferences()) {
+        const auto* nextType = nextRef->get();
         err = nextType->recursivePass(func, visited);
         if (err != OK) return err;
     }
@@ -180,7 +213,7 @@
     visited->insert(this);
     stack->insert(this);
 
-    for (const Type* nextType : getDefinedTypes()) {
+    for (const auto* nextType : getDefinedTypes()) {
         auto err = nextType->checkAcyclic(visited, stack);
 
         if (err.status != OK) {
@@ -199,13 +232,14 @@
         }
     }
 
-    for (const Reference<Type>& nextType : getStrongReferences()) {
+    for (const auto* nextRef : getStrongReferences()) {
+        const auto* nextType = nextRef->get();
         auto err = nextType->checkAcyclic(visited, stack);
 
         if (err.status != OK) {
             if (err.cycleEnd == nullptr) return err;
 
-            std::cerr << "  '" << nextType->typeName() << "' at " << nextType.location() << "\n";
+            std::cerr << "  '" << nextType->typeName() << "' at " << nextRef->location() << "\n";
 
             if (err.cycleEnd == nextType) {
                 return CheckAcyclicStatus(err.status);
@@ -609,8 +643,8 @@
     return true;
 }
 
-std::vector<Reference<Type>> TemplatedType::getReferences() const {
-    return {mElementType};
+std::vector<const Reference<Type>*> TemplatedType::getReferences() const {
+    return {&mElementType};
 }
 
 status_t TemplatedType::validate() const {
diff --git a/Type.h b/Type.h
index ddea9bd..1338ffb 100644
--- a/Type.h
+++ b/Type.h
@@ -56,17 +56,21 @@
     virtual bool isVector() const;
 
     // All types defined in this type.
-    virtual std::vector<Type*> getDefinedTypes() const;
+    std::vector<Type*> getDefinedTypes();
+    virtual std::vector<const Type*> getDefinedTypes() const;
 
     // All types referenced in this type.
-    virtual std::vector<Reference<Type>> getReferences() const;
+    std::vector<Reference<Type>*> getReferences();
+    virtual std::vector<const Reference<Type>*> getReferences() const;
 
     // All constant expressions referenced in this type.
-    virtual std::vector<ConstantExpression*> getConstantExpressions() const;
+    std::vector<ConstantExpression*> getConstantExpressions();
+    virtual std::vector<const ConstantExpression*> getConstantExpressions() const;
 
     // All types referenced in this type that must have completed
     // definiton before being referenced.
-    virtual std::vector<Reference<Type>> getStrongReferences() const;
+    std::vector<Reference<Type>*> getStrongReferences();
+    virtual std::vector<const Reference<Type>*> getStrongReferences() const;
 
     // Proceeds recursive pass
     // Makes sure to visit each node only once.
@@ -312,7 +316,7 @@
 
     virtual bool isCompatibleElementType(Type* elementType) const = 0;
 
-    std::vector<Reference<Type>> getReferences() const override;
+    std::vector<const Reference<Type>*> getReferences() const override;
 
     virtual status_t validate() const override;
 
diff --git a/VectorType.cpp b/VectorType.cpp
index d09c226..55ea9bb 100644
--- a/VectorType.cpp
+++ b/VectorType.cpp
@@ -81,7 +81,7 @@
     return mElementType->canCheckEquality();
 }
 
-std::vector<Reference<Type>> VectorType::getStrongReferences() const {
+std::vector<const Reference<Type>*> VectorType::getStrongReferences() const {
     return {};
 }
 
diff --git a/VectorType.h b/VectorType.h
index a6acd0a..efd8798 100644
--- a/VectorType.h
+++ b/VectorType.h
@@ -33,7 +33,7 @@
     std::string typeName() const override;
     bool isCompatibleElementType(Type *elementType) const override;
 
-    std::vector<Reference<Type>> getStrongReferences() const override;
+    std::vector<const Reference<Type>*> getStrongReferences() const override;
 
     bool canCheckEquality() const override;