Fix strong references
Makes strong references to deal with interface corner case explicitly.
Makes hidl-gen to detect a cycle through typedef.
Cycle example:
typedef S A;
struct S {
A foo;
};
Fixes: 65559985
Test: mma
Test: error test in follow up CL
Change-Id: I132037995c3fc99edfe3e57a1fe84d3c36ca6993
diff --git a/Interface.cpp b/Interface.cpp
index 2e0d931..0fd702c 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -486,14 +486,17 @@
// Interface is a special case as a reference:
// its definiton must be completed for extension but
// not necessary for other references.
- // As interface declaration appears only in global scope and
- // method declaration appears only in interface, we may assume
- // that all references in method definitions are acyclic.
std::vector<const Reference<Type>*> ret;
if (superType() != nullptr) {
ret.push_back(&mSuperType);
}
+
+ for (const auto* method : methods()) {
+ const auto& references = method->getStrongReferences();
+ ret.insert(ret.end(), references.begin(), references.end());
+ }
+
return ret;
}
@@ -982,5 +985,9 @@
return Scope::isJavaCompatible(visited);
}
+bool Interface::isNeverStrongReference() const {
+ return true;
+}
+
} // namespace android
diff --git a/Interface.h b/Interface.h
index ae3bc13..bf22cb5 100644
--- a/Interface.h
+++ b/Interface.h
@@ -121,6 +121,8 @@
bool deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const override;
+ bool isNeverStrongReference() const override;
+
private:
Reference<Type> mSuperType;
diff --git a/Method.cpp b/Method.cpp
index 6885881..64a9a65 100644
--- a/Method.cpp
+++ b/Method.cpp
@@ -84,6 +84,24 @@
return ret;
}
+std::vector<Reference<Type>*> Method::getStrongReferences() {
+ const auto& constRet = static_cast<const Method*>(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>*> Method::getStrongReferences() const {
+ std::vector<const Reference<Type>*> ret;
+ for (const auto* ref : getReferences()) {
+ if (!ref->shallowGet()->isNeverStrongReference()) {
+ ret.push_back(ref);
+ }
+ }
+ return ret;
+}
+
std::vector<ConstantExpression*> Method::getConstantExpressions() {
const auto& constRet = static_cast<const Method*>(this)->getConstantExpressions();
std::vector<ConstantExpression*> ret(constRet.size());
diff --git a/Method.h b/Method.h
index 79e320d..291ea34 100644
--- a/Method.h
+++ b/Method.h
@@ -70,6 +70,9 @@
std::vector<Reference<Type>*> getReferences();
std::vector<const Reference<Type>*> getReferences() const;
+ std::vector<Reference<Type>*> getStrongReferences();
+ std::vector<const Reference<Type>*> getStrongReferences() const;
+
std::vector<ConstantExpression*> getConstantExpressions();
std::vector<const ConstantExpression*> getConstantExpressions() const;
diff --git a/Type.cpp b/Type.cpp
index cbc47fe..92df2e2 100644
--- a/Type.cpp
+++ b/Type.cpp
@@ -149,7 +149,13 @@
}
std::vector<const Reference<Type>*> Type::getStrongReferences() const {
- return getReferences();
+ std::vector<const Reference<Type>*> ret;
+ for (const auto* ref : getReferences()) {
+ if (!ref->shallowGet()->isNeverStrongReference()) {
+ ret.push_back(ref);
+ }
+ }
+ return ret;
}
status_t Type::recursivePass(const std::function<status_t(Type*)>& func,
@@ -306,7 +312,8 @@
// like pointers, vectors, interfaces.
if (isStrongRef) {
// Enum storage type and bitfield element type do not appear in output code.
- if (isEnum() || isBitField()) return OK;
+ // Typedef does not require complete declaration.
+ if (isEnum() || isBitField() || isTypeDef()) return OK;
std::cerr << "ERROR: Forward reference of '" << refType->typeName() << "' at "
<< ref.location() << " is not supported.\n"
@@ -770,6 +777,10 @@
return OK;
}
+bool Type::isNeverStrongReference() const {
+ return false;
+}
+
////////////////////////////////////////
TemplatedType::TemplatedType(Scope* parent) : Type(parent) {}
diff --git a/Type.h b/Type.h
index fc01c40..7bc853d 100644
--- a/Type.h
+++ b/Type.h
@@ -300,7 +300,9 @@
virtual status_t emitExportedHeader(Formatter &out, bool forJava) const;
-protected:
+ virtual bool isNeverStrongReference() const;
+
+ protected:
void handleError(Formatter &out, ErrorMode mode) const;
void emitReaderWriterEmbeddedForTypeName(
diff --git a/TypeDef.cpp b/TypeDef.cpp
index 1592778..d0e0c09 100644
--- a/TypeDef.cpp
+++ b/TypeDef.cpp
@@ -63,15 +63,6 @@
return {&mReferencedType};
}
-std::vector<const Reference<Type>*> TypeDef::getStrongReferences() const {
- // Typedef definition can be cyclic only if
- // it is referenced by another typedef
- if (!mReferencedType.shallowGet()->isTypeDef()) {
- return {};
- }
- return {&mReferencedType};
-}
-
bool TypeDef::needsEmbeddedReadWrite() const {
CHECK(!"Should not be here");
return false;
diff --git a/TypeDef.h b/TypeDef.h
index 0e380fa..d383f50 100644
--- a/TypeDef.h
+++ b/TypeDef.h
@@ -42,7 +42,6 @@
const Type* resolve() const override;
std::vector<const Reference<Type>*> getReferences() const override;
- std::vector<const Reference<Type>*> getStrongReferences() const override;
status_t emitTypeDeclarations(Formatter &out) const override;