Cleaned up namespace handling.

A Namespace object is now guaranteed unique.
This cleaned up some old workarounds and latent bugs.

Change-Id: Ic3f12d89947871b03b2c449ba51b3186f953adde
Tested: on Linux.
Bug: 21336857
diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h
index 4d158d1..4ed23fe 100644
--- a/include/flatbuffers/idl.h
+++ b/include/flatbuffers/idl.h
@@ -483,13 +483,17 @@
 class Parser : public ParserState {
  public:
   explicit Parser(const IDLOptions &options = IDLOptions())
-    : root_struct_def_(nullptr),
+    : current_namespace_(nullptr),
+      empty_namespace_(nullptr),
+      root_struct_def_(nullptr),
       opts(options),
       uses_flexbuffers_(false),
       source_(nullptr),
       anonymous_counter(0) {
-    // Just in case none are declared:
-    namespaces_.push_back(new Namespace());
+    // Start out with the empty namespace being current.
+    empty_namespace_ = new Namespace();
+    namespaces_.push_back(empty_namespace_);
+    current_namespace_ = empty_namespace_;
     known_attributes_["deprecated"] = true;
     known_attributes_["required"] = true;
     known_attributes_["key"] = true;
@@ -649,6 +653,7 @@
                                        BaseType baseType);
 
   bool SupportsVectorOfUnions() const;
+  Namespace *UniqueNamespace(Namespace *ns);
 
  public:
   SymbolTable<Type> types_;
@@ -656,6 +661,8 @@
   SymbolTable<EnumDef> enums_;
   SymbolTable<ServiceDef> services_;
   std::vector<Namespace *> namespaces_;
+  Namespace *current_namespace_;
+  Namespace *empty_namespace_;
   std::string error_;         // User readable error_ if Parse() == false
 
   FlatBufferBuilder builder_;  // any data contained in the file
diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp
index 0953b1a..9a3217e 100644
--- a/src/idl_gen_cpp.cpp
+++ b/src/idl_gen_cpp.cpp
@@ -53,7 +53,7 @@
     guard = "FLATBUFFERS_GENERATED_" + guard;
     guard += "_";
     // For further uniqueness, also add the namespace.
-    auto name_space = parser_.namespaces_.back();
+    auto name_space = parser_.current_namespace_;
     for (auto it = name_space->components.begin();
          it != name_space->components.end(); ++it) {
       guard += *it + "_";
@@ -175,7 +175,7 @@
       SetNameSpace(struct_def.defined_namespace);
       const auto &name = struct_def.name;
       const auto qualified_name =
-          parser_.namespaces_.back()->GetFullyQualifiedName(name);
+          cur_name_space_->GetFullyQualifiedName(name);
       const auto cpp_name = TranslateNameSpace(qualified_name);
 
       code_.SetValue("STRUCT_NAME", name);
@@ -990,15 +990,14 @@
     return "VT_" + uname;
   }
 
-  void GenFullyQualifiedNameGetter(const std::string &name) {
+  void GenFullyQualifiedNameGetter(const StructDef &struct_def,
+                                   const std::string &name) {
     if (!parser_.opts.generate_name_strings) {
       return;
     }
-
-    auto fullname = parser_.namespaces_.back()->GetFullyQualifiedName(name);
+    auto fullname = struct_def.defined_namespace->GetFullyQualifiedName(name);
     code_.SetValue("NAME", fullname);
     code_.SetValue("CONSTEXPR", "FLATBUFFERS_CONSTEXPR");
-
     code_ += "  static {{CONSTEXPR}} const char *GetFullyQualifiedName() {";
     code_ += "    return \"{{NAME}}\";";
     code_ += "  }";
@@ -1115,7 +1114,7 @@
     // Generate a C++ object that can hold an unpacked version of this table.
     code_ += "struct {{NATIVE_NAME}} : public flatbuffers::NativeTable {";
     code_ += "  typedef {{STRUCT_NAME}} TableType;";
-    GenFullyQualifiedNameGetter(native_name);
+    GenFullyQualifiedNameGetter(struct_def, native_name);
     for (auto it = struct_def.fields.vec.begin();
          it != struct_def.fields.vec.end(); ++it) {
       GenMember(**it);
@@ -1204,7 +1203,7 @@
       code_ += "  typedef {{NATIVE_NAME}} NativeTableType;";
     }
 
-    GenFullyQualifiedNameGetter(struct_def.name);
+    GenFullyQualifiedNameGetter(struct_def, struct_def.name);
 
     // Generate field id constants.
     if (struct_def.fields.vec.size() > 0) {
@@ -1332,7 +1331,7 @@
       auto nested = field.attributes.Lookup("nested_flatbuffer");
       if (nested) {
         std::string qualified_name =
-            parser_.namespaces_.back()->GetFullyQualifiedName(
+            parser_.current_namespace_->GetFullyQualifiedName(
                 nested->constant);
         auto nested_root = parser_.structs_.Lookup(qualified_name);
         assert(nested_root);  // Guaranteed to exist by parser.
@@ -2057,7 +2056,7 @@
     // Generate GetFullyQualifiedName
     code_ += "";
     code_ += " public:";
-    GenFullyQualifiedNameGetter(struct_def.name);
+    GenFullyQualifiedNameGetter(struct_def, struct_def.name);
 
     // Generate a default constructor.
     code_ += "  {{STRUCT_NAME}}() {";
diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp
index 30a097d..8e79919 100644
--- a/src/idl_gen_general.cpp
+++ b/src/idl_gen_general.cpp
@@ -161,7 +161,7 @@
   GeneralGenerator &operator=(const GeneralGenerator &);
   bool generate() {
     std::string one_file_code;
-    cur_name_space_ = parser_.namespaces_.back();
+    cur_name_space_ = parser_.current_namespace_;
 
     for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
          ++it) {
@@ -194,7 +194,7 @@
     }
 
     if (parser_.opts.one_file) {
-      return SaveType(file_name_, *parser_.namespaces_.back(),
+      return SaveType(file_name_, *parser_.current_namespace_,
                       one_file_code, true);
     }
     return true;
diff --git a/src/idl_gen_grpc.cpp b/src/idl_gen_grpc.cpp
index 5d0cf4f..5fca268 100644
--- a/src/idl_gen_grpc.cpp
+++ b/src/idl_gen_grpc.cpp
@@ -214,11 +214,11 @@
   std::string service_header_ext() const { return ".grpc.fb.h"; }
 
   std::string package() const {
-    return parser_.namespaces_.back()->GetFullyQualifiedName("");
+    return parser_.current_namespace_->GetFullyQualifiedName("");
   }
 
   std::vector<std::string> package_parts() const {
-    return parser_.namespaces_.back()->components;
+    return parser_.current_namespace_->components;
   }
 
   std::string additional_headers() const {
diff --git a/src/idl_gen_python.cpp b/src/idl_gen_python.cpp
index acfcf0b..7958b91 100644
--- a/src/idl_gen_python.cpp
+++ b/src/idl_gen_python.cpp
@@ -677,7 +677,7 @@
     if (!classcode.length()) return true;
 
     std::string namespace_dir = path_;
-    auto &namespaces = parser_.namespaces_.back()->components;
+    auto &namespaces = def.defined_namespace->components;
     for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
       if (it != namespaces.begin()) namespace_dir += kPathSeparator;
       namespace_dir += *it;
diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp
index d9811bd..99513b8 100644
--- a/src/idl_parser.cpp
+++ b/src/idl_parser.cpp
@@ -529,10 +529,10 @@
 
 EnumDef *Parser::LookupEnum(const std::string &id) {
   // Search thru parent namespaces.
-  for (int components = static_cast<int>(namespaces_.back()->components.size());
+  for (int components = static_cast<int>(current_namespace_->components.size());
        components >= 0; components--) {
     auto ed = enums_.Lookup(
-                namespaces_.back()->GetFullyQualifiedName(id, components));
+                current_namespace_->GetFullyQualifiedName(id, components));
     if (ed) return ed;
   }
   return nullptr;
@@ -731,7 +731,8 @@
     LookupCreateStruct(nested->constant);
 
     // Keep a pointer to StructDef in FieldDef to simplify re-use later
-    auto nested_qualified_name = namespaces_.back()->GetFullyQualifiedName(nested->constant);
+    auto nested_qualified_name =
+        current_namespace_->GetFullyQualifiedName(nested->constant);
     field->nested_flatbuffer = structs_.Lookup(nested_qualified_name);
   }
 
@@ -1369,14 +1370,14 @@
 
 StructDef *Parser::LookupCreateStruct(const std::string &name,
                                       bool create_if_new, bool definition) {
-  std::string qualified_name = namespaces_.back()->GetFullyQualifiedName(name);
+  std::string qualified_name = current_namespace_->GetFullyQualifiedName(name);
   // See if it exists pre-declared by an unqualified use.
   auto struct_def = structs_.Lookup(name);
   if (struct_def && struct_def->predecl) {
     if (definition) {
       // Make sure it has the current namespace, and is registered under its
       // qualified name.
-      struct_def->defined_namespace = namespaces_.back();
+      struct_def->defined_namespace = current_namespace_;
       structs_.Move(name, qualified_name);
     }
     return struct_def;
@@ -1386,16 +1387,16 @@
   if (struct_def && struct_def->predecl) {
     if (definition) {
       // Make sure it has the current namespace.
-      struct_def->defined_namespace = namespaces_.back();
+      struct_def->defined_namespace = current_namespace_;
     }
     return struct_def;
   }
   if (!definition) {
     // Search thru parent namespaces.
-    for (size_t components = namespaces_.back()->components.size();
+    for (size_t components = current_namespace_->components.size();
          components && !struct_def; components--) {
       struct_def = structs_.Lookup(
-          namespaces_.back()->GetFullyQualifiedName(name, components - 1));
+          current_namespace_->GetFullyQualifiedName(name, components - 1));
     }
   }
   if (!struct_def && create_if_new) {
@@ -1403,7 +1404,7 @@
     if (definition) {
       structs_.Add(qualified_name, struct_def);
       struct_def->name = name;
-      struct_def->defined_namespace = namespaces_.back();
+      struct_def->defined_namespace = current_namespace_;
     } else {
       // Not a definition.
       // Rather than failing, we create a "pre declared" StructDef, due to
@@ -1413,8 +1414,7 @@
       // TODO: maybe safer to use special namespace?
       structs_.Add(name, struct_def);
       struct_def->name = name;
-      struct_def->defined_namespace = new Namespace();
-      namespaces_.insert(namespaces_.begin(), struct_def->defined_namespace);
+      struct_def->defined_namespace = empty_namespace_;
     }
   }
   return struct_def;
@@ -1430,8 +1430,8 @@
   enum_def.file = file_being_parsed_;
   enum_def.doc_comment = enum_comment;
   enum_def.is_union = is_union;
-  enum_def.defined_namespace = namespaces_.back();
-  if (enums_.Add(namespaces_.back()->GetFullyQualifiedName(enum_name),
+  enum_def.defined_namespace = current_namespace_;
+  if (enums_.Add(current_namespace_->GetFullyQualifiedName(enum_name),
                  &enum_def))
     return Error("enum already exists: " + enum_name);
   if (is_union) {
@@ -1531,7 +1531,7 @@
     }
   }
   if (dest) *dest = &enum_def;
-  types_.Add(namespaces_.back()->GetFullyQualifiedName(enum_def.name),
+  types_.Add(current_namespace_->GetFullyQualifiedName(enum_def.name),
              new Type(BASE_TYPE_UNION, nullptr, &enum_def));
   return NoError();
 }
@@ -1575,6 +1575,17 @@
     ~(IDLOptions::kCpp | IDLOptions::kJs | IDLOptions::kTs | IDLOptions::kPhp)) == 0;
 }
 
+Namespace *Parser::UniqueNamespace(Namespace *ns) {
+  for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
+    if (ns->components == (*it)->components) {
+      delete ns;
+      return *it;
+    }
+  }
+  namespaces_.push_back(ns);
+  return ns;
+}
+
 static bool compareFieldDefs(const FieldDef *a, const FieldDef *b) {
   auto a_id = atoi(a->attributes.Lookup("id")->constant.c_str());
   auto b_id = atoi(b->attributes.Lookup("id")->constant.c_str());
@@ -1643,7 +1654,7 @@
   ECHECK(CheckClash(fields, struct_def, "_byte_vector", BASE_TYPE_STRING));
   ECHECK(CheckClash(fields, struct_def, "ByteVector", BASE_TYPE_STRING));
   EXPECT('}');
-  types_.Add(namespaces_.back()->GetFullyQualifiedName(struct_def->name),
+  types_.Add(current_namespace_->GetFullyQualifiedName(struct_def->name),
              new Type(BASE_TYPE_STRUCT, struct_def, nullptr));
   return NoError();
 }
@@ -1657,8 +1668,8 @@
   service_def.name = service_name;
   service_def.file = file_being_parsed_;
   service_def.doc_comment = service_comment;
-  service_def.defined_namespace = namespaces_.back();
-  if (services_.Add(namespaces_.back()->GetFullyQualifiedName(service_name),
+  service_def.defined_namespace = current_namespace_;
+  if (services_.Add(current_namespace_->GetFullyQualifiedName(service_name),
                     &service_def))
     return Error("service already exists: " + service_name);
   ECHECK(ParseMetaData(&service_def.attributes));
@@ -1692,7 +1703,7 @@
   root_struct_def_ = structs_.Lookup(name);
   if (!root_struct_def_)
     root_struct_def_ = structs_.Lookup(
-                         namespaces_.back()->GetFullyQualifiedName(name));
+                         current_namespace_->GetFullyQualifiedName(name));
   return root_struct_def_ != nullptr;
 }
 
@@ -1719,7 +1730,7 @@
 CheckedError Parser::ParseNamespace() {
   NEXT();
   auto ns = new Namespace();
-  namespaces_.push_back(ns);
+  namespaces_.push_back(ns);  // Store it here to not leak upon error.
   if (token_ != ';') {
     for (;;) {
       ns->components.push_back(attribute_);
@@ -1727,6 +1738,8 @@
       if (Is('.')) NEXT() else break;
     }
   }
+  namespaces_.pop_back();
+  current_namespace_ = UniqueNamespace(ns);
   EXPECT(';');
   return NoError();
 }
@@ -1748,6 +1761,7 @@
     std::vector<std::string> struct_comment = doc_comment_;
     NEXT();
     StructDef *struct_def = nullptr;
+    Namespace *parent_namespace = nullptr;
     if (isextend) {
       if (Is('.')) NEXT();  // qualified names may start with a . ?
       auto id = attribute_;
@@ -1763,19 +1777,16 @@
       // Since message definitions can be nested, we create a new namespace.
       auto ns = new Namespace();
       // Copy of current namespace.
-      *ns = *namespaces_.back();
+      *ns = *current_namespace_;
       // But with current message name.
       ns->components.push_back(name);
-      namespaces_.push_back(ns);
+      parent_namespace = current_namespace_;
+      current_namespace_ = UniqueNamespace(ns);
     }
     struct_def->doc_comment = struct_comment;
     ECHECK(ParseProtoFields(struct_def, isextend, false));
     if (!isextend) {
-      // We have to remove the nested namespace, but we can't just throw it
-      // away, so put it at the beginning of the vector.
-      auto ns = namespaces_.back();
-      namespaces_.pop_back();
-      namespaces_.insert(namespaces_.begin(), ns);
+      current_namespace_ = parent_namespace;
     }
     if (Is(';')) NEXT();
   } else if (attribute_ == "enum") {
@@ -2139,7 +2150,8 @@
   // Check that all types were defined.
   for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) {
     if ((*it)->predecl) {
-      return Error("type referenced but not defined: " + (*it)->name);
+      return Error("type referenced but not defined (check namespace): " +
+                   (*it)->name);
     }
   }
 
@@ -2179,7 +2191,7 @@
   field_stack_.clear();
   builder_.Clear();
   // Start with a blank namespace just in case this file doesn't have one.
-  namespaces_.push_back(new Namespace());
+  current_namespace_ = empty_namespace_;
 
   ECHECK(StartParseFile(source, source_filename));
 
diff --git a/tests/MyGame/Example/Monster.cs b/tests/MyGame/Example/Monster.cs
index f8f59d4..ed43659 100644
--- a/tests/MyGame/Example/Monster.cs
+++ b/tests/MyGame/Example/Monster.cs
@@ -97,8 +97,9 @@
   public int VectorOfDoublesLength { get { int o = __p.__offset(70); return o != 0 ? __p.__vector_len(o) : 0; } }
   public ArraySegment<byte>? GetVectorOfDoublesBytes() { return __p.__vector_as_arraysegment(70); }
   public bool MutateVectorOfDoubles(int j, double vector_of_doubles) { int o = __p.__offset(70); if (o != 0) { __p.bb.PutDouble(__p.__vector(o) + j * 8, vector_of_doubles); return true; } else { return false; } }
+  public MyGame.InParentNamespace? ParentNamespaceTest { get { int o = __p.__offset(72); return o != 0 ? (MyGame.InParentNamespace?)(new MyGame.InParentNamespace()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
 
-  public static void StartMonster(FlatBufferBuilder builder) { builder.StartObject(34); }
+  public static void StartMonster(FlatBufferBuilder builder) { builder.StartObject(35); }
   public static void AddPos(FlatBufferBuilder builder, Offset<Vec3> posOffset) { builder.AddStruct(0, posOffset.Value, 0); }
   public static void AddMana(FlatBufferBuilder builder, short mana) { builder.AddShort(1, mana, 150); }
   public static void AddHp(FlatBufferBuilder builder, short hp) { builder.AddShort(2, hp, 100); }
@@ -153,6 +154,7 @@
   public static void AddVectorOfDoubles(FlatBufferBuilder builder, VectorOffset vectorOfDoublesOffset) { builder.AddOffset(33, vectorOfDoublesOffset.Value, 0); }
   public static VectorOffset CreateVectorOfDoublesVector(FlatBufferBuilder builder, double[] data) { builder.StartVector(8, data.Length, 8); for (int i = data.Length - 1; i >= 0; i--) builder.AddDouble(data[i]); return builder.EndVector(); }
   public static void StartVectorOfDoublesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); }
+  public static void AddParentNamespaceTest(FlatBufferBuilder builder, Offset<MyGame.InParentNamespace> parentNamespaceTestOffset) { builder.AddOffset(34, parentNamespaceTestOffset.Value, 0); }
   public static Offset<Monster> EndMonster(FlatBufferBuilder builder) {
     int o = builder.EndObject();
     builder.Required(o, 10);  // name
diff --git a/tests/MyGame/Example/Monster.go b/tests/MyGame/Example/Monster.go
index 6074973..04e5852 100644
--- a/tests/MyGame/Example/Monster.go
+++ b/tests/MyGame/Example/Monster.go
@@ -516,8 +516,21 @@
 	return 0
 }
 
+func (rcv *Monster) ParentNamespaceTest(obj *InParentNamespace) *InParentNamespace {
+	o := flatbuffers.UOffsetT(rcv._tab.Offset(72))
+	if o != 0 {
+		x := rcv._tab.Indirect(o + rcv._tab.Pos)
+		if obj == nil {
+			obj = new(InParentNamespace)
+		}
+		obj.Init(rcv._tab.Bytes, x)
+		return obj
+	}
+	return nil
+}
+
 func MonsterStart(builder *flatbuffers.Builder) {
-	builder.StartObject(34)
+	builder.StartObject(35)
 }
 func MonsterAddPos(builder *flatbuffers.Builder, pos flatbuffers.UOffsetT) {
 	builder.PrependStructSlot(0, flatbuffers.UOffsetT(pos), 0)
@@ -654,6 +667,9 @@
 func MonsterStartVectorOfDoublesVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
 	return builder.StartVector(8, numElems, 8)
 }
+func MonsterAddParentNamespaceTest(builder *flatbuffers.Builder, parentNamespaceTest flatbuffers.UOffsetT) {
+	builder.PrependUOffsetTSlot(34, flatbuffers.UOffsetT(parentNamespaceTest), 0)
+}
 func MonsterEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
 	return builder.EndObject()
 }
diff --git a/tests/MyGame/Example/Monster.java b/tests/MyGame/Example/Monster.java
index 870be6c..3d97b77 100644
--- a/tests/MyGame/Example/Monster.java
+++ b/tests/MyGame/Example/Monster.java
@@ -106,8 +106,10 @@
   public int vectorOfDoublesLength() { int o = __offset(70); return o != 0 ? __vector_len(o) : 0; }
   public ByteBuffer vectorOfDoublesAsByteBuffer() { return __vector_as_bytebuffer(70, 8); }
   public boolean mutateVectorOfDoubles(int j, double vector_of_doubles) { int o = __offset(70); if (o != 0) { bb.putDouble(__vector(o) + j * 8, vector_of_doubles); return true; } else { return false; } }
+  public MyGame.InParentNamespace parentNamespaceTest() { return parentNamespaceTest(new MyGame.InParentNamespace()); }
+  public MyGame.InParentNamespace parentNamespaceTest(MyGame.InParentNamespace obj) { int o = __offset(72); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; }
 
-  public static void startMonster(FlatBufferBuilder builder) { builder.startObject(34); }
+  public static void startMonster(FlatBufferBuilder builder) { builder.startObject(35); }
   public static void addPos(FlatBufferBuilder builder, int posOffset) { builder.addStruct(0, posOffset, 0); }
   public static void addMana(FlatBufferBuilder builder, short mana) { builder.addShort(1, mana, 150); }
   public static void addHp(FlatBufferBuilder builder, short hp) { builder.addShort(2, hp, 100); }
@@ -162,6 +164,7 @@
   public static void addVectorOfDoubles(FlatBufferBuilder builder, int vectorOfDoublesOffset) { builder.addOffset(33, vectorOfDoublesOffset, 0); }
   public static int createVectorOfDoublesVector(FlatBufferBuilder builder, double[] data) { builder.startVector(8, data.length, 8); for (int i = data.length - 1; i >= 0; i--) builder.addDouble(data[i]); return builder.endVector(); }
   public static void startVectorOfDoublesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(8, numElems, 8); }
+  public static void addParentNamespaceTest(FlatBufferBuilder builder, int parentNamespaceTestOffset) { builder.addOffset(34, parentNamespaceTestOffset, 0); }
   public static int endMonster(FlatBufferBuilder builder) {
     int o = builder.endObject();
     builder.required(o, 10);  // name
diff --git a/tests/MyGame/Example/Monster.php b/tests/MyGame/Example/Monster.php
index f422ee1..eb66de8 100644
--- a/tests/MyGame/Example/Monster.php
+++ b/tests/MyGame/Example/Monster.php
@@ -482,22 +482,29 @@
         return $o != 0 ? $this->__vector_len($o) : 0;
     }
 
+    public function getParentNamespaceTest()
+    {
+        $obj = new InParentNamespace();
+        $o = $this->__offset(72);
+        return $o != 0 ? $obj->init($this->__indirect($o + $this->bb_pos), $this->bb) : 0;
+    }
+
     /**
      * @param FlatBufferBuilder $builder
      * @return void
      */
     public static function startMonster(FlatBufferBuilder $builder)
     {
-        $builder->StartObject(34);
+        $builder->StartObject(35);
     }
 
     /**
      * @param FlatBufferBuilder $builder
      * @return Monster
      */
-    public static function createMonster(FlatBufferBuilder $builder, $pos, $mana, $hp, $name, $inventory, $color, $test_type, $test, $test4, $testarrayofstring, $testarrayoftables, $enemy, $testnestedflatbuffer, $testempty, $testbool, $testhashs32_fnv1, $testhashu32_fnv1, $testhashs64_fnv1, $testhashu64_fnv1, $testhashs32_fnv1a, $testhashu32_fnv1a, $testhashs64_fnv1a, $testhashu64_fnv1a, $testarrayofbools, $testf, $testf2, $testf3, $testarrayofstring2, $testarrayofsortedstruct, $flex, $test5, $vector_of_longs, $vector_of_doubles)
+    public static function createMonster(FlatBufferBuilder $builder, $pos, $mana, $hp, $name, $inventory, $color, $test_type, $test, $test4, $testarrayofstring, $testarrayoftables, $enemy, $testnestedflatbuffer, $testempty, $testbool, $testhashs32_fnv1, $testhashu32_fnv1, $testhashs64_fnv1, $testhashu64_fnv1, $testhashs32_fnv1a, $testhashu32_fnv1a, $testhashs64_fnv1a, $testhashu64_fnv1a, $testarrayofbools, $testf, $testf2, $testf3, $testarrayofstring2, $testarrayofsortedstruct, $flex, $test5, $vector_of_longs, $vector_of_doubles, $parent_namespace_test)
     {
-        $builder->startObject(34);
+        $builder->startObject(35);
         self::addPos($builder, $pos);
         self::addMana($builder, $mana);
         self::addHp($builder, $hp);
@@ -531,6 +538,7 @@
         self::addTest5($builder, $test5);
         self::addVectorOfLongs($builder, $vector_of_longs);
         self::addVectorOfDoubles($builder, $vector_of_doubles);
+        self::addParentNamespaceTest($builder, $parent_namespace_test);
         $o = $builder->endObject();
         $builder->required($o, 10);  // name
         return $o;
@@ -1151,6 +1159,16 @@
 
     /**
      * @param FlatBufferBuilder $builder
+     * @param int
+     * @return void
+     */
+    public static function addParentNamespaceTest(FlatBufferBuilder $builder, $parentNamespaceTest)
+    {
+        $builder->addOffsetX(34, $parentNamespaceTest, 0);
+    }
+
+    /**
+     * @param FlatBufferBuilder $builder
      * @return int table offset
      */
     public static function endMonster(FlatBufferBuilder $builder)
diff --git a/tests/MyGame/Example/Monster.py b/tests/MyGame/Example/Monster.py
index 1a1f095..910f39a 100644
--- a/tests/MyGame/Example/Monster.py
+++ b/tests/MyGame/Example/Monster.py
@@ -422,7 +422,18 @@
             return self._tab.VectorLen(o)
         return 0
 
-def MonsterStart(builder): builder.StartObject(34)
+    # Monster
+    def ParentNamespaceTest(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(72))
+        if o != 0:
+            x = self._tab.Indirect(o + self._tab.Pos)
+            from .InParentNamespace import InParentNamespace
+            obj = InParentNamespace()
+            obj.Init(self._tab.Bytes, x)
+            return obj
+        return None
+
+def MonsterStart(builder): builder.StartObject(35)
 def MonsterAddPos(builder, pos): builder.PrependStructSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(pos), 0)
 def MonsterAddMana(builder, mana): builder.PrependInt16Slot(1, mana, 150)
 def MonsterAddHp(builder, hp): builder.PrependInt16Slot(2, hp, 100)
@@ -468,4 +479,5 @@
 def MonsterStartVectorOfLongsVector(builder, numElems): return builder.StartVector(8, numElems, 8)
 def MonsterAddVectorOfDoubles(builder, vectorOfDoubles): builder.PrependUOffsetTRelativeSlot(33, flatbuffers.number_types.UOffsetTFlags.py_type(vectorOfDoubles), 0)
 def MonsterStartVectorOfDoublesVector(builder, numElems): return builder.StartVector(8, numElems, 8)
+def MonsterAddParentNamespaceTest(builder, parentNamespaceTest): builder.PrependUOffsetTRelativeSlot(34, flatbuffers.number_types.UOffsetTFlags.py_type(parentNamespaceTest), 0)
 def MonsterEnd(builder): return builder.EndObject()
diff --git a/tests/MyGame/Example2/__init__.py b/tests/MyGame/Example2/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/MyGame/Example2/__init__.py
diff --git a/tests/MyGame/InParentNamespace.cs b/tests/MyGame/InParentNamespace.cs
new file mode 100644
index 0000000..7b8ffc2
--- /dev/null
+++ b/tests/MyGame/InParentNamespace.cs
@@ -0,0 +1,29 @@
+// <auto-generated>
+//  automatically generated by the FlatBuffers compiler, do not modify
+// </auto-generated>
+
+namespace MyGame
+{
+
+using global::System;
+using global::FlatBuffers;
+
+public struct InParentNamespace : IFlatbufferObject
+{
+  private Table __p;
+  public ByteBuffer ByteBuffer { get { return __p.bb; } }
+  public static InParentNamespace GetRootAsInParentNamespace(ByteBuffer _bb) { return GetRootAsInParentNamespace(_bb, new InParentNamespace()); }
+  public static InParentNamespace GetRootAsInParentNamespace(ByteBuffer _bb, InParentNamespace obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+  public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
+  public InParentNamespace __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
+
+
+  public static void StartInParentNamespace(FlatBufferBuilder builder) { builder.StartObject(0); }
+  public static Offset<InParentNamespace> EndInParentNamespace(FlatBufferBuilder builder) {
+    int o = builder.EndObject();
+    return new Offset<InParentNamespace>(o);
+  }
+};
+
+
+}
diff --git a/tests/MyGame/InParentNamespace.go b/tests/MyGame/InParentNamespace.go
new file mode 100644
index 0000000..341b05c
--- /dev/null
+++ b/tests/MyGame/InParentNamespace.go
@@ -0,0 +1,34 @@
+// automatically generated by the FlatBuffers compiler, do not modify
+
+package MyGame
+
+import (
+	flatbuffers "github.com/google/flatbuffers/go"
+)
+
+type InParentNamespace struct {
+	_tab flatbuffers.Table
+}
+
+func GetRootAsInParentNamespace(buf []byte, offset flatbuffers.UOffsetT) *InParentNamespace {
+	n := flatbuffers.GetUOffsetT(buf[offset:])
+	x := &InParentNamespace{}
+	x.Init(buf, n+offset)
+	return x
+}
+
+func (rcv *InParentNamespace) Init(buf []byte, i flatbuffers.UOffsetT) {
+	rcv._tab.Bytes = buf
+	rcv._tab.Pos = i
+}
+
+func (rcv *InParentNamespace) Table() flatbuffers.Table {
+	return rcv._tab
+}
+
+func InParentNamespaceStart(builder *flatbuffers.Builder) {
+	builder.StartObject(0)
+}
+func InParentNamespaceEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
+	return builder.EndObject()
+}
diff --git a/tests/MyGame/InParentNamespace.java b/tests/MyGame/InParentNamespace.java
new file mode 100644
index 0000000..5ac27c2
--- /dev/null
+++ b/tests/MyGame/InParentNamespace.java
@@ -0,0 +1,24 @@
+// automatically generated by the FlatBuffers compiler, do not modify
+
+package MyGame;
+
+import java.nio.*;
+import java.lang.*;
+import java.util.*;
+import com.google.flatbuffers.*;
+
+@SuppressWarnings("unused")
+public final class InParentNamespace extends Table {
+  public static InParentNamespace getRootAsInParentNamespace(ByteBuffer _bb) { return getRootAsInParentNamespace(_bb, new InParentNamespace()); }
+  public static InParentNamespace getRootAsInParentNamespace(ByteBuffer _bb, InParentNamespace obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
+  public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
+  public InParentNamespace __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
+
+
+  public static void startInParentNamespace(FlatBufferBuilder builder) { builder.startObject(0); }
+  public static int endInParentNamespace(FlatBufferBuilder builder) {
+    int o = builder.endObject();
+    return o;
+  }
+}
+
diff --git a/tests/MyGame/InParentNamespace.php b/tests/MyGame/InParentNamespace.php
new file mode 100644
index 0000000..e13a4f3
--- /dev/null
+++ b/tests/MyGame/InParentNamespace.php
@@ -0,0 +1,79 @@
+<?php
+// automatically generated by the FlatBuffers compiler, do not modify
+
+namespace MyGame;
+
+use \Google\FlatBuffers\Struct;
+use \Google\FlatBuffers\Table;
+use \Google\FlatBuffers\ByteBuffer;
+use \Google\FlatBuffers\FlatBufferBuilder;
+
+class InParentNamespace extends Table
+{
+    /**
+     * @param ByteBuffer $bb
+     * @return InParentNamespace
+     */
+    public static function getRootAsInParentNamespace(ByteBuffer $bb)
+    {
+        $obj = new InParentNamespace();
+        return ($obj->init($bb->getInt($bb->getPosition()) + $bb->getPosition(), $bb));
+    }
+
+    public static function InParentNamespaceIdentifier()
+    {
+        return "MONS";
+    }
+
+    public static function InParentNamespaceBufferHasIdentifier(ByteBuffer $buf)
+    {
+        return self::__has_identifier($buf, self::InParentNamespaceIdentifier());
+    }
+
+    public static function InParentNamespaceExtension()
+    {
+        return "mon";
+    }
+
+    /**
+     * @param int $_i offset
+     * @param ByteBuffer $_bb
+     * @return InParentNamespace
+     **/
+    public function init($_i, ByteBuffer $_bb)
+    {
+        $this->bb_pos = $_i;
+        $this->bb = $_bb;
+        return $this;
+    }
+
+    /**
+     * @param FlatBufferBuilder $builder
+     * @return void
+     */
+    public static function startInParentNamespace(FlatBufferBuilder $builder)
+    {
+        $builder->StartObject(0);
+    }
+
+    /**
+     * @param FlatBufferBuilder $builder
+     * @return InParentNamespace
+     */
+    public static function createInParentNamespace(FlatBufferBuilder $builder, )
+    {
+        $builder->startObject(0);
+        $o = $builder->endObject();
+        return $o;
+    }
+
+    /**
+     * @param FlatBufferBuilder $builder
+     * @return int table offset
+     */
+    public static function endInParentNamespace(FlatBufferBuilder $builder)
+    {
+        $o = $builder->endObject();
+        return $o;
+    }
+}
diff --git a/tests/MyGame/InParentNamespace.py b/tests/MyGame/InParentNamespace.py
new file mode 100644
index 0000000..428d9a9
--- /dev/null
+++ b/tests/MyGame/InParentNamespace.py
@@ -0,0 +1,22 @@
+# automatically generated by the FlatBuffers compiler, do not modify
+
+# namespace: MyGame
+
+import flatbuffers
+
+class InParentNamespace(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAsInParentNamespace(cls, buf, offset):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = InParentNamespace()
+        x.Init(buf, n + offset)
+        return x
+
+    # InParentNamespace
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+def InParentNamespaceStart(builder): builder.StartObject(0)
+def InParentNamespaceEnd(builder): return builder.EndObject()
diff --git a/tests/monster_test.bfbs b/tests/monster_test.bfbs
index f7ae2a4..843e308 100644
--- a/tests/monster_test.bfbs
+++ b/tests/monster_test.bfbs
Binary files differ
diff --git a/tests/monster_test.fbs b/tests/monster_test.fbs
index 41cacef..53493a1 100755
--- a/tests/monster_test.fbs
+++ b/tests/monster_test.fbs
@@ -2,6 +2,10 @@
 
 include "include_test1.fbs";
 
+namespace MyGame;
+
+table InParentNamespace {}
+
 namespace MyGame.Example2;
 
 table Monster {}  // Test having same name as below, but in different namespace.
@@ -77,6 +81,7 @@
   flex:[ubyte] (id:30, flexbuffer);
   vector_of_longs:[long] (id:32);
   vector_of_doubles:[double] (id:33);
+  parent_namespace_test:InParentNamespace (id:34);
 }
 
 table TypeAliases {
diff --git a/tests/monster_test.schema.json b/tests/monster_test.schema.json
index 9af53bb..578e896 100644
--- a/tests/monster_test.schema.json
+++ b/tests/monster_test.schema.json
@@ -30,6 +30,11 @@
         "b" : { "$ref" : "#/definitions/MyGame_OtherNameSpace_TableB" }
       }
     },
+    "MyGame_InParentNamespace" : {
+      "type" : "object",
+      "properties" : {
+      }
+    },
     "MyGame_Example2_Monster" : {
       "type" : "object",
       "properties" : {
@@ -111,7 +116,8 @@
         "flex" : { "type" : "array", "items" : { "type" : "number" } },
         "test5" : { "type" : "array", "items" : { "$ref" : "#/definitions/MyGame_Example_Test" } },
         "vector_of_longs" : { "type" : "array", "items" : { "type" : "number" } },
-        "vector_of_doubles" : { "type" : "array", "items" : { "type" : "number" } }
+        "vector_of_doubles" : { "type" : "array", "items" : { "type" : "number" } },
+        "parent_namespace_test" : { "$ref" : "#/definitions/MyGame_InParentNamespace" }
       },
       "required" : [ "name"]
     },
diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h
index 3375cf6..3580cca 100644
--- a/tests/monster_test_generated.h
+++ b/tests/monster_test_generated.h
@@ -8,6 +8,10 @@
 #include "flatbuffers/flexbuffers.h"
 
 namespace MyGame {
+
+struct InParentNamespace;
+struct InParentNamespaceT;
+
 namespace Example2 {
 
 struct Monster;
@@ -317,6 +321,46 @@
 
 }  // namespace Example
 
+struct InParentNamespaceT : public flatbuffers::NativeTable {
+  typedef InParentNamespace TableType;
+  InParentNamespaceT() {
+  }
+};
+
+struct InParentNamespace FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+  typedef InParentNamespaceT NativeTableType;
+  bool Verify(flatbuffers::Verifier &verifier) const {
+    return VerifyTableStart(verifier) &&
+           verifier.EndTable();
+  }
+  InParentNamespaceT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(InParentNamespaceT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static flatbuffers::Offset<InParentNamespace> Pack(flatbuffers::FlatBufferBuilder &_fbb, const InParentNamespaceT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct InParentNamespaceBuilder {
+  flatbuffers::FlatBufferBuilder &fbb_;
+  flatbuffers::uoffset_t start_;
+  InParentNamespaceBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+        : fbb_(_fbb) {
+    start_ = fbb_.StartTable();
+  }
+  InParentNamespaceBuilder &operator=(const InParentNamespaceBuilder &);
+  flatbuffers::Offset<InParentNamespace> Finish() {
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<InParentNamespace>(end);
+    return o;
+  }
+};
+
+inline flatbuffers::Offset<InParentNamespace> CreateInParentNamespace(
+    flatbuffers::FlatBufferBuilder &_fbb) {
+  InParentNamespaceBuilder builder_(_fbb);
+  return builder_.Finish();
+}
+
+flatbuffers::Offset<InParentNamespace> CreateInParentNamespace(flatbuffers::FlatBufferBuilder &_fbb, const InParentNamespaceT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
 namespace Example2 {
 
 struct MonsterT : public flatbuffers::NativeTable {
@@ -553,6 +597,7 @@
   std::vector<Test> test5;
   std::vector<int64_t> vector_of_longs;
   std::vector<double> vector_of_doubles;
+  flatbuffers::unique_ptr<MyGame::InParentNamespaceT> parent_namespace_test;
   MonsterT()
       : mana(150),
         hp(100),
@@ -608,7 +653,8 @@
     VT_FLEX = 64,
     VT_TEST5 = 66,
     VT_VECTOR_OF_LONGS = 68,
-    VT_VECTOR_OF_DOUBLES = 70
+    VT_VECTOR_OF_DOUBLES = 70,
+    VT_PARENT_NAMESPACE_TEST = 72
   };
   const Vec3 *pos() const {
     return GetStruct<const Vec3 *>(VT_POS);
@@ -834,6 +880,12 @@
   flatbuffers::Vector<double> *mutable_vector_of_doubles() {
     return GetPointer<flatbuffers::Vector<double> *>(VT_VECTOR_OF_DOUBLES);
   }
+  const MyGame::InParentNamespace *parent_namespace_test() const {
+    return GetPointer<const MyGame::InParentNamespace *>(VT_PARENT_NAMESPACE_TEST);
+  }
+  MyGame::InParentNamespace *mutable_parent_namespace_test() {
+    return GetPointer<MyGame::InParentNamespace *>(VT_PARENT_NAMESPACE_TEST);
+  }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
            VerifyField<Vec3>(verifier, VT_POS) &&
@@ -888,6 +940,8 @@
            verifier.Verify(vector_of_longs()) &&
            VerifyOffset(verifier, VT_VECTOR_OF_DOUBLES) &&
            verifier.Verify(vector_of_doubles()) &&
+           VerifyOffset(verifier, VT_PARENT_NAMESPACE_TEST) &&
+           verifier.VerifyTable(parent_namespace_test()) &&
            verifier.EndTable();
   }
   MonsterT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
@@ -1009,6 +1063,9 @@
   void add_vector_of_doubles(flatbuffers::Offset<flatbuffers::Vector<double>> vector_of_doubles) {
     fbb_.AddOffset(Monster::VT_VECTOR_OF_DOUBLES, vector_of_doubles);
   }
+  void add_parent_namespace_test(flatbuffers::Offset<MyGame::InParentNamespace> parent_namespace_test) {
+    fbb_.AddOffset(Monster::VT_PARENT_NAMESPACE_TEST, parent_namespace_test);
+  }
   MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
@@ -1056,12 +1113,14 @@
     flatbuffers::Offset<flatbuffers::Vector<uint8_t>> flex = 0,
     flatbuffers::Offset<flatbuffers::Vector<const Test *>> test5 = 0,
     flatbuffers::Offset<flatbuffers::Vector<int64_t>> vector_of_longs = 0,
-    flatbuffers::Offset<flatbuffers::Vector<double>> vector_of_doubles = 0) {
+    flatbuffers::Offset<flatbuffers::Vector<double>> vector_of_doubles = 0,
+    flatbuffers::Offset<MyGame::InParentNamespace> parent_namespace_test = 0) {
   MonsterBuilder builder_(_fbb);
   builder_.add_testhashu64_fnv1a(testhashu64_fnv1a);
   builder_.add_testhashs64_fnv1a(testhashs64_fnv1a);
   builder_.add_testhashu64_fnv1(testhashu64_fnv1);
   builder_.add_testhashs64_fnv1(testhashs64_fnv1);
+  builder_.add_parent_namespace_test(parent_namespace_test);
   builder_.add_vector_of_doubles(vector_of_doubles);
   builder_.add_vector_of_longs(vector_of_longs);
   builder_.add_test5(test5);
@@ -1128,7 +1187,8 @@
     const std::vector<uint8_t> *flex = nullptr,
     const std::vector<const Test *> *test5 = nullptr,
     const std::vector<int64_t> *vector_of_longs = nullptr,
-    const std::vector<double> *vector_of_doubles = nullptr) {
+    const std::vector<double> *vector_of_doubles = nullptr,
+    flatbuffers::Offset<MyGame::InParentNamespace> parent_namespace_test = 0) {
   return MyGame::Example::CreateMonster(
       _fbb,
       pos,
@@ -1163,7 +1223,8 @@
       flex ? _fbb.CreateVector<uint8_t>(*flex) : 0,
       test5 ? _fbb.CreateVector<const Test *>(*test5) : 0,
       vector_of_longs ? _fbb.CreateVector<int64_t>(*vector_of_longs) : 0,
-      vector_of_doubles ? _fbb.CreateVector<double>(*vector_of_doubles) : 0);
+      vector_of_doubles ? _fbb.CreateVector<double>(*vector_of_doubles) : 0,
+      parent_namespace_test);
 }
 
 flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
@@ -1422,6 +1483,29 @@
 
 }  // namespace Example
 
+inline InParentNamespaceT *InParentNamespace::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
+  auto _o = new InParentNamespaceT();
+  UnPackTo(_o, _resolver);
+  return _o;
+}
+
+inline void InParentNamespace::UnPackTo(InParentNamespaceT *_o, const flatbuffers::resolver_function_t *_resolver) const {
+  (void)_o;
+  (void)_resolver;
+}
+
+inline flatbuffers::Offset<InParentNamespace> InParentNamespace::Pack(flatbuffers::FlatBufferBuilder &_fbb, const InParentNamespaceT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
+  return CreateInParentNamespace(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<InParentNamespace> CreateInParentNamespace(flatbuffers::FlatBufferBuilder &_fbb, const InParentNamespaceT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const InParentNamespaceT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
+  return MyGame::CreateInParentNamespace(
+      _fbb);
+}
+
 namespace Example2 {
 
 inline MonsterT *Monster::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
@@ -1551,6 +1635,7 @@
   { auto _e = test5(); if (_e) { _o->test5.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->test5[_i] = *_e->Get(_i); } } };
   { auto _e = vector_of_longs(); if (_e) { _o->vector_of_longs.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->vector_of_longs[_i] = _e->Get(_i); } } };
   { auto _e = vector_of_doubles(); if (_e) { _o->vector_of_doubles.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->vector_of_doubles[_i] = _e->Get(_i); } } };
+  { auto _e = parent_namespace_test(); if (_e) _o->parent_namespace_test = flatbuffers::unique_ptr<MyGame::InParentNamespaceT>(_e->UnPack(_resolver)); };
 }
 
 inline flatbuffers::Offset<Monster> Monster::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -1594,6 +1679,7 @@
   auto _test5 = _o->test5.size() ? _fbb.CreateVectorOfStructs(_o->test5) : 0;
   auto _vector_of_longs = _o->vector_of_longs.size() ? _fbb.CreateVector(_o->vector_of_longs) : 0;
   auto _vector_of_doubles = _o->vector_of_doubles.size() ? _fbb.CreateVector(_o->vector_of_doubles) : 0;
+  auto _parent_namespace_test = _o->parent_namespace_test ? CreateInParentNamespace(_fbb, _o->parent_namespace_test.get(), _rehasher) : 0;
   return MyGame::Example::CreateMonster(
       _fbb,
       _pos,
@@ -1628,7 +1714,8 @@
       _flex,
       _test5,
       _vector_of_longs,
-      _vector_of_doubles);
+      _vector_of_doubles,
+      _parent_namespace_test);
 }
 
 inline TypeAliasesT *TypeAliases::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
diff --git a/tests/monster_test_generated.js b/tests/monster_test_generated.js
index 4899c56..e073b79 100644
--- a/tests/monster_test_generated.js
+++ b/tests/monster_test_generated.js
@@ -46,6 +46,57 @@
 /**
  * @constructor
  */
+MyGame.InParentNamespace = function() {
+  /**
+   * @type {flatbuffers.ByteBuffer}
+   */
+  this.bb = null;
+
+  /**
+   * @type {number}
+   */
+  this.bb_pos = 0;
+};
+
+/**
+ * @param {number} i
+ * @param {flatbuffers.ByteBuffer} bb
+ * @returns {MyGame.InParentNamespace}
+ */
+MyGame.InParentNamespace.prototype.__init = function(i, bb) {
+  this.bb_pos = i;
+  this.bb = bb;
+  return this;
+};
+
+/**
+ * @param {flatbuffers.ByteBuffer} bb
+ * @param {MyGame.InParentNamespace=} obj
+ * @returns {MyGame.InParentNamespace}
+ */
+MyGame.InParentNamespace.getRootAsInParentNamespace = function(bb, obj) {
+  return (obj || new MyGame.InParentNamespace).__init(bb.readInt32(bb.position()) + bb.position(), bb);
+};
+
+/**
+ * @param {flatbuffers.Builder} builder
+ */
+MyGame.InParentNamespace.startInParentNamespace = function(builder) {
+  builder.startObject(0);
+};
+
+/**
+ * @param {flatbuffers.Builder} builder
+ * @returns {flatbuffers.Offset}
+ */
+MyGame.InParentNamespace.endInParentNamespace = function(builder) {
+  var offset = builder.endObject();
+  return offset;
+};
+
+/**
+ * @constructor
+ */
 MyGame.Example2.Monster = function() {
   /**
    * @type {flatbuffers.ByteBuffer}
@@ -1357,10 +1408,19 @@
 };
 
 /**
+ * @param {MyGame.InParentNamespace=} obj
+ * @returns {MyGame.InParentNamespace|null}
+ */
+MyGame.Example.Monster.prototype.parentNamespaceTest = function(obj) {
+  var offset = this.bb.__offset(this.bb_pos, 72);
+  return offset ? (obj || new MyGame.InParentNamespace).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null;
+};
+
+/**
  * @param {flatbuffers.Builder} builder
  */
 MyGame.Example.Monster.startMonster = function(builder) {
-  builder.startObject(34);
+  builder.startObject(35);
 };
 
 /**
@@ -1842,6 +1902,14 @@
 
 /**
  * @param {flatbuffers.Builder} builder
+ * @param {flatbuffers.Offset} parentNamespaceTestOffset
+ */
+MyGame.Example.Monster.addParentNamespaceTest = function(builder, parentNamespaceTestOffset) {
+  builder.addFieldOffset(34, parentNamespaceTestOffset, 0);
+};
+
+/**
+ * @param {flatbuffers.Builder} builder
  * @returns {flatbuffers.Offset}
  */
 MyGame.Example.Monster.endMonster = function(builder) {
diff --git a/tests/monster_test_generated.ts b/tests/monster_test_generated.ts
index b8938e1..fa4e963 100644
--- a/tests/monster_test_generated.ts
+++ b/tests/monster_test_generated.ts
@@ -24,6 +24,58 @@
 /**
  * @constructor
  */
+export namespace MyGame{
+export class InParentNamespace {
+  /**
+   * @type {flatbuffers.ByteBuffer}
+   */
+  bb: flatbuffers.ByteBuffer;
+
+  /**
+   * @type {number}
+   */
+  bb_pos:number = 0;
+/**
+ * @param {number} i
+ * @param {flatbuffers.ByteBuffer} bb
+ * @returns {InParentNamespace}
+ */
+__init(i:number, bb:flatbuffers.ByteBuffer):InParentNamespace {
+  this.bb_pos = i;
+  this.bb = bb;
+  return this;
+};
+
+/**
+ * @param {flatbuffers.ByteBuffer} bb
+ * @param {InParentNamespace=} obj
+ * @returns {InParentNamespace}
+ */
+static getRootAsInParentNamespace(bb:flatbuffers.ByteBuffer, obj?:InParentNamespace):InParentNamespace {
+  return (obj || new InParentNamespace).__init(bb.readInt32(bb.position()) + bb.position(), bb);
+};
+
+/**
+ * @param {flatbuffers.Builder} builder
+ */
+static startInParentNamespace(builder:flatbuffers.Builder) {
+  builder.startObject(0);
+};
+
+/**
+ * @param {flatbuffers.Builder} builder
+ * @returns {flatbuffers.Offset}
+ */
+static endInParentNamespace(builder:flatbuffers.Builder):flatbuffers.Offset {
+  var offset = builder.endObject();
+  return offset;
+};
+
+}
+}
+/**
+ * @constructor
+ */
 export namespace MyGame.Example2{
 export class Monster {
   /**
@@ -1348,10 +1400,19 @@
 };
 
 /**
+ * @param {MyGame.InParentNamespace=} obj
+ * @returns {MyGame.InParentNamespace|null}
+ */
+parentNamespaceTest(obj?:MyGame.InParentNamespace):MyGame.InParentNamespace|null {
+  var offset = this.bb.__offset(this.bb_pos, 72);
+  return offset ? (obj || new MyGame.InParentNamespace).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null;
+};
+
+/**
  * @param {flatbuffers.Builder} builder
  */
 static startMonster(builder:flatbuffers.Builder) {
-  builder.startObject(34);
+  builder.startObject(35);
 };
 
 /**
@@ -1833,6 +1894,14 @@
 
 /**
  * @param {flatbuffers.Builder} builder
+ * @param {flatbuffers.Offset} parentNamespaceTestOffset
+ */
+static addParentNamespaceTest(builder:flatbuffers.Builder, parentNamespaceTestOffset:flatbuffers.Offset) {
+  builder.addFieldOffset(34, parentNamespaceTestOffset, 0);
+};
+
+/**
+ * @param {flatbuffers.Builder} builder
  * @returns {flatbuffers.Offset}
  */
 static endMonster(builder:flatbuffers.Builder):flatbuffers.Offset {
diff --git a/tests/namespace_test/NamespaceC/__init__.py b/tests/namespace_test/NamespaceC/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/namespace_test/NamespaceC/__init__.py
diff --git a/tests/prototest/test.golden b/tests/prototest/test.golden
index fc70c1b..f814249 100644
--- a/tests/prototest/test.golden
+++ b/tests/prototest/test.golden
@@ -9,14 +9,10 @@
   BAR = 5,
 }
 
-namespace _proto._test;
-
 table ImportedMessage {
   a:int;
 }
 
-namespace _proto._test;
-
 /// 2nd table doc comment with
 /// many lines.
 table ProtoMessage {