THRIFT-3554 Constant decls may lead to "Error: internal error: prepare_member_name_mapping() already active for different struct"
Client: C#
Patch: Jens Geyer
diff --git a/compiler/cpp/src/generate/t_csharp_generator.cc b/compiler/cpp/src/generate/t_csharp_generator.cc
index aae595d..d9d2f79 100644
--- a/compiler/cpp/src/generate/t_csharp_generator.cc
+++ b/compiler/cpp/src/generate/t_csharp_generator.cc
@@ -45,6 +45,11 @@
static const string endl = "\n"; // avoid ostream << std::endl flushes
+struct member_mapping_scope {
+ void* scope_member;
+ std::map<std::string, std::string> mapping_table;
+};
+
class t_csharp_generator : public t_oop_generator {
public:
t_csharp_generator(t_program* program,
@@ -233,9 +238,7 @@
std::string wcf_namespace_;
std::map<std::string, int> csharp_keywords;
-
- void* member_mapping_scope;
- std::map<std::string, std::string> member_name_mapping;
+ std::vector<member_mapping_scope> member_mapping_scopes;
void init_keywords();
std::string normalize_name(std::string name);
@@ -268,7 +271,10 @@
namespace_dir_ = subdir;
init_keywords();
- member_mapping_scope = NULL;
+
+ while( ! member_mapping_scopes.empty()) {
+ cleanup_member_name_mapping( member_mapping_scopes.back().scope_member);
+ }
pverbose("C# options:\n");
pverbose("- async ...... %s\n", (async_ ? "ON" : "off"));
@@ -2856,23 +2862,27 @@
}
void t_csharp_generator::cleanup_member_name_mapping(void* scope) {
- if (member_mapping_scope != scope) {
- if (member_mapping_scope == NULL) {
- throw "internal error: cleanup_member_name_mapping() not active";
- } else {
- throw "internal error: cleanup_member_name_mapping() called for wrong struct";
- }
+ if( member_mapping_scopes.empty()) {
+ throw "internal error: cleanup_member_name_mapping() no scope active";
+ }
+
+ member_mapping_scope& active = member_mapping_scopes.back();
+ if (active.scope_member != scope) {
+ throw "internal error: cleanup_member_name_mapping() called for wrong struct";
}
- member_mapping_scope = NULL;
- member_name_mapping.clear();
+ member_mapping_scopes.pop_back();
}
string t_csharp_generator::get_mapped_member_name(string name) {
- map<string, string>::iterator iter = member_name_mapping.find(name);
- if (member_name_mapping.end() != iter) {
- return iter->second;
+ if( ! member_mapping_scopes.empty()) {
+ member_mapping_scope& active = member_mapping_scopes.back();
+ map<string, string>::iterator iter = active.mapping_table.find(name);
+ if (active.mapping_table.end() != iter) {
+ return iter->second;
+ }
}
+
pverbose("no mapping for member %s\n", name.c_str());
return name;
}
@@ -2884,23 +2894,16 @@
void t_csharp_generator::prepare_member_name_mapping(void* scope,
const vector<t_field*>& members,
const string& structname) {
- if (member_mapping_scope != NULL) {
- if (member_mapping_scope != scope) {
- throw "internal error: prepare_member_name_mapping() already active for different struct";
- } else {
- throw "internal error: prepare_member_name_mapping() already active for this struct";
- }
- }
-
- member_mapping_scope = scope;
- member_name_mapping.clear();
-
- std::set<std::string> used_member_names;
- vector<t_field*>::const_iterator iter;
+ // begin new scope
+ member_mapping_scopes.push_back({});
+ member_mapping_scope& active = member_mapping_scopes.back();
+ active.scope_member = scope;
// current C# generator policy:
// - prop names are always rendered with an Uppercase first letter
// - struct names are used as given
+ std::set<std::string> used_member_names;
+ vector<t_field*>::const_iterator iter;
// prevent name conflicts with struct (CS0542 error)
used_member_names.insert(structname);
@@ -2929,7 +2932,7 @@
structname.c_str(),
oldname.c_str(),
newname.c_str());
- member_name_mapping[oldname] = newname;
+ active.mapping_table[oldname] = newname;
used_member_names.insert(newname);
break;
}
@@ -3193,6 +3196,7 @@
return package + type->get_name();
}
+
THRIFT_REGISTER_GENERATOR(
csharp,
"C#",