THRIFT-5302 Add recursive function name uniqueness check
Patch: wangliming07 <wangliming07@58.com>

This closes #2268
diff --git a/compiler/cpp/src/thrift/parse/t_program.h b/compiler/cpp/src/thrift/parse/t_program.h
index 140dc35..b6b1332 100644
--- a/compiler/cpp/src/thrift/parse/t_program.h
+++ b/compiler/cpp/src/thrift/parse/t_program.h
@@ -112,7 +112,10 @@
     objects_.push_back(tx);
     xceptions_.push_back(tx);
   }
-  void add_service(t_service* ts) { services_.push_back(ts); }
+  void add_service(t_service* ts) {
+    ts->validate_unique_members();
+    services_.push_back(ts);
+  }
 
   // Programs to include
   std::vector<t_program*>& get_includes() { return includes_; }
diff --git a/compiler/cpp/src/thrift/parse/t_service.h b/compiler/cpp/src/thrift/parse/t_service.h
index a43a515..f405c15 100644
--- a/compiler/cpp/src/thrift/parse/t_service.h
+++ b/compiler/cpp/src/thrift/parse/t_service.h
@@ -38,15 +38,58 @@
   void set_extends(t_service* extends) { extends_ = extends; }
 
   void add_function(t_function* func) {
-    std::vector<t_function*>::const_iterator iter;
-    for (iter = functions_.begin(); iter != functions_.end(); ++iter) {
-      if (func->get_name() == (*iter)->get_name()) {
-        throw "Function " + func->get_name() + " is already defined";
-      }
+    if (get_function_by_name(func->get_name()) != NULL) {
+      throw "Function " + func->get_name() + " is already defined";
     }
     functions_.push_back(func);
   }
 
+  void validate_unique_members() {
+    std::vector<t_function*>::const_iterator iter;
+    for (iter = functions_.begin(); iter != functions_.end(); ++iter) {
+      // throw exception when there is a conflict of names with super class
+      if (extends_ != NULL) {
+        if (extends_->get_function_by_name((*iter)->get_name()) != NULL) {
+          throw "Function " + (*iter)->get_name() + " is already defined in service " + name_;
+        }
+      }
+    }
+  }
+
+  t_function* get_function_by_name(std::string func_name) {
+    if (extends_ != NULL) {
+      t_function* func = NULL;
+      if ((func = extends_->get_function_by_name(func_name)) != NULL) {
+        return func;
+      }
+    }
+
+    std::vector<t_function*>::const_iterator iter;
+    for (iter = functions_.begin(); iter != functions_.end(); ++iter) {
+      if ((*iter)->get_name() == func_name) {
+        return *iter;
+      }
+    }
+    return NULL;
+  }
+
+  const t_function* get_function_by_name(std::string func_name) const {
+    if (extends_ != NULL) {
+      t_function* func = NULL;
+      if ((func = extends_->get_function_by_name(func_name)) != NULL) {
+        return func;
+      }
+    }
+
+    std::vector<t_function*>::const_iterator iter;
+    for (iter = functions_.begin(); iter != functions_.end(); ++iter) {
+      if ((*iter)->get_name() == func_name) {
+        return *iter;
+      }
+    }
+    return NULL;
+  }
+
   const std::vector<t_function*>& get_functions() const { return functions_; }
 
   t_service* get_extends() { return extends_; }