Browse Source

Merge branch 'master' into internal-merge

Josh Haberman 9 năm trước cách đây
mục cha
commit
4465daa57a
42 tập tin đã thay đổi với 371 bổ sung124 xóa
  1. 12 2
      BUILD
  2. 1 0
      cmake/extract_includes.bat.in
  3. 8 0
      objectivec/DevTools/full_mac_build.sh
  4. 4 3
      objectivec/GPBCodedInputStream.m
  5. 43 6
      objectivec/Tests/GPBCodedInputStreamTests.m
  6. 1 0
      src/Makefile.am
  7. 2 2
      src/google/protobuf/compiler/csharp/csharp_enum.cc
  8. 1 1
      src/google/protobuf/compiler/csharp/csharp_enum.h
  9. 6 5
      src/google/protobuf/compiler/csharp/csharp_enum_field.cc
  10. 6 2
      src/google/protobuf/compiler/csharp/csharp_enum_field.h
  11. 8 6
      src/google/protobuf/compiler/csharp/csharp_field_base.cc
  12. 3 1
      src/google/protobuf/compiler/csharp/csharp_field_base.h
  13. 16 10
      src/google/protobuf/compiler/csharp/csharp_generator.cc
  14. 17 14
      src/google/protobuf/compiler/csharp/csharp_helpers.cc
  15. 12 7
      src/google/protobuf/compiler/csharp/csharp_helpers.h
  16. 7 4
      src/google/protobuf/compiler/csharp/csharp_map_field.cc
  17. 3 1
      src/google/protobuf/compiler/csharp/csharp_map_field.h
  18. 13 8
      src/google/protobuf/compiler/csharp/csharp_message.cc
  19. 1 1
      src/google/protobuf/compiler/csharp/csharp_message.h
  20. 9 5
      src/google/protobuf/compiler/csharp/csharp_message_field.cc
  21. 6 2
      src/google/protobuf/compiler/csharp/csharp_message_field.h
  22. 75 0
      src/google/protobuf/compiler/csharp/csharp_options.h
  23. 5 4
      src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
  24. 8 2
      src/google/protobuf/compiler/csharp/csharp_primitive_field.h
  25. 6 4
      src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
  26. 4 2
      src/google/protobuf/compiler/csharp/csharp_reflection_class.h
  27. 2 2
      src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
  28. 3 1
      src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
  29. 6 4
      src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
  30. 5 1
      src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
  31. 2 2
      src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
  32. 1 1
      src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
  33. 9 2
      src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
  34. 5 1
      src/google/protobuf/compiler/csharp/csharp_source_generator_base.h
  35. 6 5
      src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
  36. 8 2
      src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
  37. 4 2
      src/google/protobuf/compiler/objectivec/objectivec_enum.cc
  38. 9 8
      src/google/protobuf/compiler/objectivec/objectivec_field.cc
  39. 10 0
      src/google/protobuf/compiler/objectivec/objectivec_file.cc
  40. 16 0
      src/google/protobuf/compiler/objectivec/objectivec_helpers.h
  41. 2 1
      src/google/protobuf/compiler/objectivec/objectivec_message.cc
  42. 6 0
      src/google/protobuf/dynamic_message.cc

+ 12 - 2
BUILD

@@ -15,8 +15,18 @@ COPTS = [
     "-Wno-error=unused-function",
 ]
 
-# Bazel should provide portable link_opts for pthread.
-LINK_OPTS = ["-lpthread"]
+config_setting(
+    name = "android",
+    values = {
+        "crosstool_top": "//external:android/crosstool",
+    },
+)
+
+# Android builds do not need to link in a separate pthread library.
+LINK_OPTS = select({
+    ":android": [],
+    "//conditions:default": ["-lpthread"],
+})
 
 load(
     "protobuf",

+ 1 - 0
cmake/extract_includes.bat.in

@@ -23,6 +23,7 @@ copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\command_line_
 copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\cpp_generator.h include\google\protobuf\compiler\cpp\cpp_generator.h
 copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_generator.h include\google\protobuf\compiler\csharp\csharp_generator.h
 copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_names.h include\google\protobuf\compiler\csharp\csharp_names.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_options.h include\google\protobuf\compiler\csharp\csharp_options.h
 copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\importer.h include\google\protobuf\compiler\importer.h
 copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_generator.h include\google\protobuf\compiler\java\java_generator.h
 copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_names.h include\google\protobuf\compiler\java\java_names.h

+ 8 - 0
objectivec/DevTools/full_mac_build.sh

@@ -242,6 +242,14 @@ if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then
           -destination "platform=iOS Simulator,name=iPad Air,OS=9.0" # 64bit
       )
       ;;
