Fix nested structure/union name handling.

Local names must be assigned before processing the body.

Change-Id: I9c3e3d4b7575c612148aea89bbd424e59e3c0604
diff --git a/AST.cpp b/AST.cpp
index 5939e85..66e54c4 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -18,7 +18,7 @@
     : mCoordinator(coordinator),
       mPath(path),
       mScanner(NULL),
-      mRootScope(new Scope) {
+      mRootScope(new Scope("" /* localName */)) {
     enterScope(mRootScope);
 }
 
@@ -128,10 +128,9 @@
             localName, new TypeDef(type), errorMsg, true /* isTypeDef */);
 }
 
-bool AST::addScopedType(
-        const char *localName, NamedType *type, std::string *errorMsg) {
+bool AST::addScopedType(NamedType *type, std::string *errorMsg) {
     return addScopedTypeInternal(
-            localName, type, errorMsg, false /* isTypeDef */);
+            type->localName().c_str(), type, errorMsg, false /* isTypeDef */);
 }
 
 bool AST::addScopedTypeInternal(
@@ -146,14 +145,6 @@
         }
     }
 
-    std::string anonName;
-
-    if (localName == nullptr) {
-        // Anonymous type declaration.
-        anonName = scope()->pickUniqueAnonymousName();
-        localName = anonName.c_str();
-    }
-
     // LOG(INFO) << "adding scoped type '" << localName << "'";
 
     bool success = scope()->addType(localName, type,  errorMsg);
@@ -174,7 +165,6 @@
         CHECK(type->isNamedType());
 
         NamedType *namedType = static_cast<NamedType *>(type);
-        namedType->setLocalName(localName);
         namedType->setFullName(fqName);
     }
 
diff --git a/AST.h b/AST.h
index e2b68cf..67256f3 100644
--- a/AST.h
+++ b/AST.h
@@ -41,8 +41,7 @@
     bool addTypeDef(const char *localName, Type *type, std::string *errorMsg);
 
     // Returns true iff successful.
-    bool addScopedType(
-            const char *localName, NamedType *type, std::string *errorMsg);
+    bool addScopedType(NamedType *type, std::string *errorMsg);
 
     void *scanner();
     void setScanner(void *scanner);
diff --git a/CompoundType.cpp b/CompoundType.cpp
index 015b576..d757acd 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -6,8 +6,9 @@
 
 namespace android {
 
-CompoundType::CompoundType(Style style)
-    : mStyle(style),
+CompoundType::CompoundType(Style style, const char *localName)
+    : Scope(localName),
+      mStyle(style),
       mFields(NULL) {
 }
 
diff --git a/CompoundType.h b/CompoundType.h
index 3628b52..4333d8d 100644
--- a/CompoundType.h
+++ b/CompoundType.h
@@ -16,7 +16,7 @@
         STYLE_UNION,
     };
 
-    CompoundType(Style style);
+    CompoundType(Style style, const char *localName);
 
     bool setFields(std::vector<CompoundField *> *fields, std::string *errorMsg);
 
