Better diagnostics if an attempt is made to redeclare a type under the same name

as an existing type in that scope. Support for anonymous struct/unions.

Change-Id: I0122cfae4da848419956c7b27bacaca66f8021d5
Bug: 30896059
diff --git a/AST.cpp b/AST.cpp
index 20db9b3..d5f8cc7 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -109,6 +109,14 @@
 }
 
 bool AST::addScopedType(const char *localName, NamedType *type) {
+    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);
diff --git a/Scope.cpp b/Scope.cpp
index abad31d..0e21c8e 100644
--- a/Scope.cpp
+++ b/Scope.cpp
@@ -12,6 +12,10 @@
 
 bool Scope::addType(const char *localName, NamedType *type) {
     if (mTypeIndexByName.indexOfKey(localName) >= 0) {
+        fprintf(stderr,
+                "A type named '%s' is already declared in the current scope.\n",
+                localName);
+
         return false;
     }
 
@@ -67,6 +71,18 @@
     return false;
 }
 
+std::string Scope::pickUniqueAnonymousName() const {
+    static size_t sNextID = 0;
+
+    for (;;) {
+        std::string anonName = "_hidl_Anon_" + std::to_string(sNextID++);
+
+        if (mTypeIndexByName.indexOfKey(anonName) < 0) {
+            return anonName;
+        }
+    }
+}
+
 std::string Scope::getJavaType() const {
     CHECK(!"Should not be here");
     return std::string();
diff --git a/Scope.h b/Scope.h
index 0c3ca68..ad140ac 100644
--- a/Scope.h
+++ b/Scope.h
@@ -29,6 +29,8 @@
 
     bool containsSingleInterface(std::string *ifaceName) const;
 
+    std::string pickUniqueAnonymousName() const;
+
     std::string getJavaType() const override;
 
     status_t emitTypeDeclarations(Formatter &out) const override;