THRIFT-5138 Swift keywords may be used as identifiers if escaped
Client: Swift
Patch: Jano Svitok

This closes #2059
diff --git a/compiler/cpp/src/thrift/generate/t_generator.h b/compiler/cpp/src/thrift/generate/t_generator.h
index cb9d076..f82463d 100644
--- a/compiler/cpp/src/thrift/generate/t_generator.h
+++ b/compiler/cpp/src/thrift/generate/t_generator.h
@@ -42,8 +42,9 @@
  */
 class t_generator {
 public:
-  t_generator(t_program* program)
-    : keywords_(lang_keywords()){
+  t_generator(t_program* program) {
+    update_keywords();
+
     tmp_ = 0;
     indent_ = 0;
     program_ = program;
@@ -99,6 +100,7 @@
 
   /**
    * Check if all identifiers are valid for the target language
+   * See update_keywords()
    */
   virtual void validate_input() const;
 
@@ -106,9 +108,16 @@
   virtual std::set<std::string> lang_keywords() const;
 
   /**
+   * Call this from constructor if you implement lang_keywords()
+   */
+  void update_keywords() {
+    keywords_ = lang_keywords();
+  }
+
+  /**
    * A list of reserved words that cannot be used as identifiers.
    */
-  const std::set<std::string> keywords_;
+  std::set<std::string> keywords_;
 
   virtual void validate_id(const std::string& id) const;
 
diff --git a/compiler/cpp/src/thrift/generate/t_py_generator.cc b/compiler/cpp/src/thrift/generate/t_py_generator.cc
index e93bbe1..4be2fcc 100644
--- a/compiler/cpp/src/thrift/generate/t_py_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_py_generator.cc
@@ -52,6 +52,8 @@
                  const std::map<std::string, std::string>& parsed_options,
                  const std::string& option_string)
     : t_generator (program) {
+    update_keywords();
+
     std::map<std::string, std::string>::const_iterator iter;
 
     gen_newstyle_ = true;
diff --git a/compiler/cpp/src/thrift/generate/t_swift_generator.cc b/compiler/cpp/src/thrift/generate/t_swift_generator.cc
index f291ee4..91181f6 100644
--- a/compiler/cpp/src/thrift/generate/t_swift_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_swift_generator.cc
@@ -50,6 +50,8 @@
                     const map<string, string>& parsed_options,
                     const string& option_string)
     : t_oop_generator(program) {
+    update_keywords();
+	
     (void)option_string;
     map<string, string>::const_iterator iter;
 
@@ -288,6 +290,10 @@
   bool gen_cocoa_;
   bool promise_kit_;
 
+protected:
+  std::set<std::string> lang_keywords() const override {
+	  return {};
+  }
 };
 
 /**
@@ -1210,7 +1216,7 @@
         if (field_is_optional(*f_iter)) {
           continue;
         }
-        indent(out) << "try proto.validateValue(" << (*f_iter)->get_name() << ", "
+        indent(out) << "try proto.validateValue(" << maybe_escape_identifier((*f_iter)->get_name()) << ", "
                     << "named: \"" << (*f_iter)->get_name() << "\")" << endl;
       }
     }
diff --git a/compiler/cpp/test/CMakeLists.txt b/compiler/cpp/test/CMakeLists.txt
index 4ce1e49..b80f060 100644
--- a/compiler/cpp/test/CMakeLists.txt
+++ b/compiler/cpp/test/CMakeLists.txt
@@ -18,7 +18,9 @@
 #
 
 file(GLOB KEYWORD_SAMPLES "${CMAKE_CURRENT_SOURCE_DIR}/keyword-samples/*.thrift")
-foreach(LANG ${thrift_compiler_LANGS})
+set(KEYWORD_LANGS ${thrift_compiler_LANGS})
+LIST(REMOVE_ITEM KEYWORD_LANGS swift) # in Swift you can escape reserved words
+foreach(LANG ${KEYWORD_LANGS})
     foreach(SAMPLE ${KEYWORD_SAMPLES})
         get_filename_component(FILENAME ${SAMPLE} NAME_WE)
         add_test(NAME "${LANG}_${FILENAME}"