+    7.3* )
+      XCODEBUILD_TEST_BASE_IOS+=(
+          -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit
+          -destination "platform=iOS Simulator,name=iPhone 6,OS=9.3" # 64bit
+          -destination "platform=iOS Simulator,name=iPad 2,OS=8.1" # 32bit
+          -destination "platform=iOS Simulator,name=iPad Air,OS=9.3" # 64bit
+      )
+      ;;
     7.* )
       XCODEBUILD_TEST_BASE_IOS+=(
           -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit

+ 4 - 3
objectivec/GPBCodedInputStream.m

@@ -219,15 +219,16 @@ NSString *GPBCodedInputStreamReadRetainedString(
     result = [[NSString alloc] initWithBytes:&state->bytes[state->bufferPos]
                                       length:size
                                     encoding:NSUTF8StringEncoding];
+    state->bufferPos += size;
     if (!result) {
-      result = @"";
 #ifdef DEBUG
       // https://developers.google.com/protocol-buffers/docs/proto#scalar
-      NSLog(@"UTF8 failure, is some field type 'string' when it should be "
+      NSLog(@"UTF-8 failure, is some field type 'string' when it should be "
             @"'bytes'?");
 #endif
+      [NSException raise:NSParseErrorException
+                  format:@"Invalid UTF-8 for a 'string'"];
     }
-    state->bufferPos += size;
   }
   return result;
 }

+ 43 - 6
objectivec/Tests/GPBCodedInputStreamTests.m

@@ -283,16 +283,53 @@
   [output writeRawData:[NSData dataWithBytes:bytes length:sizeof(bytes)]];
   [output flush];
 
-  NSData* data =
+  NSData *data =
       [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
   GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+  NSError *error = nil;
   TestAllTypes* message = [TestAllTypes parseFromCodedInputStream:input
                                                 extensionRegistry:nil
-                                                            error:NULL];
-  XCTAssertNotNil(message);
-  // Make sure we can read string properties twice without crashing.
-  XCTAssertEqual([message.defaultString length], (NSUInteger)0);
-  XCTAssertEqualObjects(@"", message.defaultString);
+                                                            error:&error];
+  XCTAssertNotNil(error);
+  XCTAssertNil(message);
+}
+
+- (void)testBOMWithinStrings {
+  // We've seen servers that end up with BOMs within strings (not always at the
+  // start, and sometimes in multiple places), make sure they always parse
+  // correctly. (Again, this is inpart incase a custom string class is ever
+  // used again.)
+  const char* strs[] = {
+    "\xEF\xBB\xBF String with BOM",
+    "String with \xEF\xBB\xBF in middle",
+    "String with end bom \xEF\xBB\xBF",
+    "\xEF\xBB\xBF\xe2\x99\xa1",  // BOM White Heart
+    "\xEF\xBB\xBF\xEF\xBB\xBF String with Two BOM",
+  };
+  for (size_t i = 0; i < GPBARRAYSIZE(strs); ++i) {
+    NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+    GPBCodedOutputStream* output =
+        [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+
+    int32_t tag = GPBWireFormatMakeTag(TestAllTypes_FieldNumber_DefaultString,
+                                       GPBWireFormatLengthDelimited);
+    [output writeRawVarint32:tag];
+    size_t length = strlen(strs[i]);
+    [output writeRawVarint32:(int32_t)length];
+    [output writeRawData:[NSData dataWithBytes:strs[i] length:length]];
+    [output flush];
+
+    NSData* data =
+        [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+    TestAllTypes* message = [TestAllTypes parseFromCodedInputStream:input
+                                                  extensionRegistry:nil
+                                                              error:NULL];
+    XCTAssertNotNil(message, @"Loop %zd", i);
+    // Ensure the string is there. NSString can consume the BOM in some
+    // cases, so don't actually check the string for exact equality.
+    XCTAssertTrue(message.defaultString.length > 0, @"Loop %zd", i);
+  }
 }
 
 @end

+ 1 - 0
src/Makefile.am

@@ -455,6 +455,7 @@ libprotoc_la_SOURCES =                                         \
   google/protobuf/compiler/csharp/csharp_message.h             \
   google/protobuf/compiler/csharp/csharp_message_field.cc      \
   google/protobuf/compiler/csharp/csharp_message_field.h       \
+  google/protobuf/compiler/csharp/csharp_options.h             \
   google/protobuf/compiler/csharp/csharp_primitive_field.cc    \
   google/protobuf/compiler/csharp/csharp_primitive_field.h     \
   google/protobuf/compiler/csharp/csharp_reflection_class.cc     \

+ 2 - 2
src/google/protobuf/compiler/csharp/csharp_enum.cc

@@ -49,8 +49,8 @@ namespace protobuf {
 namespace compiler {
 namespace csharp {
 
-EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) :
-    SourceGeneratorBase(descriptor->file()),
+EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Options* options) :
+    SourceGeneratorBase(descriptor->file(), options),
     descriptor_(descriptor) {
 }
 

+ 1 - 1
src/google/protobuf/compiler/csharp/csharp_enum.h

@@ -43,7 +43,7 @@ namespace csharp {
 
 class EnumGenerator : public SourceGeneratorBase {
  public:
-  EnumGenerator(const EnumDescriptor* descriptor);
+  EnumGenerator(const EnumDescriptor* descriptor, const Options* options);
   ~EnumGenerator();
 
   void Generate(io::Printer* printer);

+ 6 - 5
src/google/protobuf/compiler/csharp/csharp_enum_field.cc

@@ -38,6 +38,7 @@
 #include <google/protobuf/io/zero_copy_stream.h>
 
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
 #include <google/protobuf/compiler/csharp/csharp_enum_field.h>
 
 namespace google {
@@ -46,8 +47,8 @@ namespace compiler {
 namespace csharp {
 
 EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
-                                       int fieldOrdinal)
-    : PrimitiveFieldGenerator(descriptor, fieldOrdinal) {
+                                       int fieldOrdinal, const Options *options)
+    : PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) {
 }
 
 EnumFieldGenerator::~EnumFieldGenerator() {
@@ -80,9 +81,9 @@ void EnumFieldGenerator::GenerateCodecCode(io::Printer* printer) {
         "pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x)");
 }
 
-EnumOneofFieldGenerator::EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
-						 int fieldOrdinal)
-  : PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal) {
+EnumOneofFieldGenerator::EnumOneofFieldGenerator(
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+  : PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options) {
 }
 
 EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {

+ 6 - 2
src/google/protobuf/compiler/csharp/csharp_enum_field.h

@@ -43,7 +43,9 @@ namespace csharp {
 
 class EnumFieldGenerator : public PrimitiveFieldGenerator {
  public:
-  EnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  EnumFieldGenerator(const FieldDescriptor* descriptor,
+                     int fieldOrdinal,
+                     const Options *options);
   ~EnumFieldGenerator();
 
   virtual void GenerateCodecCode(io::Printer* printer);
@@ -57,7 +59,9 @@ class EnumFieldGenerator : public PrimitiveFieldGenerator {
 
 class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator {
  public:
-  EnumOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
+                          int fieldOrdinal,
+                          const Options *options);
   ~EnumOneofFieldGenerator();
 
   virtual void GenerateParsingCode(io::Printer* printer);

+ 8 - 6
src/google/protobuf/compiler/csharp/csharp_field_base.cc

@@ -94,14 +94,15 @@ void FieldGeneratorBase::SetCommonFieldVariables(
 void FieldGeneratorBase::SetCommonOneofFieldVariables(
     map<string, string>* variables) {
   (*variables)["oneof_name"] = oneof_name();
-  (*variables)["has_property_check"] = oneof_name() + "Case_ == " + oneof_property_name() +
+  (*variables)["has_property_check"] =
+    oneof_name() + "Case_ == " + oneof_property_name() +
     "OneofCase." + property_name();
   (*variables)["oneof_property_name"] = oneof_property_name();
 }
 
 FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor,
-                                       int fieldOrdinal)
-    : SourceGeneratorBase(descriptor->file()),
+                                       int fieldOrdinal, const Options* options)
+    : SourceGeneratorBase(descriptor->file(), options),
       descriptor_(descriptor),
       fieldOrdinal_(fieldOrdinal) {
   SetCommonFieldVariables(&variables_);
@@ -158,10 +159,11 @@ std::string FieldGeneratorBase::type_name(const FieldDescriptor* descriptor) {
     case FieldDescriptor::TYPE_MESSAGE:
     case FieldDescriptor::TYPE_GROUP:
       if (IsWrapperType(descriptor)) {
-        const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
+        const FieldDescriptor* wrapped_field =
+            descriptor->message_type()->field(0);
         string wrapped_field_type_name = type_name(wrapped_field);
-        // String and ByteString go to the same type; other wrapped types go to the
-        // nullable equivalent.
+        // String and ByteString go to the same type; other wrapped types
+        // go to the nullable equivalent.
         if (wrapped_field->type() == FieldDescriptor::TYPE_STRING ||
             wrapped_field->type() == FieldDescriptor::TYPE_BYTES) {
           return wrapped_field_type_name;

+ 3 - 1
src/google/protobuf/compiler/csharp/csharp_field_base.h

@@ -44,7 +44,9 @@ namespace csharp {
 
 class FieldGeneratorBase : public SourceGeneratorBase {
  public:
-  FieldGeneratorBase(const FieldDescriptor* descriptor, int fieldOrdinal);
+  FieldGeneratorBase(const FieldDescriptor* descriptor,
+                     int fieldOrdinal,
+                     const Options* options);
   ~FieldGeneratorBase();
 
   virtual void GenerateCloningCode(io::Printer* printer) = 0;

+ 16 - 10
src/google/protobuf/compiler/csharp/csharp_generator.cc

@@ -41,6 +41,7 @@
 #include <google/protobuf/compiler/csharp/csharp_generator.h>
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
 #include <google/protobuf/compiler/csharp/csharp_names.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
 #include <google/protobuf/compiler/csharp/csharp_reflection_class.h>
 
 using google::protobuf::internal::scoped_ptr;
@@ -51,8 +52,9 @@ namespace compiler {
 namespace csharp {
 
 void GenerateFile(const google::protobuf::FileDescriptor* file,
-                  io::Printer* printer) {
-  ReflectionClassGenerator reflectionClassGenerator(file);
+                  io::Printer* printer,
+                  const Options* options) {
+  ReflectionClassGenerator reflectionClassGenerator(file, options);
   reflectionClassGenerator.Generate(printer);
 }
 
@@ -71,15 +73,14 @@ bool Generator::Generate(
     return false;
   }
 
-  std::string file_extension = ".cs";
-  std::string base_namespace = "";
-  bool generate_directories = false;
+  struct Options cli_options;
+
   for (int i = 0; i < options.size(); i++) {
     if (options[i].first == "file_extension") {
-      file_extension = options[i].second;
+      cli_options.file_extension = options[i].second;
     } else if (options[i].first == "base_namespace") {
-      base_namespace = options[i].second;
-      generate_directories = true;
+      cli_options.base_namespace = options[i].second;
+      cli_options.base_namespace_specified = true;
     } else {
       *error = "Unknown generator option: " + options[i].first;
       return false;
@@ -87,7 +88,12 @@ bool Generator::Generate(
   }
 
   string filename_error = "";
-  std::string filename = GetOutputFile(file, file_extension, generate_directories, base_namespace, &filename_error);
+  std::string filename = GetOutputFile(file,
+      cli_options.file_extension,
+      cli_options.base_namespace_specified,
+      cli_options.base_namespace,
+      &filename_error);
+
   if (filename.empty()) {
     *error = filename_error;
     return false;
@@ -96,7 +102,7 @@ bool Generator::Generate(
       generator_context->Open(filename));
   io::Printer printer(output.get(), '$');
 
-  GenerateFile(file, &printer);
+  GenerateFile(file, &printer, &cli_options);
 
   return true;
 }

+ 17 - 14
src/google/protobuf/compiler/csharp/csharp_helpers.cc

@@ -48,6 +48,7 @@
 #include <google/protobuf/compiler/csharp/csharp_enum_field.h>
 #include <google/protobuf/compiler/csharp/csharp_map_field.h>
 #include <google/protobuf/compiler/csharp/csharp_message_field.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
 #include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
 #include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h>
 #include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h>
@@ -127,7 +128,8 @@ std::string GetFileNameBase(const FileDescriptor* descriptor) {
 }
 
 std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor) {
-  // TODO: Detect collisions with existing messages, and append an underscore if necessary.
+  // TODO: Detect collisions with existing messages,
+  // and append an underscore if necessary.
   return GetFileNameBase(descriptor) + "Reflection";
 }
 
@@ -351,49 +353,50 @@ std::string FileDescriptorToBase64(const FileDescriptor* descriptor) {
 }
 
 FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
-                                         int fieldOrdinal) {
+                                         int fieldOrdinal,
+                                         const Options* options) {
   switch (descriptor->type()) {
     case FieldDescriptor::TYPE_GROUP:
     case FieldDescriptor::TYPE_MESSAGE:
       if (descriptor->is_repeated()) {
         if (descriptor->is_map()) {
-          return new MapFieldGenerator(descriptor, fieldOrdinal);
+          return new MapFieldGenerator(descriptor, fieldOrdinal, options);
         } else {
-          return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal);
+          return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal, options);
         }
       } else {
         if (IsWrapperType(descriptor)) {
           if (descriptor->containing_oneof()) {
-            return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal);
+            return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal, options);
           } else {
-            return new WrapperFieldGenerator(descriptor, fieldOrdinal);
+            return new WrapperFieldGenerator(descriptor, fieldOrdinal, options);
           }
         } else {
           if (descriptor->containing_oneof()) {
-            return new MessageOneofFieldGenerator(descriptor, fieldOrdinal);
+            return new MessageOneofFieldGenerator(descriptor, fieldOrdinal, options);
           } else {
-            return new MessageFieldGenerator(descriptor, fieldOrdinal);
+            return new MessageFieldGenerator(descriptor, fieldOrdinal, options);
           }
         }
       }
     case FieldDescriptor::TYPE_ENUM:
       if (descriptor->is_repeated()) {
-        return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal);
+        return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal, options);
       } else {
         if (descriptor->containing_oneof()) {
-          return new EnumOneofFieldGenerator(descriptor, fieldOrdinal);
+          return new EnumOneofFieldGenerator(descriptor, fieldOrdinal, options);
         } else {
-          return new EnumFieldGenerator(descriptor, fieldOrdinal);
+          return new EnumFieldGenerator(descriptor, fieldOrdinal, options);
         }
       }
     default:
       if (descriptor->is_repeated()) {
-        return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal);
+        return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal, options);
       } else {
         if (descriptor->containing_oneof()) {
-          return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal);
+          return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options);
         } else {
-          return new PrimitiveFieldGenerator(descriptor, fieldOrdinal);
+          return new PrimitiveFieldGenerator(descriptor, fieldOrdinal, options);
         }
       }
   }

+ 12 - 7
src/google/protobuf/compiler/csharp/csharp_helpers.h

@@ -46,6 +46,7 @@ namespace protobuf {
 namespace compiler {
 namespace csharp {
 
+struct Options;
 class FieldGeneratorBase;
 
 // TODO: start using this enum.
@@ -82,7 +83,9 @@ std::string GetPropertyName(const FieldDescriptor* descriptor);
 
 int GetFixedSize(FieldDescriptor::Type type);
 
-std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter, bool preserve_period);
+std::string UnderscoresToCamelCase(const std::string& input,
+                                   bool cap_next_letter,
+                                   bool preserve_period);
 
 inline std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter) {
   return UnderscoresToCamelCase(input, cap_next_letter, false);
@@ -95,17 +98,19 @@ std::string StringToBase64(const std::string& input);
 
 std::string FileDescriptorToBase64(const FileDescriptor* descriptor);
 
-FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
+                                         int fieldOrdinal,
+                                         const Options* options);
 
-// Determines whether the given message is a map entry message, i.e. one implicitly created
-// by protoc due to a map<key, value> field.
+// Determines whether the given message is a map entry message,
+// i.e. one implicitly created by protoc due to a map<key, value> field.
 inline bool IsMapEntryMessage(const Descriptor* descriptor) {
   return descriptor->options().map_entry();
 }
 
-// Determines whether we're generating code for the proto representation of descriptors etc,
-// for use in the runtime. This is the only type which is allowed to use proto2 syntax,
-// and it generates internal classes.
+// Determines whether we're generating code for the proto representation of
+// descriptors etc, for use in the runtime. This is the only type which is
+// allowed to use proto2 syntax, and it generates internal classes.
 inline bool IsDescriptorProto(const FileDescriptor* descriptor) {
   return descriptor->name() == "google/protobuf/descriptor.proto";
 }

+ 7 - 4
src/google/protobuf/compiler/csharp/csharp_map_field.cc

@@ -48,8 +48,9 @@ namespace compiler {
 namespace csharp {
 
 MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
-                                             int fieldOrdinal)
-    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+                                     int fieldOrdinal,
+                                     const Options* options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
 }
 
 MapFieldGenerator::~MapFieldGenerator() {
@@ -62,8 +63,10 @@ void MapFieldGenerator::GenerateMembers(io::Printer* printer) {
       descriptor_->message_type()->FindFieldByName("value");
   variables_["key_type_name"] = type_name(key_descriptor);
   variables_["value_type_name"] = type_name(value_descriptor);
-  scoped_ptr<FieldGeneratorBase> key_generator(CreateFieldGenerator(key_descriptor, 1));  
-  scoped_ptr<FieldGeneratorBase> value_generator(CreateFieldGenerator(value_descriptor, 2));
+  scoped_ptr<FieldGeneratorBase> key_generator(
+      CreateFieldGenerator(key_descriptor, 1, this->options()));
+  scoped_ptr<FieldGeneratorBase> value_generator(
+      CreateFieldGenerator(value_descriptor, 2, this->options()));
 
   printer->Print(
     variables_,

+ 3 - 1
src/google/protobuf/compiler/csharp/csharp_map_field.h

@@ -43,7 +43,9 @@ namespace csharp {
 
 class MapFieldGenerator : public FieldGeneratorBase {
  public:
-  MapFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  MapFieldGenerator(const FieldDescriptor* descriptor,
+                    int fieldOrdinal,
+                    const Options* options);
   ~MapFieldGenerator();
 
   virtual void GenerateCloningCode(io::Printer* printer);

+ 13 - 8
src/google/protobuf/compiler/csharp/csharp_message.cc

@@ -60,8 +60,9 @@ bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) {
   return d1->number() < d2->number();
 }
 
-MessageGenerator::MessageGenerator(const Descriptor* descriptor)
-    : SourceGeneratorBase(descriptor->file()),
+MessageGenerator::MessageGenerator(const Descriptor* descriptor,
+                                   const Options* options)
+    : SourceGeneratorBase(descriptor->file(), options),
       descriptor_(descriptor) {
 
   // sorted field names
@@ -185,7 +186,8 @@ void MessageGenerator::Generate(io::Printer* printer) {
     }
     printer->Outdent();
     printer->Print("}\n");
-    // TODO: Should we put the oneof .proto comments here? It's unclear exactly where they should go.
+    // TODO: Should we put the oneof .proto comments here?
+    // It's unclear exactly where they should go.
     printer->Print(
       vars,
       "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n"
@@ -214,13 +216,14 @@ void MessageGenerator::Generate(io::Printer* printer) {
     printer->Print("public static partial class Types {\n");
     printer->Indent();
     for (int i = 0; i < descriptor_->enum_type_count(); i++) {
-      EnumGenerator enumGenerator(descriptor_->enum_type(i));
+      EnumGenerator enumGenerator(descriptor_->enum_type(i), this->options());
       enumGenerator.Generate(printer);
     }
     for (int i = 0; i < descriptor_->nested_type_count(); i++) {
       // Don't generate nested types for maps...
       if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
-        MessageGenerator messageGenerator(descriptor_->nested_type(i));
+        MessageGenerator messageGenerator(
+            descriptor_->nested_type(i), this->options());
         messageGenerator.Generate(printer);
       }
     }
@@ -268,7 +271,8 @@ void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
   // Clone just the right field for each oneof
   for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
     vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
-    vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
+    vars["property_name"] = UnderscoresToCamelCase(
+        descriptor_->oneof_decl(i)->name(), true);
     printer->Print(vars, "switch (other.$property_name$Case) {\n");
     printer->Indent();
     for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
@@ -449,7 +453,8 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
     uint32 tag = internal::WireFormatLite::MakeTag(field->number(), wt);
     // Handle both packed and unpacked repeated fields with the same Read*Array call;
     // the two generated cases are the packed and unpacked tags.
-    // TODO(jonskeet): Check that is_packable is equivalent to is_repeated && wt in { VARINT, FIXED32, FIXED64 }.
+    // TODO(jonskeet): Check that is_packable is equivalent to
+    // is_repeated && wt in { VARINT, FIXED32, FIXED64 }.
     // It looks like it is...
     if (field->is_packable()) {
       printer->Print(
@@ -490,7 +495,7 @@ int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) {
 
 FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal(
     const FieldDescriptor* descriptor) {
-  return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor));
+  return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor), this->options());
 }
 
 }  // namespace csharp

+ 1 - 1
src/google/protobuf/compiler/csharp/csharp_message.h

@@ -47,7 +47,7 @@ class FieldGeneratorBase;
 
 class MessageGenerator : public SourceGeneratorBase {
  public:
-  MessageGenerator(const Descriptor* descriptor);
+  MessageGenerator(const Descriptor* descriptor, const Options* options);
   ~MessageGenerator();
 
   void GenerateCloningCode(io::Printer* printer);

+ 9 - 5
src/google/protobuf/compiler/csharp/csharp_message_field.cc

@@ -41,6 +41,7 @@
 #include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
 #include <google/protobuf/compiler/csharp/csharp_message_field.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
 
 namespace google {
 namespace protobuf {
@@ -48,8 +49,9 @@ namespace compiler {
 namespace csharp {
 
 MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
-                                             int fieldOrdinal)
-    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+                                             int fieldOrdinal,
+                                             const Options *options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
   variables_["has_property_check"] = name() + "_ != null";
   variables_["has_not_property_check"] = name() + "_ == null";
 }
@@ -143,9 +145,11 @@ void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) {
     "pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)");
 }
 
-MessageOneofFieldGenerator::MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
-						       int fieldOrdinal)
-    : MessageFieldGenerator(descriptor, fieldOrdinal) {
+MessageOneofFieldGenerator::MessageOneofFieldGenerator(
+    const FieldDescriptor* descriptor,
+	  int fieldOrdinal,
+    const Options *options)
+    : MessageFieldGenerator(descriptor, fieldOrdinal, options) {
   SetCommonOneofFieldVariables(&variables_);
 }
 

+ 6 - 2
src/google/protobuf/compiler/csharp/csharp_message_field.h

@@ -43,7 +43,9 @@ namespace csharp {
 
 class MessageFieldGenerator : public FieldGeneratorBase {
  public:
-  MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  MessageFieldGenerator(const FieldDescriptor* descriptor,
+                        int fieldOrdinal,
+                        const Options *options);
   ~MessageFieldGenerator();
 
   virtual void GenerateCodecCode(io::Printer* printer);
@@ -65,7 +67,9 @@ class MessageFieldGenerator : public FieldGeneratorBase {
 
 class MessageOneofFieldGenerator : public MessageFieldGenerator {
  public:
-  MessageOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
+                             int fieldOrdinal,
+                             const Options *options);
   ~MessageOneofFieldGenerator();
 
   virtual void GenerateCloningCode(io::Printer* printer);

+ 75 - 0
src/google/protobuf/compiler/csharp/csharp_options.h

@@ -0,0 +1,75 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+// Generator options (used by csharp_generator.cc):
+struct Options {
+  Options() :
+      file_extension(".cs"),
+      base_namespace(""),
+      base_namespace_specified(false) {
+  }
+  // Extension of the generated file. Defaults to ".cs"
+  string file_extension;
+  // Base namespace to use to create directory hierarchy. Defaults to "".
+  // This option allows the simple creation of a conventional C# file layout,
+  // where directories are created relative to a project-specific base
+  // namespace. For example, in a project with a base namespace of PetShop, a
+  // proto of user.proto with a C# namespace of PetShop.Model.Shared would
+  // generate Model/Shared/User.cs underneath the specified --csharp_out
+  // directory.
+  //
+  // If no base namespace is specified, all files are generated in the
+  // --csharp_out directory, with no subdirectories created automatically.
+  string base_namespace;
+  // Whether the base namespace has been explicitly specified by the user.
+  // This is required as the base namespace can be explicitly set to the empty
+  // string, meaning "create a full directory hierarchy, starting from the first
+  // segment of the namespace."
+  bool base_namespace_specified;
+};
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__

+ 5 - 4
src/google/protobuf/compiler/csharp/csharp_primitive_field.cc

@@ -40,6 +40,7 @@
 
 #include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
 #include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
 
 namespace google {
@@ -48,8 +49,8 @@ namespace compiler {
 namespace csharp {
 
 PrimitiveFieldGenerator::PrimitiveFieldGenerator(
-    const FieldDescriptor* descriptor, int fieldOrdinal)
-    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
   // TODO(jonskeet): Make this cleaner...
   is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING
       && descriptor->type() != FieldDescriptor::TYPE_BYTES;
@@ -163,8 +164,8 @@ void PrimitiveFieldGenerator::GenerateCodecCode(io::Printer* printer) {
 }
 
 PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
-    const FieldDescriptor* descriptor, int fieldOrdinal)
-    : PrimitiveFieldGenerator(descriptor, fieldOrdinal) {
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+    : PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) {
   SetCommonOneofFieldVariables(&variables_);
 }
 

+ 8 - 2
src/google/protobuf/compiler/csharp/csharp_primitive_field.h

@@ -41,9 +41,13 @@ namespace protobuf {
 namespace compiler {
 namespace csharp {
 
+struct Options;
+
 class PrimitiveFieldGenerator : public FieldGeneratorBase {
  public:
-  PrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                          int fieldOrdinal,
+                          const Options *options);
   ~PrimitiveFieldGenerator();
 
   virtual void GenerateCodecCode(io::Printer* printer);
@@ -67,7 +71,9 @@ class PrimitiveFieldGenerator : public FieldGeneratorBase {
 
 class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
  public:
-  PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
+                               int fieldOrdinal,
+                               const Options *options);
   ~PrimitiveOneofFieldGenerator();
 
   virtual void GenerateCloningCode(io::Printer* printer);

+ 6 - 4
src/google/protobuf/compiler/csharp/csharp_reflection_class.cc

@@ -43,6 +43,7 @@
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
 #include <google/protobuf/compiler/csharp/csharp_message.h>
 #include <google/protobuf/compiler/csharp/csharp_names.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
 #include <google/protobuf/compiler/csharp/csharp_reflection_class.h>
 
 namespace google {
@@ -50,8 +51,9 @@ namespace protobuf {
 namespace compiler {
 namespace csharp {
 
-ReflectionClassGenerator::ReflectionClassGenerator(const FileDescriptor* file)
-    : SourceGeneratorBase(file),
+ReflectionClassGenerator::ReflectionClassGenerator(const FileDescriptor* file,
+                                                   const Options* options)
+    : SourceGeneratorBase(file, options),
       file_(file) {
   namespace_ = GetFileNamespace(file);
   reflectionClassname_ = GetReflectionClassUnqualifiedName(file);
@@ -72,7 +74,7 @@ void ReflectionClassGenerator::Generate(io::Printer* printer) {
   if (file_->enum_type_count() > 0) {
     printer->Print("#region Enums\n");
     for (int i = 0; i < file_->enum_type_count(); i++) {
-      EnumGenerator enumGenerator(file_->enum_type(i));
+      EnumGenerator enumGenerator(file_->enum_type(i), this->options());
       enumGenerator.Generate(printer);
     }
     printer->Print("#endregion\n");
@@ -83,7 +85,7 @@ void ReflectionClassGenerator::Generate(io::Printer* printer) {
   if (file_->message_type_count() > 0) {
     printer->Print("#region Messages\n");
     for (int i = 0; i < file_->message_type_count(); i++) {
-      MessageGenerator messageGenerator(file_->message_type(i));
+      MessageGenerator messageGenerator(file_->message_type(i), this->options());
       messageGenerator.Generate(printer);
     }
     printer->Print("#endregion\n");

+ 4 - 2
src/google/protobuf/compiler/csharp/csharp_reflection_class.h

@@ -43,7 +43,7 @@ namespace csharp {
 
 class ReflectionClassGenerator : public SourceGeneratorBase {
  public:
-  ReflectionClassGenerator(const FileDescriptor* file);
+  ReflectionClassGenerator(const FileDescriptor* file, const Options* options);
   ~ReflectionClassGenerator();
 
   void Generate(io::Printer* printer);
@@ -56,7 +56,9 @@ class ReflectionClassGenerator : public SourceGeneratorBase {
 
   void WriteIntroduction(io::Printer* printer);
   void WriteDescriptor(io::Printer* printer);
-  void WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last);
+  void WriteGeneratedCodeInfo(const Descriptor* descriptor,
+                              io::Printer* printer,
+                              bool last);
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReflectionClassGenerator);
 };

+ 2 - 2
src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc

@@ -48,8 +48,8 @@ namespace compiler {
 namespace csharp {
 
 RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
-    const FieldDescriptor* descriptor, int fieldOrdinal)
-    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
 }
 
 RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {

+ 3 - 1
src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h

@@ -45,7 +45,9 @@ namespace csharp {
 // should probably have a RepeatedFieldGeneratorBase.
 class RepeatedEnumFieldGenerator : public FieldGeneratorBase {
  public:
-  RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+                             int fieldOrdinal,
+                             const Options *options);
   ~RepeatedEnumFieldGenerator();
 
   virtual void GenerateCloningCode(io::Printer* printer);

+ 6 - 4
src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc

@@ -49,8 +49,8 @@ namespace compiler {
 namespace csharp {
 
 RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
-    const FieldDescriptor* descriptor, int fieldOrdinal)
-    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
 }
 
 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {
@@ -66,10 +66,12 @@ void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) {
   // "create single field generator for this repeated field"
   // function, but it doesn't seem worth it for just this.
   if (IsWrapperType(descriptor_)) {
-    scoped_ptr<FieldGeneratorBase> single_generator(new WrapperFieldGenerator(descriptor_, fieldOrdinal_));
+    scoped_ptr<FieldGeneratorBase> single_generator(
+      new WrapperFieldGenerator(descriptor_, fieldOrdinal_, this->options()));
     single_generator->GenerateCodecCode(printer);
   } else {
-    scoped_ptr<FieldGeneratorBase> single_generator(new MessageFieldGenerator(descriptor_, fieldOrdinal_));
+    scoped_ptr<FieldGeneratorBase> single_generator(
+      new MessageFieldGenerator(descriptor_, fieldOrdinal_, this->options()));
     single_generator->GenerateCodecCode(printer);
   }
   printer->Print(";\n");

+ 5 - 1
src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h

@@ -41,9 +41,13 @@ namespace protobuf {
 namespace compiler {
 namespace csharp {
 
+struct Options;
+
 class RepeatedMessageFieldGenerator : public FieldGeneratorBase {
  public:
-  RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+                                int fieldOrdinal,
+                                const Options *options);
   ~RepeatedMessageFieldGenerator();
 
   virtual void GenerateCloningCode(io::Printer* printer);

+ 2 - 2
src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc

@@ -48,8 +48,8 @@ namespace compiler {
 namespace csharp {
 
 RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
-    const FieldDescriptor* descriptor, int fieldOrdinal)
-    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
 }
 
 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {

+ 1 - 1
src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h

@@ -43,7 +43,7 @@ namespace csharp {
 
 class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase {
  public:
-  RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options);
   ~RepeatedPrimitiveFieldGenerator();
 
   virtual void GenerateCloningCode(io::Printer* printer);

+ 9 - 2
src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc

@@ -39,14 +39,17 @@
 
 #include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_names.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace csharp {
 
-SourceGeneratorBase::SourceGeneratorBase(const FileDescriptor* descriptor)
-    : descriptor_(descriptor) {
+SourceGeneratorBase::SourceGeneratorBase(const FileDescriptor* descriptor,
+                                         const Options *options)
+    : descriptor_(descriptor), options_(options) {
 }
 
 SourceGeneratorBase::~SourceGeneratorBase() {
@@ -60,6 +63,10 @@ std::string SourceGeneratorBase::class_access_level() {
   return IsDescriptorProto(descriptor_) ? "internal" : "public";  // public_classes is always on.
 }
 
+const Options* SourceGeneratorBase::options() {
+  return this->options_;
+}
+
 }  // namespace csharp
 }  // namespace compiler
 }  // namespace protobuf

+ 5 - 1
src/google/protobuf/compiler/csharp/csharp_source_generator_base.h

@@ -40,17 +40,21 @@ namespace protobuf {
 namespace compiler {
 namespace csharp {
 
+struct Options;
+
 class SourceGeneratorBase {
  protected:
-  SourceGeneratorBase(const FileDescriptor* descriptor);
+  SourceGeneratorBase(const FileDescriptor* descriptor, const Options* options);
   virtual ~SourceGeneratorBase();
 
   std::string class_access_level();
+  const Options* options();
 
   void WriteGeneratedCodeAttributes(io::Printer* printer);
 
  private:
   const FileDescriptor* descriptor_;
+  const Options *options_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceGeneratorBase);
 };

+ 6 - 5
src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc

@@ -39,6 +39,7 @@
 
 #include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
 #include <google/protobuf/compiler/csharp/csharp_wrapper_field.h>
 
 namespace google {
@@ -47,8 +48,8 @@ namespace compiler {
 namespace csharp {
 
 WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor,
-                                       int fieldOrdinal)
-    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+                                       int fieldOrdinal, const Options *options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
   variables_["has_property_check"] = name() + "_ != null";
   variables_["has_not_property_check"] = name() + "_ == null";
   const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
@@ -151,9 +152,9 @@ void WrapperFieldGenerator::GenerateCodecCode(io::Printer* printer) {
   }
 }
 
-WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(const FieldDescriptor* descriptor,
-    int fieldOrdinal)
-    : WrapperFieldGenerator(descriptor, fieldOrdinal) {
+WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+    : WrapperFieldGenerator(descriptor, fieldOrdinal, options) {
     SetCommonOneofFieldVariables(&variables_);
 }
 

+ 8 - 2
src/google/protobuf/compiler/csharp/csharp_wrapper_field.h

@@ -41,9 +41,13 @@ namespace protobuf {
 namespace compiler {
 namespace csharp {
 
+struct Options;
+
 class WrapperFieldGenerator : public FieldGeneratorBase {
  public:
-  WrapperFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  WrapperFieldGenerator(const FieldDescriptor* descriptor,
+                        int fieldOrdinal,
+                        const Options *options);
   ~WrapperFieldGenerator();
 
   virtual void GenerateCodecCode(io::Printer* printer);
@@ -65,7 +69,9 @@ class WrapperFieldGenerator : public FieldGeneratorBase {
 
 class WrapperOneofFieldGenerator : public WrapperFieldGenerator {
  public:
-  WrapperOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  WrapperOneofFieldGenerator(const FieldDescriptor* descriptor,
+                             int fieldOrdinal,
+                             const Options *options);
   ~WrapperOneofFieldGenerator();
 
   virtual void GenerateMembers(io::Printer* printer);

+ 4 - 2
src/google/protobuf/compiler/objectivec/objectivec_enum.cc

@@ -72,8 +72,9 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) {
       "\n",
       "name", name_);
 
-  printer->Print("$comments$typedef GPB_ENUM($name$) {\n",
+  printer->Print("$comments$typedef$deprecated_attribute$ GPB_ENUM($name$) {\n",
                  "comments", enum_comments,
+                 "deprecated_attribute", GetOptionalDeprecatedAttribute(descriptor_),
                  "name", name_);
   printer->Indent();
 
@@ -99,8 +100,9 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) {
     }
 
     printer->Print(
-        "$name$ = $value$,\n",
+        "$name$$deprecated_attribute$ = $value$,\n",
         "name", EnumValueName(all_values_[i]),
+        "deprecated_attribute", GetOptionalDeprecatedAttribute(all_values_[i]),
         "value", SimpleItoa(all_values_[i]->number()));
   }
   printer->Outdent();

+ 9 - 8
src/google/protobuf/compiler/objectivec/objectivec_field.cc

@@ -78,6 +78,7 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
       classname + "_FieldNumber_" + capitalized_name;
   (*variables)["field_number"] = SimpleItoa(descriptor->number());
   (*variables)["field_type"] = GetCapitalizedType(descriptor);
+  (*variables)["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor);
   std::vector<string> field_flags;
   if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated");
   if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired");
@@ -266,12 +267,12 @@ void SingleFieldGenerator::GeneratePropertyDeclaration(
   printer->Print(variables_, "$comments$");
   printer->Print(
       variables_,
-      "@property(nonatomic, readwrite) $property_type$ $name$;\n"
+      "@property(nonatomic, readwrite) $property_type$ $name$$deprecated_attribute$;\n"
       "\n");
   if (WantsHasProperty()) {
     printer->Print(
         variables_,
-        "@property(nonatomic, readwrite) BOOL has$capitalized_name$;\n");
+        "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
   }
 }
 
@@ -330,18 +331,18 @@ void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
   printer->Print(variables_, "$comments$");
   printer->Print(
       variables_,
-      "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$;\n");
+      "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n");
   if (WantsHasProperty()) {
     printer->Print(
         variables_,
         "/// Test to see if @c $name$ has been set.\n"
-        "@property(nonatomic, readwrite) BOOL has$capitalized_name$;\n");
+        "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
   }
   if (IsInitName(variables_.find("name")->second)) {
     // If property name starts with init we need to annotate it to get past ARC.
     // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
     printer->Print(variables_,
-                   "- ($property_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n");
+                   "- ($property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
   }
   printer->Print("\n");
 }
@@ -385,14 +386,14 @@ void RepeatedFieldGenerator::GeneratePropertyDeclaration(
       variables_,
       "$comments$"
       "$array_comment$"
-      "@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$;\n"
+      "@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n"
       "/// The number of items in @c $name$ without causing the array to be created.\n"
-      "@property(nonatomic, readonly) NSUInteger $name$_Count;\n");
+      "@property(nonatomic, readonly) NSUInteger $name$_Count$deprecated_attribute$;\n");
   if (IsInitName(variables_.find("name")->second)) {
     // If property name starts with init we need to annotate it to get past ARC.
     // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
     printer->Print(variables_,
-                   "- ($array_property_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n");
+                   "- ($array_property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
   }
   printer->Print("\n");
 }

+ 10 - 0
src/google/protobuf/compiler/objectivec/objectivec_file.cc

@@ -115,6 +115,9 @@ void FileGenerator::GenerateHeader(io::Printer *printer) {
   printer->Print(
       "// @@protoc_insertion_point(imports)\n"
       "\n"
+      "#pragma clang diagnostic push\n"
+      "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n"
+      "\n"
       "CF_EXTERN_C_BEGIN\n"
       "\n");
 
@@ -189,6 +192,8 @@ void FileGenerator::GenerateHeader(io::Printer *printer) {
       "\n"
       "CF_EXTERN_C_END\n"
       "\n"
+      "#pragma clang diagnostic pop\n"
+      "\n"
       "// @@protoc_insertion_point(global_scope)\n");
 }
 
@@ -216,6 +221,9 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
   }
   printer->Print(
       "// @@protoc_insertion_point(imports)\n"
+      "\n"
+      "#pragma clang diagnostic push\n"
+      "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n"
       "\n");
 
   printer->Print(
@@ -342,6 +350,8 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
   }
 
   printer->Print(
+    "\n"
+    "#pragma clang diagnostic pop\n"
     "\n"
     "// @@protoc_insertion_point(global_scope)\n");
 }

+ 16 - 0
src/google/protobuf/compiler/objectivec/objectivec_helpers.h

@@ -133,6 +133,22 @@ enum ObjectiveCType {
   OBJECTIVECTYPE_MESSAGE
 };
 
+template<class TDescriptor>
+string GetOptionalDeprecatedAttribute(const TDescriptor* descriptor, bool preSpace = true, bool postNewline = false) {
+  if (descriptor->options().deprecated()) {
+    string result = "DEPRECATED_ATTRIBUTE";
+    if (preSpace) {
+      result.insert(0, " ");
+    }
+    if (postNewline) {
+      result.append("\n");
+    }
+    return result;
+  } else {
+    return "";
+  }
+}
+
 string GetCapitalizedType(const FieldDescriptor* field);
 
 ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type);

+ 2 - 1
src/google/protobuf/compiler/objectivec/objectivec_message.cc

@@ -321,8 +321,9 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
   }
 
   printer->Print(
-      "$comments$@interface $classname$ : GPBMessage\n\n",
+      "$comments$$deprecated_attribute$@interface $classname$ : GPBMessage\n\n",
       "classname", class_name_,
+      "deprecated_attribute", GetOptionalDeprecatedAttribute(descriptor_, false, true),
       "comments", message_comments);
 
   vector<char> seen_oneofs(descriptor_->oneof_decl_count(), 0);

+ 6 - 0
src/google/protobuf/dynamic_message.cc

@@ -253,6 +253,12 @@ class DynamicMessage : public Message {
   DynamicMessage(const TypeInfo* type_info);
   ~DynamicMessage();
 
+#ifndef _MSC_VER
+  void operator delete(void *p) {
+    ::operator delete(p); // non-sized deallocation
+  }
+#endif
+
   // Called on the prototype after construction to initialize message fields.
   void CrossLinkPrototypes();