diff --git a/EnumType.cpp b/EnumType.cpp
index 3a9a3c2..0ae6215 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -8,8 +8,11 @@
 namespace android {
 
 EnumType::EnumType(
-        std::vector<EnumValue *> *values, Type *storageType)
-    : mValues(values),
+        const char *localName,
+        std::vector<EnumValue *> *values,
+        Type *storageType)
+    : NamedType(localName),
+      mValues(values),
       mStorageType(
               storageType != NULL
                 ? storageType
diff --git a/EnumType.h b/EnumType.h
index 7aa55e5..fc2a9ea 100644
--- a/EnumType.h
+++ b/EnumType.h
@@ -11,7 +11,8 @@
 struct EnumValue;
 
 struct EnumType : public NamedType {
-    EnumType(std::vector<EnumValue *> *values,
+    EnumType(const char *localName,
+             std::vector<EnumValue *> *values,
              Type *storageType = NULL);
 
     const Type *storageType() const;
diff --git a/Interface.cpp b/Interface.cpp
index 52c1963..e48fc7c 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -6,8 +6,10 @@
 
 namespace android {
 
-Interface::Interface(Interface *super, AnnotationVector *annotations)
-    : mSuperType(super),
+Interface::Interface(
+        const char *localName, Interface *super, AnnotationVector *annotations)
+    : Scope(localName),
+      mSuperType(super),
       mAnnotationsByName(annotations),
       mIsJavaCompatibleInProgress(false) {
 }
diff --git a/Interface.h b/Interface.h
index d825122..2770990 100644
--- a/Interface.h
+++ b/Interface.h
@@ -15,6 +15,7 @@
 
 struct Interface : public Scope {
     Interface(
+            const char *localName,
             Interface *super,
             AnnotationVector *annotations);
 
diff --git a/NamedType.cpp b/NamedType.cpp
index ddefff7..d3b48f2 100644
--- a/NamedType.cpp
+++ b/NamedType.cpp
@@ -2,16 +2,14 @@
 
 namespace android {
 
-NamedType::NamedType() {}
+NamedType::NamedType(const char *localName)
+    : mLocalName(localName) {
+}
 
 bool NamedType::isNamedType() const {
     return true;
 }
 
-void NamedType::setLocalName(const std::string &localName) {
-    mLocalName = localName;
-}
-
 void NamedType::setFullName(const FQName &fullName) {
     mFullName = fullName;
 }
diff --git a/NamedType.h b/NamedType.h
index 52a7434..5f79bf6 100644
--- a/NamedType.h
+++ b/NamedType.h
@@ -11,11 +11,10 @@
 namespace android {
 
 struct NamedType : public Type {
-    NamedType();
+    NamedType(const char *localName);
 
     bool isNamedType() const override;
 
-    void setLocalName(const std::string &localName);
     void setFullName(const FQName &fullName);
 
     const FQName &fqName() const;
diff --git a/ScalarType.cpp b/ScalarType.cpp
index 479a6b5..036ba46 100644
--- a/ScalarType.cpp
+++ b/ScalarType.cpp
@@ -143,7 +143,6 @@
     handleError(out, mode);
 }
 
-
 status_t ScalarType::emitVtsTypeDeclarations(Formatter &out) const {
     std::string extra;
     out << "type: TYPE_SCALAR\n"
diff --git a/Scope.cpp b/Scope.cpp
index 28570e0..16f67ec 100644
--- a/Scope.cpp
+++ b/Scope.cpp
@@ -7,7 +7,9 @@
 
 namespace android {
 
-Scope::Scope() {}
+Scope::Scope(const char *localName)
+    : NamedType(localName) {
+}
 
 bool Scope::addType(const char *localName, Type *type, std::string *errorMsg) {
     if (mTypeIndexByName.indexOfKey(localName) >= 0) {
diff --git a/Scope.h b/Scope.h
index 4a77a7c..5a90abe 100644
--- a/Scope.h
+++ b/Scope.h
@@ -13,7 +13,7 @@
 struct Interface;
 
 struct Scope : public NamedType {
-    Scope();
+    Scope(const char *localName);
 
     bool addType(const char *localName, Type *type, std::string *errorMsg);
 
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index 5867f4a..31568b8 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -282,12 +282,12 @@
               YYERROR;
           }
 
-          Interface *iface = new Interface(static_cast<Interface *>($4), $1);
+          Interface *iface = new Interface($3, static_cast<Interface *>($4), $1);
 
           // Register interface immediately so it can be referenced inside
           // definition.
           std::string errorMsg;
-          if (!ast->addScopedType($3, iface, &errorMsg)) {
+          if (!ast->addScopedType(iface, &errorMsg)) {
               std::cerr << "ERROR: " << errorMsg << " at " << @3 << "\n";
               YYERROR;
           }
@@ -411,7 +411,7 @@
 named_struct_or_union_declaration
     : struct_or_union_keyword IDENTIFIER
       {
-          CompoundType *container = new CompoundType($1);
+          CompoundType *container = new CompoundType($1, $2);
           ast->enterScope(container);
       }
       struct_or_union_body
@@ -426,7 +426,7 @@
 
           ast->leaveScope();
 
-          if (!ast->addScopedType($2, container, &errorMsg)) {
+          if (!ast->addScopedType(container, &errorMsg)) {
               std::cerr << "ERROR: " << errorMsg << " at " << @2 << "\n";
               YYERROR;
           }
@@ -436,7 +436,14 @@
 struct_or_union_declaration
     : struct_or_union_keyword optIdentifier
       {
-          CompoundType *container = new CompoundType($1);
+          const char *localName = $2;
+          std::string anonName;
+          if (localName == nullptr) {
+              anonName = ast->scope()->pickUniqueAnonymousName();
+              localName = anonName.c_str();
+          }
+
+          CompoundType *container = new CompoundType($1, localName);
           ast->enterScope(container);
       }
       struct_or_union_body
@@ -451,7 +458,7 @@
 
           ast->leaveScope();
 
-          if (!ast->addScopedType($2, container, &errorMsg)) {
+          if (!ast->addScopedType(container, &errorMsg)) {
               std::cerr << "ERROR: " << errorMsg << " at " << @2 << "\n";
               YYERROR;
           }
@@ -505,10 +512,10 @@
 named_enum_declaration
     : ENUM IDENTIFIER opt_storage_type '{' enum_values opt_comma '}'
       {
-          EnumType *enumType = new EnumType($5, $3);
+          EnumType *enumType = new EnumType($2, $5, $3);
 
           std::string errorMsg;
-          if (!ast->addScopedType($2, enumType, &errorMsg)) {
+          if (!ast->addScopedType(enumType, &errorMsg)) {
               std::cerr << "ERROR: " << errorMsg << " at " << @2 << "\n";
               YYERROR;
           }
@@ -518,10 +525,12 @@
 enum_declaration
     : ENUM '{' enum_values opt_comma '}'
       {
-          EnumType *enumType = new EnumType($3);
+          std::string anonName = ast->scope()->pickUniqueAnonymousName();
+
+          EnumType *enumType = new EnumType(anonName.c_str(), $3);
 
           std::string errorMsg;
-          if (!ast->addScopedType(NULL /* localName */, enumType, &errorMsg)) {
+          if (!ast->addScopedType(enumType, &errorMsg)) {
               // This should never fail.
               std::cerr << "ERROR: " << errorMsg << "\n";
               YYERROR;
@@ -531,10 +540,10 @@
       }
     | ENUM IDENTIFIER opt_storage_type '{' enum_values opt_comma '}'
       {
-          EnumType *enumType = new EnumType($5, $3);
+          EnumType *enumType = new EnumType($2, $5, $3);
 
           std::string errorMsg;
-          if (!ast->addScopedType($2, enumType, &errorMsg)) {
+          if (!ast->addScopedType(enumType, &errorMsg)) {
               std::cerr << "ERROR: " << errorMsg << " at " << @2 << "\n";
               YYERROR;
           }