THRIFT-5254 Member name cannot be Isset (unless it is an "required" member)
Client: netstd
Patch: Jens Geyer

This closes #2203
diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc
index fb8d65c..f1198e5 100644
--- a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc
@@ -990,7 +990,7 @@
                 {
                     out << indent() << "[DataMember]" << endl;
                 }
-                out << indent() << "public bool " << normalize_name((*m_iter)->get_name()) << ";" << endl;
+                out << indent() << "public bool " << get_isset_name(normalize_name((*m_iter)->get_name())) << ";" << endl;
             }
         }
 
@@ -1011,7 +1011,7 @@
                     out << indent() << "public bool ShouldSerialize" << prop_name(*m_iter) << "()" << endl
                         << indent() << "{" << endl;
                     indent_up();
-                    out << indent() << "return __isset." << normalize_name((*m_iter)->get_name()) << ";" << endl;
+                    out << indent() << "return __isset." << get_isset_name(normalize_name((*m_iter)->get_name())) << ";" << endl;
                     indent_down();
                     out << indent() << "}" << endl << endl;
                 }
@@ -1041,7 +1041,7 @@
             {
                 print_const_value(out, "this._" + (*m_iter)->get_name(), t, (*m_iter)->get_value(), true, true);
                 // Optionals with defaults are marked set
-                out << indent() << "this.__isset." << normalize_name((*m_iter)->get_name()) << " = true;" << endl;
+                out << indent() << "this.__isset." << get_isset_name(normalize_name((*m_iter)->get_name())) << " = true;" << endl;
             }
         }
     }
@@ -1184,8 +1184,8 @@
 
         generate_null_check_end( out, *m_iter);
         if( !is_required) {
-            out << indent() << tmp_instance << ".__isset." << normalize_name((*m_iter)->get_name())
-                 << " = this.__isset." << normalize_name((*m_iter)->get_name()) << ";" << endl;
+            out << indent() << tmp_instance << ".__isset." << get_isset_name(normalize_name((*m_iter)->get_name()))
+                 << " = this.__isset." << get_isset_name(normalize_name((*m_iter)->get_name())) << ";" << endl;
         }
     }
 
@@ -1317,7 +1317,7 @@
             if( !first) {
                 out << " && ";
             }
-            out << "__isset." << normalize_name(tfield->get_name());
+            out << "__isset." << get_isset_name(normalize_name(tfield->get_name()));
         }
         
         out << ")" << endl
@@ -1421,7 +1421,7 @@
                 out << indent() << "else if";
             }
 
-            out << "(this.__isset." << normalize_name((*f_iter)->get_name()) << ")" << endl
+            out << "(this.__isset." << get_isset_name(normalize_name((*f_iter)->get_name())) << ")" << endl
                 << indent() << "{" << endl;
             indent_up();
 
@@ -1802,9 +1802,9 @@
         }
         if (!field_is_required((*f_iter)))
         {
-            out << "((__isset." << normalize_name((*f_iter)->get_name()) << " == other.__isset."
-                << normalize_name((*f_iter)->get_name()) << ") && ((!__isset."
-                << normalize_name((*f_iter)->get_name()) << ") || (";
+            out << "((__isset." << get_isset_name(normalize_name((*f_iter)->get_name())) << " == other.__isset."
+                << get_isset_name(normalize_name((*f_iter)->get_name())) << ") && ((!__isset."
+                << get_isset_name(normalize_name((*f_iter)->get_name())) << ") || (";
         }
         t_type* ttype = (*f_iter)->get_type();
         if (ttype->is_container() || ttype->is_binary())
@@ -2082,7 +2082,7 @@
             vector<t_field*>::const_iterator x_iter;
             for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter)
             {
-                out << indent() << "if (result.__isset." << normalize_name((*x_iter)->get_name()) << ")" << endl
+                out << indent() << "if (result.__isset." << get_isset_name(normalize_name((*x_iter)->get_name())) << ")" << endl
                     << indent() << "{" << endl;
                 indent_up();
                 out << indent() << "throw result." << prop_name(*x_iter) << ";" << endl;
@@ -2910,7 +2910,7 @@
         {
             if (generateIsset)
             {
-                out << indent() << "__isset." << normalize_name(tfield->get_name()) << " = value.HasValue;" << endl;
+                out << indent() << "__isset." << get_isset_name(normalize_name(tfield->get_name())) << " = value.HasValue;" << endl;
             }
             out << indent() << "if (value.HasValue) this." << fieldPrefix + tfield->get_name() << " = value.Value;" << endl;
         }
@@ -2918,7 +2918,7 @@
         {
             if (generateIsset)
             {
-                out << indent() << "__isset." << normalize_name(tfield->get_name()) << " = true;" << endl;
+                out << indent() << "__isset." << get_isset_name(normalize_name(tfield->get_name())) << " = true;" << endl;
             }
             out << indent() << "this." << fieldPrefix + tfield->get_name() << " = value;" << endl;
         }
@@ -3068,6 +3068,11 @@
 }
 
 
+string t_netstd_generator::get_isset_name(const string& str) {
+  return ("Isset" != str) ? str : str + "_";
+}
+
+
 string t_netstd_generator::prop_name(t_field* tfield, bool suppress_mapping) {
   string name(tfield->get_name());
   if (suppress_mapping) {
diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.h b/compiler/cpp/src/thrift/generate/t_netstd_generator.h
index 94ad161..1217cc8 100644
--- a/compiler/cpp/src/thrift/generate/t_netstd_generator.h
+++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.h
@@ -166,6 +166,7 @@
   void prepare_member_name_mapping(void* scope, const vector<t_field*>& members, const string& structname);
   void cleanup_member_name_mapping(void* scope);
   string get_mapped_member_name(string oldname);
+  string get_isset_name(const string& str);
   string get_deep_copy_method_call(t_type* ttype, bool& needs_typecast);
   void collect_extensions_types(t_struct* tstruct);
   void collect_extensions_types(t_type* ttype);
diff --git a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5253.thrift b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5253.thrift
index bf77302..ee3df9b 100644
--- a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5253.thrift
+++ b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5253.thrift
@@ -32,14 +32,15 @@
 struct Client          { 1: optional i32 foo }
 struct IAsync          { 1: optional i32 foo }
 
+struct ReservedMemberName { 1: optional i32 Isset }
 
 service MyService{
     BrokenResult Broken( 1 : BrokenArgs  foo)
     WorksRslt     Works( 1 : WorksArrrgs foo)
 
-	InternalStructs InternalStructs( 1: InternalStructs foo)
-	AsyncProcessor  AsyncProcessor ( 1: AsyncProcessor  foo)
-	Client          Client         ( 1: Client  foo)
-	IAsync          IAsync         ( 1: IAsync  foo)
+    InternalStructs InternalStructs( 1: InternalStructs foo)
+    AsyncProcessor  AsyncProcessor ( 1: AsyncProcessor  foo)
+    Client          Client         ( 1: Client  foo)
+    IAsync          IAsync         ( 1: IAsync  foo)
 }