Be a little smarter about dealing with TypeDefs, resolve to the typedef'd
target at lookup time, so all code ever sees is anything _but_ TypeDefs.
Also verify that the optional Enum storage type is valid (i.e. an enum
or an integer type) and re-emit enum values for derived enum types.
diff --git a/AST.cpp b/AST.cpp
index d10a3ef..c26c99c 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -5,6 +5,7 @@
#include "FQName.h"
#include "HandleType.h"
#include "Scope.h"
+#include "TypeDef.h"
#include <android-base/logging.h>
#include <stdlib.h>
@@ -183,6 +184,11 @@
Type *type = mScopePath[i]->lookupType(name);
if (type != NULL) {
+ // Resolve typeDefs to the target type.
+ while (type->isTypeDef()) {
+ type = static_cast<TypeDef *>(type)->referencedType();
+ }
+
return type->ref();
}
}
@@ -228,6 +234,11 @@
}
if (dotPos == std::string::npos) {
+ // Resolve typeDefs to the target type.
+ while (type->isTypeDef()) {
+ type = static_cast<TypeDef *>(type)->referencedType();
+ }
+
return type;
}
diff --git a/EnumType.cpp b/EnumType.cpp
index 3cd8c8a..95cb6be 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -16,10 +16,22 @@
: new ScalarType(ScalarType::KIND_INT32)) {
}
+const Type *EnumType::storageType() const {
+ return mStorageType;
+}
+
+const std::vector<EnumValue *> &EnumType::values() const {
+ return *mValues;
+}
+
const ScalarType *EnumType::resolveToScalarType() const {
return mStorageType->resolveToScalarType();
}
+bool EnumType::isEnum() const {
+ return true;
+}
+
std::string EnumType::getCppType(StorageMode, std::string *extra) const {
extra->clear();
@@ -60,15 +72,32 @@
out.indent();
- for (const auto &entry : *mValues) {
- out << entry->name();
+ std::vector<const EnumType *> chain;
+ const EnumType *type = this;
+ for (;;) {
+ chain.push_back(type);
- const char *value = entry->value();
- if (value != NULL) {
- out << " = " << value;
+ const Type *superType = type->storageType();
+ if (superType == NULL || !superType->isEnum()) {
+ break;
}
- out << ",\n";
+ type = static_cast<const EnumType *>(superType);
+ }
+
+ for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
+ const auto &type = *it;
+
+ for (const auto &entry : type->values()) {
+ out << entry->name();
+
+ const char *value = entry->value();
+ if (value != NULL) {
+ out << " = " << value;
+ }
+
+ out << ",\n";
+ }
}
out.unindent();
diff --git a/EnumType.h b/EnumType.h
index 2bb258c..939cd3b 100644
--- a/EnumType.h
+++ b/EnumType.h
@@ -14,8 +14,13 @@
EnumType(std::vector<EnumValue *> *values,
Type *storageType = NULL);
+ const Type *storageType() const;
+ const std::vector<EnumValue *> &values() const;
+
const ScalarType *resolveToScalarType() const override;
+ bool isEnum() const override;
+
std::string getCppType(StorageMode mode, std::string *extra) const override;
void emitReaderWriter(
diff --git a/ScalarType.cpp b/ScalarType.cpp
index d612d9b..f308a72 100644
--- a/ScalarType.cpp
+++ b/ScalarType.cpp
@@ -12,6 +12,11 @@
return this;
}
+bool ScalarType::isValidEnumStorageType() const {
+ // Only integer types.
+ return mKind >= KIND_INT8 && mKind <= KIND_UINT64;
+}
+
std::string ScalarType::getCppType(StorageMode, std::string *extra) const {
static const char *const kName[] = {
"char",
diff --git a/ScalarType.h b/ScalarType.h
index bc642f5..38b79d4 100644
--- a/ScalarType.h
+++ b/ScalarType.h
@@ -27,6 +27,8 @@
const ScalarType *resolveToScalarType() const override;
+ bool isValidEnumStorageType() const;
+
std::string getCppType(StorageMode mode, std::string *extra) const override;
void emitReaderWriter(
diff --git a/Type.cpp b/Type.cpp
index 548e425..6d0e4e8 100644
--- a/Type.cpp
+++ b/Type.cpp
@@ -1,6 +1,7 @@
#include "Type.h"
#include "Formatter.h"
+#include "ScalarType.h"
#include <android-base/logging.h>
@@ -17,10 +18,28 @@
return false;
}
+bool Type::isEnum() const {
+ return false;
+}
+
+bool Type::isTypeDef() const {
+ return false;
+}
+
const ScalarType *Type::resolveToScalarType() const {
return NULL;
}
+bool Type::isValidEnumStorageType() const {
+ const ScalarType *scalarType = resolveToScalarType();
+
+ if (scalarType == NULL) {
+ return false;
+ }
+
+ return scalarType->isValidEnumStorageType();
+}
+
std::string Type::getCppType(StorageMode, std::string *) const {
CHECK(!"Should not be here");
return std::string();
diff --git a/Type.h b/Type.h
index bf0b6c6..03c6615 100644
--- a/Type.h
+++ b/Type.h
@@ -19,8 +19,13 @@
virtual bool isScope() const;
virtual bool isInterface() const;
+ virtual bool isEnum() const;
+ virtual bool isTypeDef() const;
+
virtual const ScalarType *resolveToScalarType() const;
+ bool isValidEnumStorageType() const;
+
enum StorageMode {
StorageMode_Stack,
StorageMode_Argument,
diff --git a/TypeDef.cpp b/TypeDef.cpp
index 1d50e6e..1e3c5b7 100644
--- a/TypeDef.cpp
+++ b/TypeDef.cpp
@@ -2,6 +2,8 @@
#include "Formatter.h"
+#include <android-base/logging.h>
+
namespace android {
TypeDef::TypeDef(Type *type)
@@ -10,60 +12,36 @@
}
const ScalarType *TypeDef::resolveToScalarType() const {
- return mReferencedType->resolveToScalarType();
+ CHECK(!"Should not be here");
+ return NULL;
}
-const Type *TypeDef::referencedType() const {
+Type *TypeDef::referencedType() const {
return mReferencedType;
}
bool TypeDef::isInterface() const {
- return mReferencedType->isInterface();
+ CHECK(!"Should not be here");
+ return false;
}
-std::string TypeDef::getCppType(StorageMode mode, std::string *extra) const {
- return mReferencedType->getCppType(mode, extra);
+bool TypeDef::isEnum() const {
+ CHECK(!"Should not be here");
+ return false;
}
-void TypeDef::emitReaderWriter(
- Formatter &out,
- const std::string &name,
- const std::string &parcelObj,
- bool parcelObjIsPointer,
- bool isReader,
- ErrorMode mode) const {
- mReferencedType->emitReaderWriter(
- out, name, parcelObj, parcelObjIsPointer, isReader, mode);
-}
-
-void TypeDef::emitReaderWriterEmbedded(
- Formatter &out,
- const std::string &name,
- bool nameIsPointer,
- const std::string &parcelObj,
- bool parcelObjIsPointer,
- bool isReader,
- ErrorMode mode,
- const std::string &parentName,
- const std::string &offsetText) const {
- mReferencedType->emitReaderWriterEmbedded(
- out,
- name,
- nameIsPointer,
- parcelObj,
- parcelObjIsPointer,
- isReader,
- mode,
- parentName,
- offsetText);
+bool TypeDef::isTypeDef() const {
+ return true;
}
bool TypeDef::needsEmbeddedReadWrite() const {
- return mReferencedType->needsEmbeddedReadWrite();
+ CHECK(!"Should not be here");
+ return false;
}
bool TypeDef::resultNeedsDeref() const {
- return mReferencedType->resultNeedsDeref();
+ CHECK(!"Should not be here");
+ return false;
}
} // namespace android
diff --git a/TypeDef.h b/TypeDef.h
index 14e0727..f3030bf 100644
--- a/TypeDef.h
+++ b/TypeDef.h
@@ -11,30 +11,11 @@
const ScalarType *resolveToScalarType() const override;
- const Type *referencedType() const;
+ Type *referencedType() const;
bool isInterface() const override;
-
- std::string getCppType(StorageMode mode, std::string *extra) const override;
-
- void emitReaderWriter(
- Formatter &out,
- const std::string &name,
- const std::string &parcelObj,
- bool parcelObjIsPointer,
- bool isReader,
- ErrorMode mode) const override;
-
- void emitReaderWriterEmbedded(
- Formatter &out,
- const std::string &name,
- bool nameIsPointer,
- const std::string &parcelObj,
- bool parcelObjIsPointer,
- bool isReader,
- ErrorMode mode,
- const std::string &parentName,
- const std::string &offsetText) const override;
+ bool isEnum() const override;
+ bool isTypeDef() const override;
bool needsEmbeddedReadWrite() const override;
bool resultNeedsDeref() const override;
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index 81151a7..4f640ce 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -162,7 +162,6 @@
YYERROR;
}
- // XXX What if $3 was a typedef _pointing_ to an interface...
Interface *iface = new Interface(static_cast<Interface *>($3));
// Register interface immediately so it can be referenced inside
@@ -331,7 +330,15 @@
opt_storage_type
: /* empty */ { $$ = NULL; }
- | ':' fqname { $$ = $2; }
+ | ':' fqname
+ {
+ $$ = $2;
+
+ if ($$ != NULL && !$$->isValidEnumStorageType()) {
+ fprintf(stderr, "Invalid enum storage type specified.\n");
+ YYABORT;
+ }
+ }
;
opt_comma