Submit recent changes from internal branch. See CHANGES.txt for more details.
diff --git a/src/Makefile.am b/src/Makefile.am
index 35f5c0c..92bbe8c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -178,6 +178,8 @@
   google/protobuf/compiler/java/java_primitive_field.h         \
   google/protobuf/compiler/java/java_service.cc                \
   google/protobuf/compiler/java/java_service.h                 \
+  google/protobuf/compiler/java/java_string_field.cc           \
+  google/protobuf/compiler/java/java_string_field.h            \
   google/protobuf/compiler/python/python_generator.cc
 
 bin_PROGRAMS = protoc
diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc
index 3413a36..455c239 100644
--- a/src/google/protobuf/compiler/code_generator.cc
+++ b/src/google/protobuf/compiler/code_generator.cc
@@ -42,14 +42,19 @@
 namespace compiler {
 
 CodeGenerator::~CodeGenerator() {}
-OutputDirectory::~OutputDirectory() {}
+GeneratorContext::~GeneratorContext() {}
 
-io::ZeroCopyOutputStream* OutputDirectory::OpenForInsert(
+io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert(
     const string& filename, const string& insertion_point) {
-  GOOGLE_LOG(FATAL) << "This OutputDirectory does not support insertion.";
+  GOOGLE_LOG(FATAL) << "This GeneratorContext does not support insertion.";
   return NULL;  // make compiler happy
 }
 
+void GeneratorContext::ListParsedFiles(
+    vector<const FileDescriptor*>* output) {
+  GOOGLE_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles";
+}
+
 // Parses a set of comma-delimited name/value pairs.
 void ParseGeneratorParameter(const string& text,
                              vector<pair<string, string> >* output) {
diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h
index ea094cd..252f68d 100644
--- a/src/google/protobuf/compiler/code_generator.h
+++ b/src/google/protobuf/compiler/code_generator.h
@@ -53,7 +53,7 @@
 
 // Defined in this file.
 class CodeGenerator;
-class OutputDirectory;
+class GeneratorContext;
 
 // The abstract interface to a class which generates code implementing a
 // particular proto file in a particular language.  A number of these may
@@ -76,7 +76,7 @@
   // the problem (e.g. "invalid parameter") and returns false.
   virtual bool Generate(const FileDescriptor* file,
                         const string& parameter,
-                        OutputDirectory* output_directory,
+                        GeneratorContext* generator_context,
                         string* error) const = 0;
 
  private:
@@ -85,11 +85,12 @@
 
 // CodeGenerators generate one or more files in a given directory.  This
 // abstract interface represents the directory to which the CodeGenerator is
-// to write.
-class LIBPROTOC_EXPORT OutputDirectory {
+// to write and other information about the context in which the Generator
+// runs.
+class LIBPROTOC_EXPORT GeneratorContext {
  public:
-  inline OutputDirectory() {}
-  virtual ~OutputDirectory();
+  inline GeneratorContext() {}
+  virtual ~GeneratorContext();
 
   // Opens the given file, truncating it if it exists, and returns a
   // ZeroCopyOutputStream that writes to the file.  The caller takes ownership
@@ -112,10 +113,19 @@
   virtual io::ZeroCopyOutputStream* OpenForInsert(
       const string& filename, const string& insertion_point);
 
+  // Returns a vector of FileDescriptors for all the files being compiled
+  // in this run.  Useful for languages, such as Go, that treat files
+  // differently when compiled as a set rather than individually.
+  virtual void ListParsedFiles(vector<const FileDescriptor*>* output);
+
  private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OutputDirectory);
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorContext);
 };
 
+// The type GeneratorContext was once called OutputDirectory. This typedef
+// provides backward compatibility.
+typedef GeneratorContext OutputDirectory;
+
 // Several code generators treat the parameter argument as holding a
 // list of options separated by commas.  This helper function parses
 // a set of comma-delimited name/value pairs: e.g.,
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 02c3e0f..9e9849c 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -48,6 +48,9 @@
 #include <iostream>
 #include <ctype.h>
 
+#include <google/protobuf/stubs/hash.h>
+
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/importer.h>
 #include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/compiler/plugin.pb.h>
@@ -58,12 +61,10 @@
 #include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/stubs/map-util.h>
 #include <google/protobuf/stubs/stl_util-inl.h>
-#include <google/protobuf/stubs/hash.h>
 
 
 namespace google {
@@ -182,7 +183,7 @@
 class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector,
                                            public io::ErrorCollector {
  public:
-  ErrorPrinter(ErrorFormat format, DiskSourceTree *tree = NULL) 
+  ErrorPrinter(ErrorFormat format, DiskSourceTree *tree = NULL)
     : format_(format), tree_(tree) {}
   ~ErrorPrinter() {}
 
@@ -191,8 +192,8 @@
                 const string& message) {
 
     // Print full path when running under MSVS
-    std::string dfile;
-    if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS && 
+    string dfile;
+    if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS &&
         tree_ != NULL &&
         tree_->VirtualFileToDiskFile(filename, &dfile)) {
       cerr << dfile;
@@ -229,12 +230,12 @@
 
 // -------------------------------------------------------------------
 
-// An OutputDirectory implementation that buffers files in memory, then dumps
+// A GeneratorContext implementation that buffers files in memory, then dumps
 // them all to disk on demand.
-class CommandLineInterface::MemoryOutputDirectory : public OutputDirectory {
+class CommandLineInterface::GeneratorContextImpl : public GeneratorContext {
  public:
-  MemoryOutputDirectory();
-  ~MemoryOutputDirectory();
+  GeneratorContextImpl(const vector<const FileDescriptor*>& parsed_files);
+  ~GeneratorContextImpl();
 
   // Write all files in the directory to disk at the given output location,
   // which must end in a '/'.
@@ -248,10 +249,13 @@
   // format, unless one has already been written.
   void AddJarManifest();
 
-  // implements OutputDirectory --------------------------------------
+  // implements GeneratorContext --------------------------------------
   io::ZeroCopyOutputStream* Open(const string& filename);
   io::ZeroCopyOutputStream* OpenForInsert(
       const string& filename, const string& insertion_point);
+  void ListParsedFiles(vector<const FileDescriptor*>* output) {
+    *output = parsed_files_;
+  }
 
  private:
   friend class MemoryOutputStream;
@@ -259,14 +263,15 @@
   // map instead of hash_map so that files are written in order (good when
   // writing zips).
   map<string, string*> files_;
+  const vector<const FileDescriptor*>& parsed_files_;
   bool had_error_;
 };
 
 class CommandLineInterface::MemoryOutputStream
     : public io::ZeroCopyOutputStream {
  public:
-  MemoryOutputStream(MemoryOutputDirectory* directory, const string& filename);
-  MemoryOutputStream(MemoryOutputDirectory* directory, const string& filename,
+  MemoryOutputStream(GeneratorContextImpl* directory, const string& filename);
+  MemoryOutputStream(GeneratorContextImpl* directory, const string& filename,
                      const string& insertion_point);
   virtual ~MemoryOutputStream();
 
@@ -277,7 +282,7 @@
 
  private:
   // Where to insert the string when it's done.
-  MemoryOutputDirectory* directory_;
+  GeneratorContextImpl* directory_;
   string filename_;
   string insertion_point_;
 
@@ -290,14 +295,17 @@
 
 // -------------------------------------------------------------------
 
-CommandLineInterface::MemoryOutputDirectory::MemoryOutputDirectory()
-    : had_error_(false) {}
+CommandLineInterface::GeneratorContextImpl::GeneratorContextImpl(
+    const vector<const FileDescriptor*>& parsed_files)
+    : parsed_files_(parsed_files),
+      had_error_(false) {
+}
 
-CommandLineInterface::MemoryOutputDirectory::~MemoryOutputDirectory() {
+CommandLineInterface::GeneratorContextImpl::~GeneratorContextImpl() {
   STLDeleteValues(&files_);
 }
 
-bool CommandLineInterface::MemoryOutputDirectory::WriteAllToDisk(
+bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk(
     const string& prefix) {
   if (had_error_) {
     return false;
@@ -372,7 +380,7 @@
   return true;
 }
 
-bool CommandLineInterface::MemoryOutputDirectory::WriteAllToZip(
+bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip(
     const string& filename) {
   if (had_error_) {
     return false;
@@ -413,7 +421,7 @@
   return true;
 }
 
-void CommandLineInterface::MemoryOutputDirectory::AddJarManifest() {
+void CommandLineInterface::GeneratorContextImpl::AddJarManifest() {
   string** map_slot = &files_["META-INF/MANIFEST.MF"];
   if (*map_slot == NULL) {
     *map_slot = new string(
@@ -423,13 +431,13 @@
   }
 }
 
-io::ZeroCopyOutputStream* CommandLineInterface::MemoryOutputDirectory::Open(
+io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open(
     const string& filename) {
   return new MemoryOutputStream(this, filename);
 }
 
 io::ZeroCopyOutputStream*
-CommandLineInterface::MemoryOutputDirectory::OpenForInsert(
+CommandLineInterface::GeneratorContextImpl::OpenForInsert(
     const string& filename, const string& insertion_point) {
   return new MemoryOutputStream(this, filename, insertion_point);
 }
@@ -437,14 +445,14 @@
 // -------------------------------------------------------------------
 
 CommandLineInterface::MemoryOutputStream::MemoryOutputStream(
-    MemoryOutputDirectory* directory, const string& filename)
+    GeneratorContextImpl* directory, const string& filename)
     : directory_(directory),
       filename_(filename),
       inner_(new io::StringOutputStream(&data_)) {
 }
 
 CommandLineInterface::MemoryOutputStream::MemoryOutputStream(
-    MemoryOutputDirectory* directory, const string& filename,
+    GeneratorContextImpl* directory, const string& filename,
     const string& insertion_point)
     : directory_(directory),
       filename_(filename),
@@ -613,11 +621,11 @@
     }
   }
 
-  // We construct a separate OutputDirectory for each output location.  Note
+  // We construct a separate GeneratorContext for each output location.  Note
   // that two code generators may output to the same location, in which case
-  // they should share a single OutputDirectory (so that OpenForInsert() works).
-  typedef hash_map<string, MemoryOutputDirectory*> OutputDirectoryMap;
-  OutputDirectoryMap output_directories;
+  // they should share a single GeneratorContext so that OpenForInsert() works.
+  typedef hash_map<string, GeneratorContextImpl*> GeneratorContextMap;
+  GeneratorContextMap output_directories;
 
   // Generate output.
   if (mode_ == MODE_COMPILE) {
@@ -627,11 +635,11 @@
           !HasSuffixString(output_location, ".jar")) {
         AddTrailingSlash(&output_location);
       }
-      MemoryOutputDirectory** map_slot = &output_directories[output_location];
+      GeneratorContextImpl** map_slot = &output_directories[output_location];
 
       if (*map_slot == NULL) {
         // First time we've seen this output location.
-        *map_slot = new MemoryOutputDirectory;
+        *map_slot = new GeneratorContextImpl(parsed_files);
       }
 
       if (!GenerateOutput(parsed_files, output_directives_[i], *map_slot)) {
@@ -642,10 +650,10 @@
   }
 
   // Write all output to disk.
-  for (OutputDirectoryMap::iterator iter = output_directories.begin();
+  for (GeneratorContextMap::iterator iter = output_directories.begin();
        iter != output_directories.end(); ++iter) {
     const string& location = iter->first;
-    MemoryOutputDirectory* directory = iter->second;
+    GeneratorContextImpl* directory = iter->second;
     if (HasSuffixString(location, "/")) {
       if (!directory->WriteAllToDisk(location)) {
         STLDeleteValues(&output_directories);
@@ -1107,7 +1115,7 @@
 bool CommandLineInterface::GenerateOutput(
     const vector<const FileDescriptor*>& parsed_files,
     const OutputDirective& output_directive,
-    OutputDirectory* output_directory) {
+    GeneratorContext* generator_context) {
   // Call the generator.
   string error;
   if (output_directive.generator == NULL) {
@@ -1122,7 +1130,7 @@
 
     if (!GeneratePluginOutput(parsed_files, plugin_name,
                               output_directive.parameter,
-                              output_directory, &error)) {
+                              generator_context, &error)) {
       cerr << output_directive.name << ": " << error << endl;
       return false;
     }
@@ -1131,7 +1139,7 @@
     for (int i = 0; i < parsed_files.size(); i++) {
       if (!output_directive.generator->Generate(
           parsed_files[i], output_directive.parameter,
-          output_directory, &error)) {
+          generator_context, &error)) {
         // Generator returned an error.
         cerr << output_directive.name << ": " << parsed_files[i]->name() << ": "
              << error << endl;
@@ -1147,7 +1155,7 @@
     const vector<const FileDescriptor*>& parsed_files,
     const string& plugin_name,
     const string& parameter,
-    OutputDirectory* output_directory,
+    GeneratorContext* generator_context,
     string* error) {
   CodeGeneratorRequest request;
   CodeGeneratorResponse response;
@@ -1190,14 +1198,14 @@
       // We reset current_output to NULL first so that the old file is closed
       // before the new one is opened.
       current_output.reset();
-      current_output.reset(output_directory->OpenForInsert(
+      current_output.reset(generator_context->OpenForInsert(
           output_file.name(), output_file.insertion_point()));
     } else if (!output_file.name().empty()) {
       // Starting a new file.  Open it.
       // We reset current_output to NULL first so that the old file is closed
       // before the new one is opened.
       current_output.reset();
-      current_output.reset(output_directory->Open(output_file.name()));
+      current_output.reset(generator_context->Open(output_file.name()));
     } else if (current_output == NULL) {
       *error = strings::Substitute(
         "$0: First file chunk returned by plugin did not specify a file name.",
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index d25a50e..0b507d8 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -56,7 +56,7 @@
 namespace compiler {
 
 class CodeGenerator;        // code_generator.h
-class OutputDirectory;      // code_generator.h
+class GeneratorContext;      // code_generator.h
 class DiskSourceTree;       // importer.h
 
 // This class implements the command-line interface to the protocol compiler.
@@ -174,7 +174,7 @@
   // -----------------------------------------------------------------
 
   class ErrorPrinter;
-  class MemoryOutputDirectory;
+  class GeneratorContextImpl;
   class MemoryOutputStream;
 
   // Clear state from previous Run().
@@ -212,11 +212,11 @@
   struct OutputDirective;  // see below
   bool GenerateOutput(const vector<const FileDescriptor*>& parsed_files,
                       const OutputDirective& output_directive,
-                      OutputDirectory* output_directory);
+                      GeneratorContext* generator_context);
   bool GeneratePluginOutput(const vector<const FileDescriptor*>& parsed_files,
                             const string& plugin_name,
                             const string& parameter,
-                            OutputDirectory* output_directory,
+                            GeneratorContext* generator_context,
                             string* error);
 
   // Implements --encode and --decode.
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index bdf37ad..6634b67 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -143,6 +143,10 @@
                        const string& proto_name,
                        const string& message_name,
                        const string& output_directory);
+  void ExpectGeneratedWithMultipleInputs(const string& generator_name,
+                                         const string& all_proto_names,
+                                         const string& proto_name,
+                                         const string& message_name);
   void ExpectGeneratedWithInsertions(const string& generator_name,
                                      const string& parameter,
                                      const string& insertions,
@@ -190,7 +194,7 @@
   // implements CodeGenerator ----------------------------------------
   bool Generate(const FileDescriptor* file,
                 const string& parameter,
-                OutputDirectory* output_directory,
+                GeneratorContext* context,
                 string* error) const {
     called_ = true;
     parameter_ = parameter;
@@ -251,7 +255,6 @@
 
   if (!disallow_plugins_) {
     cli_.AllowPlugins("prefix-");
-
     const char* possible_paths[] = {
       // When building with shared libraries, libtool hides the real executable
       // in .libs and puts a fake wrapper in the current directory.
@@ -353,7 +356,8 @@
     const string& proto_name,
     const string& message_name) {
   MockCodeGenerator::ExpectGenerated(
-      generator_name, parameter, "", proto_name, message_name, temp_directory_);
+      generator_name, parameter, "", proto_name, message_name, proto_name,
+      temp_directory_);
 }
 
 void CommandLineInterfaceTest::ExpectGenerated(
@@ -363,10 +367,21 @@
     const string& message_name,
     const string& output_directory) {
   MockCodeGenerator::ExpectGenerated(
-      generator_name, parameter, "", proto_name, message_name,
+      generator_name, parameter, "", proto_name, message_name, proto_name,
       temp_directory_ + "/" + output_directory);
 }
 
+void CommandLineInterfaceTest::ExpectGeneratedWithMultipleInputs(
+    const string& generator_name,
+    const string& all_proto_names,
+    const string& proto_name,
+    const string& message_name) {
+  MockCodeGenerator::ExpectGenerated(
+      generator_name, "", "", proto_name, message_name,
+      all_proto_names,
+      temp_directory_);
+}
+
 void CommandLineInterfaceTest::ExpectGeneratedWithInsertions(
     const string& generator_name,
     const string& parameter,
@@ -375,7 +390,7 @@
     const string& message_name) {
   MockCodeGenerator::ExpectGenerated(
       generator_name, parameter, insertions, proto_name, message_name,
-      temp_directory_);
+      proto_name, temp_directory_);
 }
 
 void CommandLineInterfaceTest::ExpectNullCodeGeneratorCalled(
@@ -455,8 +470,44 @@
       "--proto_path=$tmpdir foo.proto bar.proto");
 
   ExpectNoErrors();
-  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
-  ExpectGenerated("test_generator", "", "bar.proto", "Bar");
+  ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+                                    "foo.proto", "Foo");
+  ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+                                    "bar.proto", "Bar");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+                                    "foo.proto", "Foo");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+                                    "bar.proto", "Bar");
+}
+
+TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport) {
+  // Test parsing multiple input files with an import of a separate file.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  CreateTempFile("bar.proto",
+    "syntax = \"proto2\";\n"
+    "import \"baz.proto\";\n"
+    "message Bar {\n"
+    "  optional Baz a = 1;\n"
+    "}\n");
+  CreateTempFile("baz.proto",
+    "syntax = \"proto2\";\n"
+    "message Baz {}\n");
+
+  Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto bar.proto");
+
+  ExpectNoErrors();
+  ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+                                    "foo.proto", "Foo");
+  ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+                                    "bar.proto", "Bar");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+                                    "foo.proto", "Foo");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+                                    "bar.proto", "Bar");
 }
 
 TEST_F(CommandLineInterfaceTest, CreateDirectory) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
index 30b1d2b..bcfa502 100644
--- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -79,10 +79,10 @@
   }
 };
 
-class MockOutputDirectory : public OutputDirectory {
+class MockGeneratorContext : public GeneratorContext {
  public:
-  MockOutputDirectory() {}
-  ~MockOutputDirectory() {
+  MockGeneratorContext() {}
+  ~MockGeneratorContext() {
     STLDeleteValues(&files_);
   }
 
@@ -102,7 +102,7 @@
          "to your CL.";
   }
 
-  // implements OutputDirectory --------------------------------------
+  // implements GeneratorContext --------------------------------------
 
   virtual io::ZeroCopyOutputStream* Open(const string& filename) {
     string** map_slot = &files_[filename];
@@ -130,24 +130,24 @@
   ASSERT_TRUE(plugin_proto_file != NULL);
 
   CppGenerator generator;
-  MockOutputDirectory output_directory;
+  MockGeneratorContext context;
   string error;
   string parameter;
   parameter = "dllexport_decl=LIBPROTOBUF_EXPORT";
   ASSERT_TRUE(generator.Generate(proto_file, parameter,
-                                 &output_directory, &error));
+                                 &context, &error));
   parameter = "dllexport_decl=LIBPROTOC_EXPORT";
   ASSERT_TRUE(generator.Generate(plugin_proto_file, parameter,
-                                 &output_directory, &error));
+                                 &context, &error));
 
-  output_directory.ExpectFileMatches("google/protobuf/descriptor.pb.h",
-                                     "google/protobuf/descriptor.pb.h");
-  output_directory.ExpectFileMatches("google/protobuf/descriptor.pb.cc",
-                                     "google/protobuf/descriptor.pb.cc");
-  output_directory.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h",
-                                     "google/protobuf/compiler/plugin.pb.h");
-  output_directory.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc",
-                                     "google/protobuf/compiler/plugin.pb.cc");
+  context.ExpectFileMatches("google/protobuf/descriptor.pb.h",
+                            "google/protobuf/descriptor.pb.h");
+  context.ExpectFileMatches("google/protobuf/descriptor.pb.cc",
+                            "google/protobuf/descriptor.pb.cc");
+  context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h",
+                            "google/protobuf/compiler/plugin.pb.h");
+  context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc",
+                            "google/protobuf/compiler/plugin.pb.cc");
 }
 
 }  // namespace
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index 91ce493..a369f41 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -85,7 +85,7 @@
     "}\n"
     "inline void $classname$::set_$name$($type$ value) {\n"
     "  GOOGLE_DCHECK($type$_IsValid(value));\n"
-    "  _set_bit($index$);\n"
+    "  set_has_$name$();\n"
     "  $name$_ = value;\n"
     "}\n");
 }
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index e31cb42..22d6fdb 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -283,6 +283,7 @@
   printer->Print(
     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
     "\n"
+
     // The generated code calls accessors that might be deprecated. We don't
     // want the compiler to warn in generated code.
     "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc
index d67d350..bb84e2a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -53,7 +53,7 @@
 
 bool CppGenerator::Generate(const FileDescriptor* file,
                             const string& parameter,
-                            OutputDirectory* output_directory,
+                            GeneratorContext* generator_context,
                             string* error) const {
   vector<pair<string, string> > options;
   ParseGeneratorParameter(parameter, &options);
@@ -100,7 +100,7 @@
   // Generate header.
   {
     scoped_ptr<io::ZeroCopyOutputStream> output(
-      output_directory->Open(basename + ".h"));
+      generator_context->Open(basename + ".h"));
     io::Printer printer(output.get(), '$');
     file_generator.GenerateHeader(&printer);
   }
@@ -108,7 +108,7 @@
   // Generate cc file.
   {
     scoped_ptr<io::ZeroCopyOutputStream> output(
-      output_directory->Open(basename + ".cc"));
+      generator_context->Open(basename + ".cc"));
     io::Printer printer(output.get(), '$');
     file_generator.GenerateSource(&printer);
   }
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.h b/src/google/protobuf/compiler/cpp/cpp_generator.h
index f52e886..a90e84d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.h
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.h
@@ -57,7 +57,7 @@
   // implements CodeGenerator ----------------------------------------
   bool Generate(const FileDescriptor* file,
                 const string& parameter,
-                OutputDirectory* output_directory,
+                GeneratorContext* generator_context,
                 string* error) const;
 
  private:
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index cbdcce8..c4e6fb2 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -35,6 +35,7 @@
 #include <algorithm>
 #include <google/protobuf/stubs/hash.h>
 #include <map>
+#include <utility>
 #include <vector>
 #include <google/protobuf/compiler/cpp/cpp_message.h>
 #include <google/protobuf/compiler/cpp/cpp_field.h>
@@ -143,6 +144,137 @@
   return HasRequiredFields(type, &already_seen);
 }
 
+// This returns an estimate of the compiler's alignment for the field.  This
+// can't guarantee to be correct because the generated code could be compiled on
+// different systems with different alignment rules.  The estimates below assume
+// 64-bit pointers.
+int EstimateAlignmentSize(const FieldDescriptor* field) {
+  if (field == NULL) return 0;
+  if (field->is_repeated()) return 8;
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return 1;
+
+    case FieldDescriptor::CPPTYPE_INT32:
+    case FieldDescriptor::CPPTYPE_UINT32:
+    case FieldDescriptor::CPPTYPE_ENUM:
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return 4;
+
+    case FieldDescriptor::CPPTYPE_INT64:
+    case FieldDescriptor::CPPTYPE_UINT64:
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+    case FieldDescriptor::CPPTYPE_STRING:
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return 8;
+  }
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return -1;  // Make compiler happy.
+}
+
+// FieldGroup is just a helper for OptimizePadding below.  It holds a vector of
+// fields that are grouped together because they have compatible alignment, and
+// a preferred location in the final field ordering.
+class FieldGroup {
+ public:
+  FieldGroup()
+      : preferred_location_(0) {}
+
+  // A group with a single field.
+  FieldGroup(float preferred_location, const FieldDescriptor* field)
+      : preferred_location_(preferred_location),
+        fields_(1, field) {}
+
+  // Append the fields in 'other' to this group.
+  void Append(const FieldGroup& other) {
+    if (other.fields_.empty()) {
+      return;
+    }
+    // Preferred location is the average among all the fields, so we weight by
+    // the number of fields on each FieldGroup object.
+    preferred_location_ =
+        (preferred_location_ * fields_.size() +
+         (other.preferred_location_ * other.fields_.size())) /
+        (fields_.size() + other.fields_.size());
+    fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end());
+  }
+
+  void SetPreferredLocation(float location) { preferred_location_ = location; }
+  const vector<const FieldDescriptor*>& fields() const { return fields_; }
+
+  // FieldGroup objects sort by their preferred location.
+  bool operator<(const FieldGroup& other) const {
+    return preferred_location_ < other.preferred_location_;
+  }
+
+ private:
+  // "preferred_location_" is an estimate of where this group should go in the
+  // final list of fields.  We compute this by taking the average index of each
+  // field in this group in the original ordering of fields.  This is very
+  // approximate, but should put this group close to where its member fields
+  // originally went.
+  float preferred_location_;
+  vector<const FieldDescriptor*> fields_;
+  // We rely on the default copy constructor and operator= so this type can be
+  // used in a vector.
+};
+
+// Reorder 'fields' so that if the fields are output into a c++ class in the new
+// order, the alignment padding is minimized.  We try to do this while keeping
+// each field as close as possible to its original position so that we don't
+// reduce cache locality much for function that access each field in order.
+void OptimizePadding(vector<const FieldDescriptor*>* fields) {
+  // First divide fields into those that align to 1 byte, 4 bytes or 8 bytes.
+  vector<FieldGroup> aligned_to_1, aligned_to_4, aligned_to_8;
+  for (int i = 0; i < fields->size(); ++i) {
+    switch (EstimateAlignmentSize((*fields)[i])) {
+      case 1: aligned_to_1.push_back(FieldGroup(i, (*fields)[i])); break;
+      case 4: aligned_to_4.push_back(FieldGroup(i, (*fields)[i])); break;
+      case 8: aligned_to_8.push_back(FieldGroup(i, (*fields)[i])); break;
+      default:
+        GOOGLE_LOG(FATAL) << "Unknown alignment size.";
+    }
+  }
+
+  // Now group fields aligned to 1 byte into sets of 4, and treat those like a
+  // single field aligned to 4 bytes.
+  for (int i = 0; i < aligned_to_1.size(); i += 4) {
+    FieldGroup field_group;
+    for (int j = i; j < aligned_to_1.size() && j < i + 4; ++j) {
+      field_group.Append(aligned_to_1[j]);
+    }
+    aligned_to_4.push_back(field_group);
+  }
+  // Sort by preferred location to keep fields as close to their original
+  // location as possible.
+  sort(aligned_to_4.begin(), aligned_to_4.end());
+
+  // Now group fields aligned to 4 bytes (or the 4-field groups created above)
+  // into pairs, and treat those like a single field aligned to 8 bytes.
+  for (int i = 0; i < aligned_to_4.size(); i += 2) {
+    FieldGroup field_group;
+    for (int j = i; j < aligned_to_4.size() && j < i + 2; ++j) {
+      field_group.Append(aligned_to_4[j]);
+    }
+    if (i == aligned_to_4.size() - 1) {
+      // Move incomplete 4-byte block to the end.
+      field_group.SetPreferredLocation(fields->size() + 1);
+    }
+    aligned_to_8.push_back(field_group);
+  }
+  // Sort by preferred location to keep fields as close to their original
+  // location as possible.
+  sort(aligned_to_8.begin(), aligned_to_8.end());
+
+  // Now pull out all the FieldDescriptors in order.
+  fields->clear();
+  for (int i = 0; i < aligned_to_8.size(); ++i) {
+    fields->insert(fields->end(),
+                   aligned_to_8[i].fields().begin(),
+                   aligned_to_8[i].fields().end());
+  }
+}
+
 }
 
 // ===================================================================
@@ -264,10 +396,20 @@
         "}\n");
     } else {
       // Singular field.
+      char buffer[kFastToBufferSize];
+      vars["has_array_index"] = SimpleItoa(field->index() / 32);
+      vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32), buffer);
       printer->Print(vars,
         "inline bool $classname$::has_$name$() const {\n"
-        "  return _has_bit($index$);\n"
-        "}\n");
+        "  return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n"
+        "}\n"
+        "inline void $classname$::set_has_$name$() {\n"
+        "  _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n"
+        "}\n"
+        "inline void $classname$::clear_has_$name$() {\n"
+        "  _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n"
+        "}\n"
+        );
     }
 
     // Generate clear_$name$()
@@ -279,7 +421,8 @@
     printer->Outdent();
 
     if (!field->is_repeated()) {
-      printer->Print(vars, "  _clear_bit($index$);\n");
+      printer->Print(vars,
+                     "  clear_has_$name$();\n");
     }
 
     printer->Print("}\n");
@@ -444,28 +587,74 @@
     "// @@protoc_insertion_point(class_scope:$full_name$)\n",
     "full_name", descriptor_->full_name());
 
-  // Generate private members for fields.
+  // Generate private members.
   printer->Outdent();
   printer->Print(" private:\n");
   printer->Indent();
 
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (!descriptor_->field(i)->is_repeated()) {
+      printer->Print(
+        "inline void set_has_$name$();\n",
+        "name", FieldName(descriptor_->field(i)));
+      printer->Print(
+        "inline void clear_has_$name$();\n",
+        "name", FieldName(descriptor_->field(i)));
+    }
+  }
+  printer->Print("\n");
+
+  // To minimize padding, data members are divided into three sections:
+  // (1) members assumed to align to 8 bytes
+  // (2) members corresponding to message fields, re-ordered to optimize
+  //     alignment.
+  // (3) members assumed to align to 4 bytes.
+
+  // Members assumed to align to 8 bytes:
+
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(
-      "::google::protobuf::internal::ExtensionSet _extensions_;\n");
+      "::google::protobuf::internal::ExtensionSet _extensions_;\n"
+      "\n");
   }
 
   if (HasUnknownFields(descriptor_->file())) {
     printer->Print(
-      "::google::protobuf::UnknownFieldSet _unknown_fields_;\n");
+      "::google::protobuf::UnknownFieldSet _unknown_fields_;\n"
+      "\n");
   }
 
+  // Field members:
+
+  vector<const FieldDescriptor*> fields;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    fields.push_back(descriptor_->field(i));
+  }
+  OptimizePadding(&fields);
+  for (int i = 0; i < fields.size(); ++i) {
+    field_generators_.get(fields[i]).GeneratePrivateMembers(printer);
+  }
+
+  // Members assumed to align to 4 bytes:
+
   // TODO(kenton):  Make _cached_size_ an atomic<int> when C++ supports it.
   printer->Print(
-    "mutable int _cached_size_;\n"
-    "\n");
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    field_generators_.get(descriptor_->field(i))
-                     .GeneratePrivateMembers(printer);
+      "\n"
+      "mutable int _cached_size_;\n");
+
+  // Generate _has_bits_.
+  if (descriptor_->field_count() > 0) {
+    printer->Print(vars,
+      "::google::protobuf::uint32 _has_bits_[($field_count$ + 31) / 32];\n"
+      "\n");
+  } else {
+    // Zero-size arrays aren't technically allowed, and MSVC in particular
+    // doesn't like them.  We still need to declare these arrays to make
+    // other code compile.  Since this is an uncommon case, we'll just declare
+    // them with size 1 and waste some space.  Oh well.
+    printer->Print(
+      "::google::protobuf::uint32 _has_bits_[1];\n"
+      "\n");
   }
 
   // Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as
@@ -484,32 +673,7 @@
       GlobalAssignDescriptorsName(descriptor_->file()->name()),
     "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name()));
 
-  // Generate offsets and _has_bits_ boilerplate.
-  if (descriptor_->field_count() > 0) {
-    printer->Print(vars,
-      "::google::protobuf::uint32 _has_bits_[($field_count$ + 31) / 32];\n");
-  } else {
-    // Zero-size arrays aren't technically allowed, and MSVC in particular
-    // doesn't like them.  We still need to declare these arrays to make
-    // other code compile.  Since this is an uncommon case, we'll just declare
-    // them with size 1 and waste some space.  Oh well.
-    printer->Print(
-      "::google::protobuf::uint32 _has_bits_[1];\n");
-  }
-
   printer->Print(
-    "\n"
-    "// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?\n"
-    "inline bool _has_bit(int index) const {\n"
-    "  return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;\n"
-    "}\n"
-    "inline void _set_bit(int index) {\n"
-    "  _has_bits_[index / 32] |= (1u << (index % 32));\n"
-    "}\n"
-    "inline void _clear_bit(int index) {\n"
-    "  _has_bits_[index / 32] &= ~(1u << (index % 32));\n"
-    "}\n"
-    "\n"
     "void InitAsDefaultInstance();\n"
     "static $classname$* default_instance_;\n",
     "classname", classname_);
@@ -961,9 +1125,6 @@
     const FieldDescriptor* field = descriptor_->field(i);
 
     if (!field->is_repeated()) {
-      map<string, string> vars;
-      vars["index"] = SimpleItoa(field->index());
-
       // We can use the fact that _has_bits_ is a giant bitfield to our
       // advantage:  We can check up to 32 bits at a time for equality to
       // zero, and skip the whole range if so.  This can improve the speed
@@ -975,8 +1136,9 @@
           printer->Outdent();
           printer->Print("}\n");
         }
-        printer->Print(vars,
-          "if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n");
+        printer->Print(
+          "if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n",
+          "index", SimpleItoa(field->index()));
         printer->Indent();
       }
       last_index = i;
@@ -989,7 +1151,9 @@
         field->cpp_type() == FieldDescriptor::CPPTYPE_STRING;
 
       if (should_check_bit) {
-        printer->Print(vars, "if (_has_bit($index$)) {\n");
+        printer->Print(
+          "if (has_$name$()) {\n",
+          "name", FieldName(field));
         printer->Indent();
       }
 
@@ -1129,24 +1293,23 @@
     const FieldDescriptor* field = descriptor_->field(i);
 
     if (!field->is_repeated()) {
-      map<string, string> vars;
-      vars["index"] = SimpleItoa(field->index());
-
       // See above in GenerateClear for an explanation of this.
       if (i / 8 != last_index / 8 || last_index < 0) {
         if (last_index >= 0) {
           printer->Outdent();
           printer->Print("}\n");
         }
-        printer->Print(vars,
-          "if (from._has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n");
+        printer->Print(
+          "if (from._has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n",
+          "index", SimpleItoa(field->index()));
         printer->Indent();
       }
 
       last_index = i;
 
-      printer->Print(vars,
-        "if (from._has_bit($index$)) {\n");
+      printer->Print(
+        "if (from.has_$name$()) {\n",
+        "name", FieldName(field));
       printer->Indent();
 
       field_generators_.get(field).GenerateMergingCode(printer);
@@ -1423,8 +1586,8 @@
 
   if (!field->is_repeated()) {
     printer->Print(
-      "if (_has_bit($index$)) {\n",
-      "index", SimpleItoa(field->index()));
+      "if (has_$name$()) {\n",
+      "name", FieldName(field));
     printer->Indent();
   }
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index c04bdc6..23e75b8 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -75,7 +75,8 @@
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
     "inline const $type$& $name$() const$deprecation$;\n"
-    "inline $type$* mutable_$name$()$deprecation$;\n");
+    "inline $type$* mutable_$name$()$deprecation$;\n"
+    "inline $type$* release_$name$()$deprecation$;\n");
 }
 
 void MessageFieldGenerator::
@@ -85,9 +86,15 @@
     "  return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n"
     "}\n"
     "inline $type$* $classname$::mutable_$name$() {\n"
-    "  _set_bit($index$);\n"
+    "  set_has_$name$();\n"
     "  if ($name$_ == NULL) $name$_ = new $type$;\n"
     "  return $name$_;\n"
+    "}\n"
+    "inline $type$* $classname$::release_$name$() {\n"
+    "  clear_has_$name$();\n"
+    "  $type$* temp = $name$_;\n"
+    "  $name$_ = NULL;\n"
+    "  return temp;\n"
     "}\n");
 }
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
index 440b716..5c4aa4f 100644
--- a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
@@ -56,24 +56,24 @@
 
   virtual bool Generate(const FileDescriptor* file,
                         const string& parameter,
-                        OutputDirectory* output_directory,
+                        GeneratorContext* context,
                         string* error) const {
-    TryInsert("test.pb.h", "includes", output_directory);
-    TryInsert("test.pb.h", "namespace_scope", output_directory);
-    TryInsert("test.pb.h", "global_scope", output_directory);
-    TryInsert("test.pb.h", "class_scope:foo.Bar", output_directory);
-    TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", output_directory);
+    TryInsert("test.pb.h", "includes", context);
+    TryInsert("test.pb.h", "namespace_scope", context);
+    TryInsert("test.pb.h", "global_scope", context);
+    TryInsert("test.pb.h", "class_scope:foo.Bar", context);
+    TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", context);
 
-    TryInsert("test.pb.cc", "includes", output_directory);
-    TryInsert("test.pb.cc", "namespace_scope", output_directory);
-    TryInsert("test.pb.cc", "global_scope", output_directory);
+    TryInsert("test.pb.cc", "includes", context);
+    TryInsert("test.pb.cc", "namespace_scope", context);
+    TryInsert("test.pb.cc", "global_scope", context);
     return true;
   }
 
   void TryInsert(const string& filename, const string& insertion_point,
-                 OutputDirectory* output_directory) const {
+                 GeneratorContext* context) const {
     scoped_ptr<io::ZeroCopyOutputStream> output(
-      output_directory->OpenForInsert(filename, insertion_point));
+      context->OpenForInsert(filename, insertion_point));
     io::Printer printer(output.get(), '$');
     printer.Print("// inserted $name$\n", "name", insertion_point);
   }
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index a69c48b..5e8df0f 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -125,7 +125,7 @@
     "  return $name$_;\n"
     "}\n"
     "inline void $classname$::set_$name$($type$ value) {\n"
-    "  _set_bit($index$);\n"
+    "  set_has_$name$();\n"
     "  $name$_ = value;\n"
     "}\n");
 }
@@ -156,7 +156,7 @@
     "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
     "         $type$, $wire_format_field_type$>(\n"
     "       input, &$name$_)));\n"
-    "_set_bit($index$);\n");
+    "set_has_$name$();\n");
 }
 
 void PrimitiveFieldGenerator::
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index ea6809a..67d7eae 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -50,6 +50,9 @@
   SetCommonFieldVariables(descriptor, variables);
   (*variables)["default"] =
     "\"" + CEscape(descriptor->default_value_string()) + "\"";
+  (*variables)["default_variable"] = descriptor->default_value_string().empty()
+      ? "::google::protobuf::internal::kEmptyString"
+      : "_default_" + FieldName(descriptor) + "_";
   (*variables)["pointer_type"] =
       descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
 }
@@ -68,9 +71,10 @@
 
 void StringFieldGenerator::
 GeneratePrivateMembers(io::Printer* printer) const {
-  printer->Print(variables_,
-    "::std::string* $name$_;\n"
-    "static const ::std::string _default_$name$_;\n");
+  printer->Print(variables_, "::std::string* $name$_;\n");
+  if (!descriptor_->default_value_string().empty()) {
+    printer->Print(variables_, "static const ::std::string $default_variable$;\n");
+  }
 }
 
 void StringFieldGenerator::
@@ -105,7 +109,8 @@
     "inline void set_$name$(const char* value)$deprecation$;\n"
     "inline void set_$name$(const $pointer_type$* value, size_t size)"
                  "$deprecation$;\n"
-    "inline ::std::string* mutable_$name$()$deprecation$;\n");
+    "inline ::std::string* mutable_$name$()$deprecation$;\n"
+    "inline ::std::string* release_$name$()$deprecation$;\n");
 
   if (descriptor_->options().ctype() != FieldOptions::STRING) {
     printer->Outdent();
@@ -121,51 +126,58 @@
     "  return *$name$_;\n"
     "}\n"
     "inline void $classname$::set_$name$(const ::std::string& value) {\n"
-    "  _set_bit($index$);\n"
-    "  if ($name$_ == &_default_$name$_) {\n"
+    "  set_has_$name$();\n"
+    "  if ($name$_ == &$default_variable$) {\n"
     "    $name$_ = new ::std::string;\n"
     "  }\n"
     "  $name$_->assign(value);\n"
     "}\n"
     "inline void $classname$::set_$name$(const char* value) {\n"
-    "  _set_bit($index$);\n"
-    "  if ($name$_ == &_default_$name$_) {\n"
+    "  set_has_$name$();\n"
+    "  if ($name$_ == &$default_variable$) {\n"
     "    $name$_ = new ::std::string;\n"
     "  }\n"
     "  $name$_->assign(value);\n"
     "}\n"
     "inline "
     "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
-    "  _set_bit($index$);\n"
-    "  if ($name$_ == &_default_$name$_) {\n"
+    "  set_has_$name$();\n"
+    "  if ($name$_ == &$default_variable$) {\n"
     "    $name$_ = new ::std::string;\n"
     "  }\n"
     "  $name$_->assign(reinterpret_cast<const char*>(value), size);\n"
     "}\n"
     "inline ::std::string* $classname$::mutable_$name$() {\n"
-    "  _set_bit($index$);\n"
-    "  if ($name$_ == &_default_$name$_) {\n");
+    "  set_has_$name$();\n"
+    "  if ($name$_ == &$default_variable$) {\n");
   if (descriptor_->default_value_string().empty()) {
     printer->Print(variables_,
       "    $name$_ = new ::std::string;\n");
   } else {
     printer->Print(variables_,
-      "    $name$_ = new ::std::string(_default_$name$_);\n");
+      "    $name$_ = new ::std::string($default_variable$);\n");
   }
   printer->Print(variables_,
     "  }\n"
     "  return $name$_;\n"
+    "}\n"
+    "inline ::std::string* $classname$::release_$name$() {\n"
+    "  clear_has_$name$();\n"
+    "  if ($name$_ == &$default_variable$) {\n"
+    "    return NULL;\n"
+    "  } else {\n"
+    "    ::std::string* temp = $name$_;\n"
+    "    $name$_ = const_cast< ::std::string*>(&$default_variable$);\n"
+    "    return temp;\n"
+    "  }\n"
     "}\n");
 }
 
 void StringFieldGenerator::
 GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
-  if (descriptor_->default_value_string().empty()) {
+  if (!descriptor_->default_value_string().empty()) {
     printer->Print(variables_,
-      "const ::std::string $classname$::_default_$name$_;\n");
-  } else {
-    printer->Print(variables_,
-      "const ::std::string $classname$::_default_$name$_($default$);\n");
+      "const ::std::string $classname$::$default_variable$($default$);\n");
   }
 }
 
@@ -173,13 +185,13 @@
 GenerateClearingCode(io::Printer* printer) const {
   if (descriptor_->default_value_string().empty()) {
     printer->Print(variables_,
-      "if ($name$_ != &_default_$name$_) {\n"
+      "if ($name$_ != &$default_variable$) {\n"
       "  $name$_->clear();\n"
       "}\n");
   } else {
     printer->Print(variables_,
-      "if ($name$_ != &_default_$name$_) {\n"
-      "  $name$_->assign(_default_$name$_);\n"
+      "if ($name$_ != &$default_variable$) {\n"
+      "  $name$_->assign($default_variable$);\n"
       "}\n");
   }
 }
@@ -197,13 +209,13 @@
 void StringFieldGenerator::
 GenerateConstructorCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "$name$_ = const_cast< ::std::string*>(&_default_$name$_);\n");
+    "$name$_ = const_cast< ::std::string*>(&$default_variable$);\n");
 }
 
 void StringFieldGenerator::
 GenerateDestructorCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if ($name$_ != &_default_$name$_) {\n"
+    "if ($name$_ != &$default_variable$) {\n"
     "  delete $name$_;\n"
     "}\n");
 }
diff --git a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
index 79971a9..54d830f 100644
--- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -36,6 +36,10 @@
 // though the same identifiers are used internally by the C++ code generator.
 
 
+// Some generic_services option(s) added automatically.
+// See:  http://go/proto2-generic-services-default
+option cc_generic_services = true;     // auto-added
+
 // We don't put this in a package within proto2 because we need to make sure
 // that the generated code doesn't depend on being in the proto2 namespace.
 package protobuf_unittest;
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index a7e852d..41ba5e4 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -195,6 +195,48 @@
   EXPECT_EQ("hello", *message.mutable_default_string());
 }
 
+TEST(GeneratedMessageTest, ReleaseString) {
+  // Check that release_foo() starts out NULL, and gives us a value
+  // that we can delete after it's been set.
+  unittest::TestAllTypes message;
+
+  EXPECT_EQ(NULL, message.release_default_string());
+  EXPECT_FALSE(message.has_default_string());
+  EXPECT_EQ("hello", message.default_string());
+
+  message.set_default_string("blah");
+  EXPECT_TRUE(message.has_default_string());
+  string* str = message.release_default_string();
+  EXPECT_FALSE(message.has_default_string());
+  ASSERT_TRUE(str != NULL);
+  EXPECT_EQ("blah", *str);
+  delete str;
+
+  EXPECT_EQ(NULL, message.release_default_string());
+  EXPECT_FALSE(message.has_default_string());
+  EXPECT_EQ("hello", message.default_string());
+}
+
+TEST(GeneratedMessageTest, ReleaseMessage) {
+  // Check that release_foo() starts out NULL, and gives us a value
+  // that we can delete after it's been set.
+  unittest::TestAllTypes message;
+
+  EXPECT_EQ(NULL, message.release_optional_nested_message());
+  EXPECT_FALSE(message.has_optional_nested_message());
+
+  message.mutable_optional_nested_message()->set_bb(1);
+  unittest::TestAllTypes::NestedMessage* nest =
+      message.release_optional_nested_message();
+  EXPECT_FALSE(message.has_optional_nested_message());
+  ASSERT_TRUE(nest != NULL);
+  EXPECT_EQ(1, nest->bb());
+  delete nest;
+
+  EXPECT_EQ(NULL, message.release_optional_nested_message());
+  EXPECT_FALSE(message.has_optional_nested_message());
+}
+
 TEST(GeneratedMessageTest, Clear) {
   // Set every field to a unique value, clear the message, then check that
   // it is cleared.
@@ -282,6 +324,7 @@
   TestUtil::ExpectAllFieldsSet(message2);
 }
 
+
 TEST(GeneratedMessageTest, SwapWithEmpty) {
   unittest::TestAllTypes message1, message2;
   TestUtil::SetAllFields(&message1);
@@ -376,7 +419,7 @@
   TestUtil::ExpectAllFieldsSet(message2);
 
   // Make sure that self-assignment does something sane.
-  message2 = message2;
+  message2.operator=(message2);
   TestUtil::ExpectAllFieldsSet(message2);
 }
 
@@ -718,6 +761,7 @@
 
 #endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
 
+
 TEST(GeneratedMessageTest, FieldConstantValues) {
   unittest::TestRequired message;
   EXPECT_EQ(unittest::TestAllTypes_NestedMessage::kBbFieldNumber, 1);
diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc
index e796587..9d7bcab 100644
--- a/src/google/protobuf/compiler/java/java_enum.cc
+++ b/src/google/protobuf/compiler/java/java_enum.cc
@@ -104,6 +104,15 @@
       "public static final $classname$ $name$ = $canonical_name$;\n");
   }
 
+  for (int i = 0; i < descriptor_->value_count(); i++) {
+    map<string, string> vars;
+    vars["name"] = descriptor_->value(i)->name();
+    vars["number"] = SimpleItoa(descriptor_->value(i)->number());
+    printer->Print(vars,
+      "public static final int $name$_VALUE = $number$;\n");
+  }
+  printer->Print("\n");
+
   // -----------------------------------------------------------------
 
   printer->Print(
@@ -219,17 +228,6 @@
     "  this.value = value;\n"
     "}\n");
 
-  if (HasDescriptorMethods(descriptor_)) {
-    // Force the static initialization code for the file to run, since it may
-    // initialize static variables declared in this class.
-    printer->Print(
-      "\n"
-      "static {\n"
-      "  $file$.getDescriptor();\n"
-      "}\n",
-      "file", ClassName(descriptor_->file()));
-  }
-
   printer->Print(
     "\n"
     "// @@protoc_insertion_point(enum_scope:$full_name$)\n",
diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
index af6b1cd..72caa10 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -52,17 +52,44 @@
 // TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
 //   repeat code between this and the other field types.
 void SetEnumVariables(const FieldDescriptor* descriptor,
+                      int messageBitIndex,
+                      int builderBitIndex,
                       map<string, string>* variables) {
   (*variables)["name"] =
     UnderscoresToCamelCase(descriptor);
   (*variables)["capitalized_name"] =
     UnderscoresToCapitalizedCamelCase(descriptor);
+  (*variables)["constant_name"] = FieldConstantName(descriptor);
   (*variables)["number"] = SimpleItoa(descriptor->number());
   (*variables)["type"] = ClassName(descriptor->enum_type());
   (*variables)["default"] = DefaultValue(descriptor);
   (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
   (*variables)["tag_size"] = SimpleItoa(
       internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+  // by the proto compiler
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
+  (*variables)["on_changed"] =
+      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+
+  // For singular messages and builders, one bit is used for the hasField bit.
+  (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+  (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_has_field_bit_builder"] =
+      GenerateClearBit(builderBitIndex);
+
+  // For repated builders, one bit is used for whether the array is immutable.
+  (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
+
+  (*variables)["get_has_field_bit_from_local"] =
+      GenerateGetBitFromLocal(builderBitIndex);
+  (*variables)["set_has_field_bit_to_local"] =
+      GenerateSetBitToLocal(messageBitIndex);
 }
 
 }  // namespace
@@ -70,52 +97,88 @@
 // ===================================================================
 
 EnumFieldGenerator::
-EnumFieldGenerator(const FieldDescriptor* descriptor)
-  : descriptor_(descriptor) {
-  SetEnumVariables(descriptor, &variables_);
+EnumFieldGenerator(const FieldDescriptor* descriptor,
+                      int messageBitIndex,
+                      int builderBitIndex)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex) {
+  SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_);
 }
 
 EnumFieldGenerator::~EnumFieldGenerator() {}
 
+int EnumFieldGenerator::GetNumBitsForMessage() const {
+  return 1;
+}
+
+int EnumFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void EnumFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$deprecation$boolean has$capitalized_name$();\n"
+    "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
 void EnumFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private boolean has$capitalized_name$;\n"
     "private $type$ $name$_;\n"
-    "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
-    "public $type$ get$capitalized_name$() { return $name$_; }\n");
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_message$;\n"
+    "}\n"
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return $name$_;\n"
+    "}\n");
 }
 
 void EnumFieldGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "public boolean has$capitalized_name$() {\n"
-    "  return result.has$capitalized_name$();\n"
+    "private $type$ $name$_ = $default$;\n"
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_builder$;\n"
     "}\n"
-    "public $type$ get$capitalized_name$() {\n"
-    "  return result.get$capitalized_name$();\n"
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return $name$_;\n"
     "}\n"
-    "public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
     "  if (value == null) {\n"
     "    throw new NullPointerException();\n"
     "  }\n"
-    "  result.has$capitalized_name$ = true;\n"
-    "  result.$name$_ = value;\n"
+    "  $set_has_field_bit_builder$;\n"
+    "  $name$_ = value;\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n"
-    "public Builder clear$capitalized_name$() {\n"
-    "  result.has$capitalized_name$ = false;\n"
-    "  result.$name$_ = $default$;\n"
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  $clear_has_field_bit_builder$;\n"
+    "  $name$_ = $default$;\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n");
 }
 
 void EnumFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for enums
+}
+
+void EnumFieldGenerator::
 GenerateInitializationCode(io::Printer* printer) const {
   printer->Print(variables_, "$name$_ = $default$;\n");
 }
 
 void EnumFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+      "$name$_ = $default$;\n"
+      "$clear_has_field_bit_builder$;\n");
+}
+
+void EnumFieldGenerator::
 GenerateMergingCode(io::Printer* printer) const {
   printer->Print(variables_,
     "if (other.has$capitalized_name$()) {\n"
@@ -125,7 +188,11 @@
 
 void EnumFieldGenerator::
 GenerateBuildingCode(io::Printer* printer) const {
-  // Nothing to do here for enum types.
+  printer->Print(variables_,
+    "if ($get_has_field_bit_from_local$) {\n"
+    "  $set_has_field_bit_to_local$;\n"
+    "}\n"
+    "result.$name$_ = $name$_;\n");
 }
 
 void EnumFieldGenerator::
@@ -143,27 +210,42 @@
       "if (value != null) {\n");
   }
   printer->Print(variables_,
-    "  set$capitalized_name$(value);\n"
+    "  $set_has_field_bit_builder$;\n"
+    "  $name$_ = value;\n"
     "}\n");
 }
 
 void EnumFieldGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (has$capitalized_name$()) {\n"
-    "  output.writeEnum($number$, get$capitalized_name$().getNumber());\n"
+    "if ($get_has_field_bit_message$) {\n"
+    "  output.writeEnum($number$, $name$_.getNumber());\n"
     "}\n");
 }
 
 void EnumFieldGenerator::
 GenerateSerializedSizeCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (has$capitalized_name$()) {\n"
+    "if ($get_has_field_bit_message$) {\n"
     "  size += com.google.protobuf.CodedOutputStream\n"
-    "    .computeEnumSize($number$, get$capitalized_name$().getNumber());\n"
+    "    .computeEnumSize($number$, $name$_.getNumber());\n"
     "}\n");
 }
 
+void EnumFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result &&\n"
+    "    (get$capitalized_name$() == other.get$capitalized_name$());\n");
+}
+
+void EnumFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "hash = (37 * hash) + $constant_name$;\n"
+    "hash = (53 * hash) + hashEnum(get$capitalized_name$());\n");
+}
+
 string EnumFieldGenerator::GetBoxedType() const {
   return ClassName(descriptor_->enum_type());
 }
@@ -171,23 +253,43 @@
 // ===================================================================
 
 RepeatedEnumFieldGenerator::
-RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor)
-  : descriptor_(descriptor) {
-  SetEnumVariables(descriptor, &variables_);
+RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+                           int messageBitIndex,
+                           int builderBitIndex)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex) {
+  SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_);
 }
 
 RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
 
+int RepeatedEnumFieldGenerator::GetNumBitsForMessage() const {
+  return 0;
+}
+
+int RepeatedEnumFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n"
+    "$deprecation$int get$capitalized_name$Count();\n"
+    "$deprecation$$type$ get$capitalized_name$(int index);\n");
+}
+
 void RepeatedEnumFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private java.util.List<$type$> $name$_ =\n"
-    "  java.util.Collections.emptyList();\n"
-    "public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "private java.util.List<$type$> $name$_;\n"
+    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
     "}\n"
-    "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
-    "public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n"
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
 
@@ -201,73 +303,119 @@
 void RepeatedEnumFieldGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
   printer->Print(variables_,
+    // One field is the list and the other field keeps track of whether the
+    // list is immutable. If it's immutable, the invariant is that it must
+    // either an instance of Collections.emptyList() or it's an ArrayList
+    // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
+    // a refererence to the underlying ArrayList. This invariant allows us to
+    // share instances of lists between protocol buffers avoiding expensive
+    // memory allocations. Note, immutable is a strong guarantee here -- not
+    // just that the list cannot be modified via the reference but that the
+    // list can never be modified.
+    "private java.util.List<$type$> $name$_ =\n"
+    "  java.util.Collections.emptyList();\n"
+
+    "private void ensure$capitalized_name$IsMutable() {\n"
+    "  if (!$get_mutable_bit_builder$) {\n"
+    "    $name$_ = new java.util.ArrayList<$type$>($name$_);\n"
+    "    $set_mutable_bit_builder$;\n"
+    "  }\n"
+    "}\n"
+
     // Note:  We return an unmodifiable list because otherwise the caller
     //   could hold on to the returned list and modify it after the message
     //   has been built, thus mutating the message which is supposed to be
     //   immutable.
-    "public java.util.List<$type$> get$capitalized_name$List() {\n"
-    "  return java.util.Collections.unmodifiableList(result.$name$_);\n"
+    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "  return java.util.Collections.unmodifiableList($name$_);\n"
     "}\n"
-    "public int get$capitalized_name$Count() {\n"
-    "  return result.get$capitalized_name$Count();\n"
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
     "}\n"
-    "public $type$ get$capitalized_name$(int index) {\n"
-    "  return result.get$capitalized_name$(index);\n"
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return $name$_.get(index);\n"
     "}\n"
-    "public Builder set$capitalized_name$(int index, $type$ value) {\n"
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$ value) {\n"
     "  if (value == null) {\n"
     "    throw new NullPointerException();\n"
     "  }\n"
-    "  result.$name$_.set(index, value);\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.set(index, value);\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n"
-    "public Builder add$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
     "  if (value == null) {\n"
     "    throw new NullPointerException();\n"
     "  }\n"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
-    "  }\n"
-    "  result.$name$_.add(value);\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(value);\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n"
-    "public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder addAll$capitalized_name$(\n"
     "    java.lang.Iterable<? extends $type$> values) {\n"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
-    "  }\n"
-    "  super.addAll(values, result.$name$_);\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  super.addAll(values, $name$_);\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n"
-    "public Builder clear$capitalized_name$() {\n"
-    "  result.$name$_ = java.util.Collections.emptyList();\n"
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  $name$_ = java.util.Collections.emptyList();\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n");
 }
 
 void RepeatedEnumFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for enums
+}
+
+void RepeatedEnumFieldGenerator::
 GenerateInitializationCode(io::Printer* printer) const {
-  // Initialized inline.
+  printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = java.util.Collections.emptyList();\n"
+    "$clear_mutable_bit_builder$;\n");
 }
 
 void RepeatedEnumFieldGenerator::
 GenerateMergingCode(io::Printer* printer) const {
+  // The code below does two optimizations:
+  //   1. If the other list is empty, there's nothing to do. This ensures we
+  //      don't allocate a new array if we already have an immutable one.
+  //   2. If the other list is non-empty and our current list is empty, we can
+  //      reuse the other list which is guaranteed to be immutable.
   printer->Print(variables_,
     "if (!other.$name$_.isEmpty()) {\n"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
+    "  if ($name$_.isEmpty()) {\n"
+    "    $name$_ = other.$name$_;\n"
+    "    $clear_mutable_bit_builder$;\n"
+    "  } else {\n"
+    "    ensure$capitalized_name$IsMutable();\n"
+    "    $name$_.addAll(other.$name$_);\n"
     "  }\n"
-    "  result.$name$_.addAll(other.$name$_);\n"
+    "  $on_changed$\n"
     "}\n");
 }
 
 void RepeatedEnumFieldGenerator::
 GenerateBuildingCode(io::Printer* printer) const {
+  // The code below ensures that the result has an immutable list. If our
+  // list is immutable, we can just reuse it. If not, we make it immutable.
   printer->Print(variables_,
-    "if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n"
-    "  result.$name$_ =\n"
-    "    java.util.Collections.unmodifiableList(result.$name$_);\n"
-    "}\n");
+    "if ($get_mutable_bit_builder$) {\n"
+    "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "}\n"
+    "result.$name$_ = $name$_;\n");
 }
 
 void RepeatedEnumFieldGenerator::
@@ -316,13 +464,13 @@
       "  output.writeRawVarint32($tag$);\n"
       "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
       "}\n"
-      "for ($type$ element : get$capitalized_name$List()) {\n"
-      "  output.writeEnumNoTag(element.getNumber());\n"
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.writeEnumNoTag($name$_.get(i).getNumber());\n"
       "}\n");
   } else {
     printer->Print(variables_,
-      "for ($type$ element : get$capitalized_name$List()) {\n"
-      "  output.writeEnum($number$, element.getNumber());\n"
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.writeEnum($number$, $name$_.get(i).getNumber());\n"
       "}\n");
   }
 }
@@ -335,9 +483,9 @@
   printer->Indent();
 
   printer->Print(variables_,
-    "for ($type$ element : get$capitalized_name$List()) {\n"
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
     "  dataSize += com.google.protobuf.CodedOutputStream\n"
-    "    .computeEnumSizeNoTag(element.getNumber());\n"
+    "    .computeEnumSizeNoTag($name$_.get(i).getNumber());\n"
     "}\n");
   printer->Print(
     "size += dataSize;\n");
@@ -350,7 +498,7 @@
       "}");
   } else {
     printer->Print(variables_,
-      "size += $tag_size$ * get$capitalized_name$List().size();\n");
+      "size += $tag_size$ * $name$_.size();\n");
   }
 
   // cache the data size for packed fields.
@@ -363,6 +511,22 @@
   printer->Print("}\n");
 }
 
+void RepeatedEnumFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$List()\n"
+    "    .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (get$capitalized_name$Count() > 0) {\n"
+    "  hash = (37 * hash) + $constant_name$;\n"
+    "  hash = (53 * hash) + hashEnumList(get$capitalized_name$List());\n"
+    "}\n");
+}
+
 string RepeatedEnumFieldGenerator::GetBoxedType() const {
   return ClassName(descriptor_->enum_type());
 }
diff --git a/src/google/protobuf/compiler/java/java_enum_field.h b/src/google/protobuf/compiler/java/java_enum_field.h
index c54a0fa..0cad6be 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.h
+++ b/src/google/protobuf/compiler/java/java_enum_field.h
@@ -46,49 +46,69 @@
 
 class EnumFieldGenerator : public FieldGenerator {
  public:
-  explicit EnumFieldGenerator(const FieldDescriptor* descriptor);
+  explicit EnumFieldGenerator(const FieldDescriptor* descriptor,
+      int messageBitIndex, int builderBitIndex);
   ~EnumFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
 
   string GetBoxedType() const;
 
  private:
   const FieldDescriptor* descriptor_;
   map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
 };
 
 class RepeatedEnumFieldGenerator : public FieldGenerator {
  public:
-  explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor);
+  explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+      int messageBitIndex, int builderBitIndex);
   ~RepeatedEnumFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateParsingCodeFromPacked(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
 
   string GetBoxedType() const;
 
  private:
   const FieldDescriptor* descriptor_;
   map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
 };
diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc
index 903b0a9..9b147c7 100644
--- a/src/google/protobuf/compiler/java/java_extension.cc
+++ b/src/google/protobuf/compiler/java/java_extension.cc
@@ -86,105 +86,120 @@
 
 ExtensionGenerator::~ExtensionGenerator() {}
 
-void ExtensionGenerator::Generate(io::Printer* printer) {
-  map<string, string> vars;
-  vars["name"] = UnderscoresToCamelCase(descriptor_);
-  vars["containing_type"] = ClassName(descriptor_->containing_type());
-  vars["number"] = SimpleItoa(descriptor_->number());
-  vars["constant_name"] = FieldConstantName(descriptor_);
-  vars["lite"] = HasDescriptorMethods(descriptor_->file()) ? "" : "Lite";
-
-  JavaType java_type = GetJavaType(descriptor_);
-  string singular_type;
-  switch (java_type) {
-    case JAVATYPE_MESSAGE:
-      vars["type"] = ClassName(descriptor_->message_type());
-      break;
-    case JAVATYPE_ENUM:
-      vars["type"] = ClassName(descriptor_->enum_type());
-      break;
-    default:
-      vars["type"] = BoxedPrimitiveTypeName(java_type);
-      break;
-  }
-
-  printer->Print(vars,
-    "public static final int $constant_name$ = $number$;\n");
-  if (descriptor_->is_repeated()) {
-    printer->Print(vars,
-      "public static final\n"
-      "  com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n"
-      "    $containing_type$,\n"
-      "    java.util.List<$type$>> $name$ =\n"
-      "      com.google.protobuf.GeneratedMessage$lite$\n"
-      "        .newGeneratedExtension();\n");
-  } else {
-    printer->Print(vars,
-      "public static final\n"
-      "  com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n"
-      "    $containing_type$,\n"
-      "    $type$> $name$ =\n"
-      "      com.google.protobuf.GeneratedMessage$lite$\n"
-      "        .newGeneratedExtension();\n");
-  }
-}
-
-void ExtensionGenerator::GenerateInitializationCode(io::Printer* printer) {
-  map<string, string> vars;
-  vars["name"] = UnderscoresToCamelCase(descriptor_);
-  vars["scope"] = scope_;
-  vars["index"] = SimpleItoa(descriptor_->index());
-  vars["extendee"] = ClassName(descriptor_->containing_type());
-  vars["default"] = descriptor_->is_repeated() ? "" : DefaultValue(descriptor_);
-  vars["number"] = SimpleItoa(descriptor_->number());
-  vars["type_constant"] = TypeName(GetType(descriptor_));
-  vars["packed"] = descriptor_->options().packed() ? "true" : "false";
+// Initializes the vars referenced in the generated code templates.
+void InitTemplateVars(const FieldDescriptor* descriptor,
+                      const string& scope,
+                      map<string, string>* vars_pointer) {
+  map<string, string> &vars = *vars_pointer;
+  vars["scope"] = scope;
+  vars["name"] = UnderscoresToCamelCase(descriptor);
+  vars["containing_type"] = ClassName(descriptor->containing_type());
+  vars["number"] = SimpleItoa(descriptor->number());
+  vars["constant_name"] = FieldConstantName(descriptor);
+  vars["index"] = SimpleItoa(descriptor->index());
+  vars["default"] =
+      descriptor->is_repeated() ? "" : DefaultValue(descriptor);
+  vars["type_constant"] = TypeName(GetType(descriptor));
+  vars["packed"] = descriptor->options().packed() ? "true" : "false";
   vars["enum_map"] = "null";
   vars["prototype"] = "null";
 
-  JavaType java_type = GetJavaType(descriptor_);
+  JavaType java_type = GetJavaType(descriptor);
   string singular_type;
   switch (java_type) {
     case JAVATYPE_MESSAGE:
-      vars["type"] = ClassName(descriptor_->message_type());
-      vars["prototype"] = ClassName(descriptor_->message_type()) +
-                          ".getDefaultInstance()";
+      singular_type = ClassName(descriptor->message_type());
+      vars["prototype"] = singular_type + ".getDefaultInstance()";
       break;
     case JAVATYPE_ENUM:
-      vars["type"] = ClassName(descriptor_->enum_type());
-      vars["enum_map"] = ClassName(descriptor_->enum_type()) +
-                         ".internalGetValueMap()";
+      singular_type = ClassName(descriptor->enum_type());
+      vars["enum_map"] = singular_type + ".internalGetValueMap()";
       break;
     default:
-      vars["type"] = BoxedPrimitiveTypeName(java_type);
+      singular_type = BoxedPrimitiveTypeName(java_type);
       break;
   }
+  vars["type"] = descriptor->is_repeated() ?
+      "java.util.List<" + singular_type + ">" : singular_type;
+  vars["singular_type"] = singular_type;
+}
+
+void ExtensionGenerator::Generate(io::Printer* printer) {
+  map<string, string> vars;
+  InitTemplateVars(descriptor_, scope_, &vars);
+  printer->Print(vars,
+      "public static final int $constant_name$ = $number$;\n");
 
   if (HasDescriptorMethods(descriptor_->file())) {
-    printer->Print(vars,
-      "$scope$.$name$.internalInit(\n"
-      "    $scope$.getDescriptor().getExtensions().get($index$),\n"
-      "    $type$.class);\n");
-  } else {
-    if (descriptor_->is_repeated()) {
-      printer->Print(vars,
-        "$scope$.$name$.internalInitRepeated(\n"
-        "    $extendee$.getDefaultInstance(),\n"
-        "    $prototype$,\n"
-        "    $enum_map$,\n"
-        "    $number$,\n"
-        "    com.google.protobuf.WireFormat.FieldType.$type_constant$,\n"
-        "    $packed$);\n");
+    // Non-lite extensions
+    if (descriptor_->extension_scope() == NULL) {
+      // Non-nested
+      printer->Print(
+          vars,
+          "public static final\n"
+          "  com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+          "    $containing_type$,\n"
+          "    $type$> $name$ = com.google.protobuf.GeneratedMessage\n"
+          "        .newFileScopedGeneratedExtension(\n"
+          "      $singular_type$.class,\n"
+          "      $prototype$);\n");
     } else {
-      printer->Print(vars,
-        "$scope$.$name$.internalInitSingular(\n"
-        "    $extendee$.getDefaultInstance(),\n"
-        "    $default$,\n"
-        "    $prototype$,\n"
-        "    $enum_map$,\n"
-        "    $number$,\n"
-        "    com.google.protobuf.WireFormat.FieldType.$type_constant$);\n");
+      // Nested
+      printer->Print(
+          vars,
+          "public static final\n"
+          "  com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+          "    $containing_type$,\n"
+          "    $type$> $name$ = com.google.protobuf.GeneratedMessage\n"
+          "        .newMessageScopedGeneratedExtension(\n"
+          "      $scope$.getDefaultInstance(),\n"
+          "      $index$,\n"
+          "      $singular_type$.class,\n"
+          "      $prototype$);\n");
     }
+  } else {
+    // Lite extensions
+    if (descriptor_->is_repeated()) {
+      printer->Print(
+          vars,
+          "public static final\n"
+          "  com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n"
+          "    $containing_type$,\n"
+          "    $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n"
+          "        .newRepeatedGeneratedExtension(\n"
+          "      $containing_type$.getDefaultInstance(),\n"
+          "      $prototype$,\n"
+          "      $enum_map$,\n"
+          "      $number$,\n"
+          "      com.google.protobuf.WireFormat.FieldType.$type_constant$,\n"
+          "      $packed$);\n");
+    } else {
+      printer->Print(
+          vars,
+          "public static final\n"
+          "  com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n"
+          "    $containing_type$,\n"
+          "    $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n"
+          "        .newSingularGeneratedExtension(\n"
+          "      $containing_type$.getDefaultInstance(),\n"
+          "      $default$,\n"
+          "      $prototype$,\n"
+          "      $enum_map$,\n"
+          "      $number$,\n"
+          "      com.google.protobuf.WireFormat.FieldType.$type_constant$);\n");
+    }
+  }
+}
+
+void ExtensionGenerator::GenerateNonNestedInitializationCode(
+    io::Printer* printer) {
+  if (descriptor_->extension_scope() == NULL &&
+      HasDescriptorMethods(descriptor_->file())) {
+    // Only applies to non-nested, non-lite extensions.
+    printer->Print(
+        "$name$.internalInit(descriptor.getExtensions().get($index$));\n",
+        "name", UnderscoresToCamelCase(descriptor_),
+        "index", SimpleItoa(descriptor_->index()));
   }
 }
 
diff --git a/src/google/protobuf/compiler/java/java_extension.h b/src/google/protobuf/compiler/java/java_extension.h
index 1e42304..009ed9f 100644
--- a/src/google/protobuf/compiler/java/java_extension.h
+++ b/src/google/protobuf/compiler/java/java_extension.h
@@ -60,7 +60,7 @@
   ~ExtensionGenerator();
 
   void Generate(io::Printer* printer);
-  void GenerateInitializationCode(io::Printer* printer);
+  void GenerateNonNestedInitializationCode(io::Printer* printer);
   void GenerateRegistrationCode(io::Printer* printer);
 
  private:
diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc
index 978c8f3..c7d433c 100644
--- a/src/google/protobuf/compiler/java/java_field.cc
+++ b/src/google/protobuf/compiler/java/java_field.cc
@@ -37,6 +37,7 @@
 #include <google/protobuf/compiler/java/java_primitive_field.h>
 #include <google/protobuf/compiler/java/java_enum_field.h>
 #include <google/protobuf/compiler/java/java_message_field.h>
+#include <google/protobuf/compiler/java/java_string_field.h>
 #include <google/protobuf/stubs/common.h>
 
 namespace google {
@@ -63,33 +64,57 @@
     extension_generators_(
       new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
 
-  // Construct all the FieldGenerators.
+  // Construct all the FieldGenerators and assign them bit indices for their
+  // bit fields.
+  int messageBitIndex = 0;
+  int builderBitIndex = 0;
   for (int i = 0; i < descriptor->field_count(); i++) {
-    field_generators_[i].reset(MakeGenerator(descriptor->field(i)));
+    FieldGenerator* generator = MakeGenerator(descriptor->field(i),
+        messageBitIndex, builderBitIndex);
+    field_generators_[i].reset(generator);
+    messageBitIndex += generator->GetNumBitsForMessage();
+    builderBitIndex += generator->GetNumBitsForBuilder();
   }
   for (int i = 0; i < descriptor->extension_count(); i++) {
-    extension_generators_[i].reset(MakeGenerator(descriptor->extension(i)));
+    FieldGenerator* generator = MakeGenerator(descriptor->extension(i),
+        messageBitIndex, builderBitIndex);
+    extension_generators_[i].reset(generator);
+    messageBitIndex += generator->GetNumBitsForMessage();
+    builderBitIndex += generator->GetNumBitsForBuilder();
   }
 }
 
-FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) {
+FieldGenerator* FieldGeneratorMap::MakeGenerator(
+    const FieldDescriptor* field, int messageBitIndex, int builderBitIndex) {
   if (field->is_repeated()) {
     switch (GetJavaType(field)) {
       case JAVATYPE_MESSAGE:
-        return new RepeatedMessageFieldGenerator(field);
+        return new RepeatedMessageFieldGenerator(
+            field, messageBitIndex, builderBitIndex);
       case JAVATYPE_ENUM:
-        return new RepeatedEnumFieldGenerator(field);
+        return new RepeatedEnumFieldGenerator(
+            field, messageBitIndex, builderBitIndex);
+      case JAVATYPE_STRING:
+        return new RepeatedStringFieldGenerator(
+            field, messageBitIndex, builderBitIndex);
       default:
-        return new RepeatedPrimitiveFieldGenerator(field);
+        return new RepeatedPrimitiveFieldGenerator(
+            field, messageBitIndex, builderBitIndex);
     }
   } else {
     switch (GetJavaType(field)) {
       case JAVATYPE_MESSAGE:
-        return new MessageFieldGenerator(field);
+        return new MessageFieldGenerator(
+            field, messageBitIndex, builderBitIndex);
       case JAVATYPE_ENUM:
-        return new EnumFieldGenerator(field);
+        return new EnumFieldGenerator(
+            field, messageBitIndex, builderBitIndex);
+      case JAVATYPE_STRING:
+        return new StringFieldGenerator(
+            field, messageBitIndex, builderBitIndex);
       default:
-        return new PrimitiveFieldGenerator(field);
+        return new PrimitiveFieldGenerator(
+            field, messageBitIndex, builderBitIndex);
     }
   }
 }
diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h
index f5bef7a..6097f35 100644
--- a/src/google/protobuf/compiler/java/java_field.h
+++ b/src/google/protobuf/compiler/java/java_field.h
@@ -55,15 +55,24 @@
   FieldGenerator() {}
   virtual ~FieldGenerator();
 
+  virtual int GetNumBitsForMessage() const = 0;
+  virtual int GetNumBitsForBuilder() const = 0;
+  virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0;
   virtual void GenerateMembers(io::Printer* printer) const = 0;
   virtual void GenerateBuilderMembers(io::Printer* printer) const = 0;
   virtual void GenerateInitializationCode(io::Printer* printer) const = 0;
+  virtual void GenerateBuilderClearCode(io::Printer* printer) const = 0;
   virtual void GenerateMergingCode(io::Printer* printer) const = 0;
   virtual void GenerateBuildingCode(io::Printer* printer) const = 0;
   virtual void GenerateParsingCode(io::Printer* printer) const = 0;
   virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const;
   virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
   virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
+  virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer)
+      const = 0;
+
+  virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
+  virtual void GenerateHashCode(io::Printer* printer) const = 0;
 
   virtual string GetBoxedType() const = 0;
 
@@ -85,7 +94,8 @@
   scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
   scoped_array<scoped_ptr<FieldGenerator> > extension_generators_;
 
-  static FieldGenerator* MakeGenerator(const FieldDescriptor* field);
+  static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
+      int messageBitIndex, int builderBitIndex);
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
 };
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index 7ea127c..8968069 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -88,7 +88,8 @@
 FileGenerator::FileGenerator(const FileDescriptor* file)
   : file_(file),
     java_package_(FileJavaPackage(file)),
-    classname_(FileClassName(file)) {}
+    classname_(FileClassName(file)) {
+}
 
 FileGenerator::~FileGenerator() {}
 
@@ -179,7 +180,9 @@
       EnumGenerator(file_->enum_type(i)).Generate(printer);
     }
     for (int i = 0; i < file_->message_type_count(); i++) {
-      MessageGenerator(file_->message_type(i)).Generate(printer);
+      MessageGenerator messageGenerator(file_->message_type(i));
+      messageGenerator.GenerateInterface(printer);
+      messageGenerator.Generate(printer);
     }
     if (HasGenericServices(file_)) {
       for (int i = 0; i < file_->service_count(); i++) {
@@ -215,24 +218,11 @@
         .GenerateStaticVariableInitializers(printer);
     }
 
-    for (int i = 0; i < file_->extension_count(); i++) {
-      // TODO(kenton):  Reuse ExtensionGenerator objects?
-      ExtensionGenerator(file_->extension(i))
-        .GenerateInitializationCode(printer);
-    }
-
     printer->Outdent();
     printer->Print(
       "}\n");
   }
 
-  // Dummy function we can use to force the static initialization block to
-  // run.  Needed by inner classes.  Cannot be private due to
-  // java_multiple_files option.
-  printer->Print(
-    "\n"
-    "public static void internalForceInit() {}\n");
-
   printer->Print(
     "\n"
     "// @@protoc_insertion_point(outer_class_scope)\n");
@@ -310,11 +300,10 @@
     MessageGenerator(file_->message_type(i))
       .GenerateStaticVariableInitializers(printer);
   }
-
   for (int i = 0; i < file_->extension_count(); i++) {
     // TODO(kenton):  Reuse ExtensionGenerator objects?
     ExtensionGenerator(file_->extension(i))
-      .GenerateInitializationCode(printer);
+        .GenerateNonNestedInitializationCode(printer);
   }
 
   if (UsesExtensions(file_proto)) {
@@ -325,9 +314,11 @@
       "  com.google.protobuf.ExtensionRegistry.newInstance();\n"
       "registerAllExtensions(registry);\n");
     for (int i = 0; i < file_->dependency_count(); i++) {
-      printer->Print(
-        "$dependency$.registerAllExtensions(registry);\n",
-        "dependency", ClassName(file_->dependency(i)));
+      if (ShouldIncludeDependency(file_->dependency(i))) {
+        printer->Print(
+            "$dependency$.registerAllExtensions(registry);\n",
+            "dependency", ClassName(file_->dependency(i)));
+      }
     }
     printer->Print(
       "return registry;\n");
@@ -372,13 +363,14 @@
 static void GenerateSibling(const string& package_dir,
                             const string& java_package,
                             const DescriptorClass* descriptor,
-                            OutputDirectory* output_directory,
-                            vector<string>* file_list) {
-  string filename = package_dir + descriptor->name() + ".java";
+                            GeneratorContext* context,
+                            vector<string>* file_list,
+                            const string& name_suffix,
+                            void (GeneratorClass::*pfn)(io::Printer* printer)) {
+  string filename = package_dir + descriptor->name() + name_suffix + ".java";
   file_list->push_back(filename);
 
-  scoped_ptr<io::ZeroCopyOutputStream> output(
-    output_directory->Open(filename));
+  scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
   io::Printer printer(output.get(), '$');
 
   printer.Print(
@@ -391,28 +383,36 @@
       "package", java_package);
   }
 
-  GeneratorClass(descriptor).Generate(&printer);
+  GeneratorClass generator(descriptor);
+  (generator.*pfn)(&printer);
 }
 
 void FileGenerator::GenerateSiblings(const string& package_dir,
-                                     OutputDirectory* output_directory,
+                                     GeneratorContext* context,
                                      vector<string>* file_list) {
   if (file_->options().java_multiple_files()) {
     for (int i = 0; i < file_->enum_type_count(); i++) {
       GenerateSibling<EnumGenerator>(package_dir, java_package_,
                                      file_->enum_type(i),
-                                     output_directory, file_list);
+                                     context, file_list, "",
+                                     &EnumGenerator::Generate);
     }
     for (int i = 0; i < file_->message_type_count(); i++) {
       GenerateSibling<MessageGenerator>(package_dir, java_package_,
                                         file_->message_type(i),
-                                        output_directory, file_list);
+                                        context, file_list, "OrBuilder",
+                                        &MessageGenerator::GenerateInterface);
+      GenerateSibling<MessageGenerator>(package_dir, java_package_,
+                                        file_->message_type(i),
+                                        context, file_list, "",
+                                        &MessageGenerator::Generate);
     }
     if (HasGenericServices(file_)) {
       for (int i = 0; i < file_->service_count(); i++) {
         GenerateSibling<ServiceGenerator>(package_dir, java_package_,
                                           file_->service(i),
-                                          output_directory, file_list);
+                                          context, file_list, "",
+                                          &ServiceGenerator::Generate);
       }
     }
   }
diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h
index 9e35d33..5991146 100644
--- a/src/google/protobuf/compiler/java/java_file.h
+++ b/src/google/protobuf/compiler/java/java_file.h
@@ -46,7 +46,7 @@
     class Printer;             // printer.h
   }
   namespace compiler {
-    class OutputDirectory;     // code_generator.h
+    class GeneratorContext;     // code_generator.h
   }
 }
 
@@ -70,12 +70,13 @@
   // files other than the outer file (i.e. one for each message, enum, and
   // service type).
   void GenerateSiblings(const string& package_dir,
-                        OutputDirectory* output_directory,
+                        GeneratorContext* generator_context,
                         vector<string>* file_list);
 
   const string& java_package() { return java_package_; }
   const string& classname()    { return classname_;    }
 
+
  private:
   // Returns whether the dependency should be included in the output file.
   // Always returns true for opensource, but used internally at Google to help
@@ -86,6 +87,7 @@
   string java_package_;
   string classname_;
 
+
   void GenerateEmbeddedDescriptor(io::Printer* printer);
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc
index 745b55a..e6c79ab 100644
--- a/src/google/protobuf/compiler/java/java_generator.cc
+++ b/src/google/protobuf/compiler/java/java_generator.cc
@@ -51,11 +51,8 @@
 
 bool JavaGenerator::Generate(const FileDescriptor* file,
                              const string& parameter,
-                             OutputDirectory* output_directory,
+                             GeneratorContext* context,
                              string* error) const {
-  vector<pair<string, string> > options;
-  ParseGeneratorParameter(parameter, &options);
-
   // -----------------------------------------------------------------
   // parse generator options
 
@@ -63,6 +60,10 @@
   // per line.
   string output_list_file;
 
+
+  vector<pair<string, string> > options;
+  ParseGeneratorParameter(parameter, &options);
+
   for (int i = 0; i < options.size(); i++) {
     if (options[i].first == "output_list_file") {
       output_list_file = options[i].second;
@@ -72,18 +73,23 @@
     }
   }
 
-
   // -----------------------------------------------------------------
 
 
+  if (file->options().optimize_for() == FileOptions::LITE_RUNTIME &&
+      file->options().java_generate_equals_and_hash()) {
+    *error = "The \"java_generate_equals_and_hash\" option is incompatible "
+             "with \"optimize_for = LITE_RUNTIME\".  You must optimize for "
+             "SPEED or CODE_SIZE if you want to use this option.";
+    return false;
+  }
+
   FileGenerator file_generator(file);
   if (!file_generator.Validate(error)) {
     return false;
   }
 
-  string package_dir =
-    StringReplace(file_generator.java_package(), ".", "/", true);
-  if (!package_dir.empty()) package_dir += "/";
+  string package_dir = JavaPackageToDir(file_generator.java_package());
 
   vector<string> all_files;
 
@@ -94,19 +100,19 @@
 
   // Generate main java file.
   scoped_ptr<io::ZeroCopyOutputStream> output(
-    output_directory->Open(java_filename));
+    context->Open(java_filename));
   io::Printer printer(output.get(), '$');
   file_generator.Generate(&printer);
 
   // Generate sibling files.
-  file_generator.GenerateSiblings(package_dir, output_directory, &all_files);
+  file_generator.GenerateSiblings(package_dir, context, &all_files);
 
   // Generate output list if requested.
   if (!output_list_file.empty()) {
     // Generate output list.  This is just a simple text file placed in a
     // deterministic location which lists the .java files being generated.
     scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
-      output_directory->Open(output_list_file));
+      context->Open(output_list_file));
     io::Printer srclist_printer(srclist_raw_output.get(), '$');
     for (int i = 0; i < all_files.size(); i++) {
       srclist_printer.Print("$filename$\n", "filename", all_files[i]);
diff --git a/src/google/protobuf/compiler/java/java_generator.h b/src/google/protobuf/compiler/java/java_generator.h
index c91c905..888b8d8 100644
--- a/src/google/protobuf/compiler/java/java_generator.h
+++ b/src/google/protobuf/compiler/java/java_generator.h
@@ -57,7 +57,7 @@
   // implements CodeGenerator ----------------------------------------
   bool Generate(const FileDescriptor* file,
                 const string& parameter,
-                OutputDirectory* output_directory,
+                GeneratorContext* context,
                 string* error) const;
 
  private:
diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc
index 7ed0c3c..1b6f165 100644
--- a/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/src/google/protobuf/compiler/java/java_helpers.cc
@@ -134,16 +134,27 @@
 }
 
 string FileJavaPackage(const FileDescriptor* file) {
+  string result;
+
   if (file->options().has_java_package()) {
-    return file->options().java_package();
+    result = file->options().java_package();
   } else {
-    string result = kDefaultPackage;
+    result = kDefaultPackage;
     if (!file->package().empty()) {
       if (!result.empty()) result += '.';
       result += file->package();
     }
-    return result;
   }
+
+
+  return result;
+}
+
+string JavaPackageToDir(string package_name) {
+  string package_dir =
+    StringReplace(package_name, ".", "/", true);
+  if (!package_dir.empty()) package_dir += "/";
+  return package_dir;
 }
 
 string ToJavaName(const string& full_name, const FileDescriptor* file) {
@@ -335,6 +346,132 @@
   return "";
 }
 
+bool IsDefaultValueJavaDefault(const FieldDescriptor* field) {
+  // Switch on CppType since we need to know which default_value_* method
+  // of FieldDescriptor to call.
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+      return field->default_value_int32() == 0;
+    case FieldDescriptor::CPPTYPE_UINT32:
+      return field->default_value_uint32() == 0;
+    case FieldDescriptor::CPPTYPE_INT64:
+      return field->default_value_int64() == 0L;
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return field->default_value_uint64() == 0L;
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return field->default_value_double() == 0.0;
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return field->default_value_float() == 0.0;
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return field->default_value_bool() == false;
+
+    case FieldDescriptor::CPPTYPE_STRING:
+    case FieldDescriptor::CPPTYPE_ENUM:
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return false;
+
+    // No default because we want the compiler to complain if any new
+    // types are added.
+  }
+
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return false;
+}
+
+const char* bit_masks[] = {
+  "0x00000001",
+  "0x00000002",
+  "0x00000004",
+  "0x00000008",
+  "0x00000010",
+  "0x00000020",
+  "0x00000040",
+  "0x00000080",
+
+  "0x00000100",
+  "0x00000200",
+  "0x00000400",
+  "0x00000800",
+  "0x00001000",
+  "0x00002000",
+  "0x00004000",
+  "0x00008000",
+
+  "0x00010000",
+  "0x00020000",
+  "0x00040000",
+  "0x00080000",
+  "0x00100000",
+  "0x00200000",
+  "0x00400000",
+  "0x00800000",
+
+  "0x01000000",
+  "0x02000000",
+  "0x04000000",
+  "0x08000000",
+  "0x10000000",
+  "0x20000000",
+  "0x40000000",
+  "0x80000000",
+};
+
+string GetBitFieldName(int index) {
+  string varName = "bitField";
+  varName += SimpleItoa(index);
+  varName += "_";
+  return varName;
+}
+
+string GetBitFieldNameForBit(int bitIndex) {
+  return GetBitFieldName(bitIndex / 32);
+}
+
+string GenerateGetBit(int bitIndex) {
+  string varName = GetBitFieldNameForBit(bitIndex);
+  int bitInVarIndex = bitIndex % 32;
+
+  string mask = bit_masks[bitInVarIndex];
+  string result = "((" + varName + " & " + mask + ") == " + mask + ")";
+  return result;
+}
+
+string GenerateSetBit(int bitIndex) {
+  string varName = GetBitFieldNameForBit(bitIndex);
+  int bitInVarIndex = bitIndex % 32;
+
+  string mask = bit_masks[bitInVarIndex];
+  string result = varName + " |= " + mask;
+  return result;
+}
+
+string GenerateClearBit(int bitIndex) {
+  string varName = GetBitFieldNameForBit(bitIndex);
+  int bitInVarIndex = bitIndex % 32;
+
+  string mask = bit_masks[bitInVarIndex];
+  string result = varName + " = (" + varName + " & ~" + mask + ")";
+  return result;
+}
+
+string GenerateGetBitFromLocal(int bitIndex) {
+  string varName = "from_" + GetBitFieldNameForBit(bitIndex);
+  int bitInVarIndex = bitIndex % 32;
+
+  string mask = bit_masks[bitInVarIndex];
+  string result = "((" + varName + " & " + mask + ") == " + mask + ")";
+  return result;
+}
+
+string GenerateSetBitToLocal(int bitIndex) {
+  string varName = "to_" + GetBitFieldNameForBit(bitIndex);
+  int bitInVarIndex = bitIndex % 32;
+
+  string mask = bit_masks[bitInVarIndex];
+  string result = varName + " |= " + mask;
+  return result;
+}
+
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index 3c8974c..4ae07f1 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -68,6 +68,9 @@
 // Returns the file's Java package name.
 string FileJavaPackage(const FileDescriptor* file);
 
+// Returns output directory for the given package name.
+string JavaPackageToDir(string package_name);
+
 // Converts the given fully-qualified name in the proto namespace to its
 // fully-qualified name in the Java namespace, given that it is in the given
 // file.
@@ -118,6 +121,7 @@
 const char* BoxedPrimitiveTypeName(JavaType type);
 
 string DefaultValue(const FieldDescriptor* field);
+bool IsDefaultValueJavaDefault(const FieldDescriptor* field);
 
 // Does this message class keep track of unknown fields?
 inline bool HasUnknownFields(const Descriptor* descriptor) {
@@ -132,6 +136,11 @@
            FileOptions::CODE_SIZE;
 }
 
+// Does this message have specialized equals() and hashCode() methods?
+inline bool HasEqualsAndHashCode(const Descriptor* descriptor) {
+  return descriptor->file()->options().java_generate_equals_and_hash();
+}
+
 // Does this message class have descriptor and reflection methods?
 inline bool HasDescriptorMethods(const Descriptor* descriptor) {
   return descriptor->file()->options().optimize_for() !=
@@ -146,6 +155,12 @@
            FileOptions::LITE_RUNTIME;
 }
 
+inline bool HasNestedBuilders(const Descriptor* descriptor) {
+  // The proto-lite version doesn't support nested builders.
+  return descriptor->file()->options().optimize_for() !=
+           FileOptions::LITE_RUNTIME;
+}
+
 // Should we generate generic services for this file?
 inline bool HasGenericServices(const FileDescriptor *file) {
   return file->service_count() > 0 &&
@@ -153,6 +168,43 @@
          file->options().java_generic_services();
 }
 
+
+// Methods for shared bitfields.
+
+// Gets the name of the shared bitfield for the given index.
+string GetBitFieldName(int index);
+
+// Gets the name of the shared bitfield for the given bit index.
+// Effectively, GetBitFieldName(bitIndex / 32)
+string GetBitFieldNameForBit(int bitIndex);
+
+// Generates the java code for the expression that returns the boolean value
+// of the bit of the shared bitfields for the given bit index.
+// Example: "((bitField1_ & 0x04) == 0x04)"
+string GenerateGetBit(int bitIndex);
+
+// Generates the java code for the expression that sets the bit of the shared
+// bitfields for the given bit index.
+// Example: "bitField1_ = (bitField1_ | 0x04)"
+string GenerateSetBit(int bitIndex);
+
+// Generates the java code for the expression that clears the bit of the shared
+// bitfields for the given bit index.
+// Example: "bitField1_ = (bitField1_ & ~0x04)"
+string GenerateClearBit(int bitIndex);
+
+// Does the same as GenerateGetBit but operates on the bit field on a local
+// variable. This is used by the builder to copy the value in the builder to
+// the message.
+// Example: "((from_bitField1_ & 0x04) == 0x04)"
+string GenerateGetBitFromLocal(int bitIndex);
+
+// Does the same as GenerateSetBit but operates on the bit field on a local
+// variable. This is used by the builder to copy the value in the builder to
+// the message.
+// Example: "to_bitField1_ = (to_bitField1_ | 0x04)"
+string GenerateSetBitToLocal(int bitIndex);
+
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 8b91193..47ee84c 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -245,14 +245,54 @@
     MessageGenerator(descriptor_->nested_type(i))
       .GenerateStaticVariableInitializers(printer);
   }
-
-  for (int i = 0; i < descriptor_->extension_count(); i++) {
-    // TODO(kenton):  Reuse ExtensionGenerator objects?
-    ExtensionGenerator(descriptor_->extension(i))
-      .GenerateInitializationCode(printer);
-  }
 }
 
+// ===================================================================
+
+void MessageGenerator::GenerateInterface(io::Printer* printer) {
+
+  if (descriptor_->extension_range_count() > 0) {
+    if (HasDescriptorMethods(descriptor_)) {
+      printer->Print(
+        "public interface $classname$OrBuilder extends\n"
+        "    com.google.protobuf.GeneratedMessage.\n"
+        "        ExtendableMessageOrBuilder<$classname$> {\n",
+        "classname", descriptor_->name());
+    } else {
+      printer->Print(
+        "public interface $classname$OrBuilder extends \n"
+        "     com.google.protobuf.GeneratedMessageLite.\n"
+        "          ExtendableMessageOrBuilder<$classname$> {\n",
+        "classname", descriptor_->name());
+    }
+  } else {
+    if (HasDescriptorMethods(descriptor_)) {
+      printer->Print(
+        "public interface $classname$OrBuilder\n"
+        "    extends com.google.protobuf.MessageOrBuilder {\n",
+        "classname", descriptor_->name());
+    } else {
+      printer->Print(
+        "public interface $classname$OrBuilder\n"
+        "    extends com.google.protobuf.MessageLiteOrBuilder {\n",
+        "classname", descriptor_->name());
+    }
+  }
+
+  printer->Indent();
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      printer->Print("\n");
+      PrintFieldComment(printer, descriptor_->field(i));
+      field_generators_.get(descriptor_->field(i))
+                       .GenerateInterfaceMembers(printer);
+    }
+  printer->Outdent();
+
+  printer->Print("}\n");
+}
+
+// ===================================================================
+
 void MessageGenerator::Generate(io::Printer* printer) {
   bool is_own_file =
     descriptor_->containing_type() == NULL &&
@@ -263,14 +303,14 @@
       printer->Print(
         "public $static$ final class $classname$ extends\n"
         "    com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
-        "      $classname$> {\n",
+        "      $classname$> implements $classname$OrBuilder {\n",
         "static", is_own_file ? "" : "static",
         "classname", descriptor_->name());
     } else {
       printer->Print(
         "public $static$ final class $classname$ extends\n"
         "    com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n"
-        "      $classname$> {\n",
+        "      $classname$> implements $classname$OrBuilder {\n",
         "static", is_own_file ? "" : "static",
         "classname", descriptor_->name());
     }
@@ -278,13 +318,15 @@
     if (HasDescriptorMethods(descriptor_)) {
       printer->Print(
         "public $static$ final class $classname$ extends\n"
-        "    com.google.protobuf.GeneratedMessage {\n",
+        "    com.google.protobuf.GeneratedMessage\n"
+        "    implements $classname$OrBuilder {\n",
         "static", is_own_file ? "" : "static",
         "classname", descriptor_->name());
     } else {
       printer->Print(
         "public $static$ final class $classname$ extends\n"
-        "    com.google.protobuf.GeneratedMessageLite {\n",
+        "    com.google.protobuf.GeneratedMessageLite\n"
+        "    implements $classname$OrBuilder {\n",
         "static", is_own_file ? "" : "static",
         "classname", descriptor_->name());
     }
@@ -292,8 +334,8 @@
   printer->Indent();
   printer->Print(
     "// Use $classname$.newBuilder() to construct.\n"
-    "private $classname$() {\n"
-    "  initFields();\n"
+    "private $classname$(Builder builder) {\n"
+    "  super(builder);\n"
     "}\n"
     // Used when constructing the default instance, which cannot be initialized
     // immediately because it may cyclically refer to other default instances.
@@ -310,33 +352,29 @@
     "\n",
     "classname", descriptor_->name());
 
-  if (HasDescriptorMethods(descriptor_)) {
-    printer->Print(
-      "public static final com.google.protobuf.Descriptors.Descriptor\n"
-      "    getDescriptor() {\n"
-      "  return $fileclass$.internal_$identifier$_descriptor;\n"
-      "}\n"
-      "\n"
-      "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
-      "    internalGetFieldAccessorTable() {\n"
-      "  return $fileclass$.internal_$identifier$_fieldAccessorTable;\n"
-      "}\n"
-      "\n",
-      "fileclass", ClassName(descriptor_->file()),
-      "identifier", UniqueFileScopeIdentifier(descriptor_));
-  }
+  GenerateDescriptorMethods(printer);
 
-  // Nested types and extensions
+  // Nested types
   for (int i = 0; i < descriptor_->enum_type_count(); i++) {
     EnumGenerator(descriptor_->enum_type(i)).Generate(printer);
   }
 
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    MessageGenerator(descriptor_->nested_type(i)).Generate(printer);
+    MessageGenerator messageGenerator(descriptor_->nested_type(i));
+    messageGenerator.GenerateInterface(printer);
+    messageGenerator.Generate(printer);
   }
 
-  for (int i = 0; i < descriptor_->extension_count(); i++) {
-    ExtensionGenerator(descriptor_->extension(i)).Generate(printer);
+  // Integers for bit fields.
+  int totalBits = 0;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    totalBits += field_generators_.get(descriptor_->field(i))
+        .GetNumBitsForMessage();
+  }
+  int totalInts = (totalBits + 31) / 32;
+  for (int i = 0; i < totalInts; i++) {
+    printer->Print("private int $bit_field_name$;\n",
+      "bit_field_name", GetBitFieldName(i));
   }
 
   // Fields
@@ -361,35 +399,42 @@
   printer->Print("}\n");
 
   if (HasGeneratedMethods(descriptor_)) {
-    GenerateIsInitialized(printer);
+    GenerateIsInitialized(printer, MEMOIZE);
     GenerateMessageSerializationMethods(printer);
   }
 
+  if (HasEqualsAndHashCode(descriptor_)) {
+    GenerateEqualsAndHashCode(printer);
+  }
+
   GenerateParseFromMethods(printer);
   GenerateBuilder(printer);
 
-  // Force initialization of outer class.  Otherwise, nested extensions may
-  // not be initialized.  Also carefully initialize the default instance in
-  // such a way that it doesn't conflict with other initialization.
+  // Carefully initialize the default instance in such a way that it doesn't
+  // conflict with other initialization.
   printer->Print(
     "\n"
     "static {\n"
     "  defaultInstance = new $classname$(true);\n"
-    "  $file$.internalForceInit();\n"
     "  defaultInstance.initFields();\n"
-    "}\n",
-    "file", ClassName(descriptor_->file()),
-    "classname", descriptor_->name());
-
-  printer->Print(
+    "}\n"
     "\n"
     "// @@protoc_insertion_point(class_scope:$full_name$)\n",
+    "classname", descriptor_->name(),
     "full_name", descriptor_->full_name());
 
+  // Extensions must be declared after the defaultInstance is initialized
+  // because the defaultInstance is used by the extension to lazily retrieve
+  // the outer class's FileDescriptor.
+  for (int i = 0; i < descriptor_->extension_count(); i++) {
+    ExtensionGenerator(descriptor_->extension(i)).Generate(printer);
+  }
+
   printer->Outdent();
   printer->Print("}\n\n");
 }
 
+
 // ===================================================================
 
 void MessageGenerator::
@@ -502,6 +547,13 @@
     "  return size;\n"
     "}\n"
     "\n");
+
+  printer->Print(
+    "@java.lang.Override\n"
+    "protected Object writeReplace() throws java.io.ObjectStreamException {\n"
+    "  return super.writeReplace();\n"
+    "}\n"
+    "\n");
 }
 
 void MessageGenerator::
@@ -605,42 +657,68 @@
     "\n",
     "classname", ClassName(descriptor_));
 
+  if (HasNestedBuilders(descriptor_)) {
+     printer->Print(
+      "@java.lang.Override\n"
+      "protected Builder newBuilderForType(\n"
+      "    com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
+      "  Builder builder = new Builder(parent);\n"
+      "  return builder;\n"
+      "}\n");
+  }
+
   if (descriptor_->extension_range_count() > 0) {
     if (HasDescriptorMethods(descriptor_)) {
       printer->Print(
         "public static final class Builder extends\n"
         "    com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
-        "      $classname$, Builder> {\n",
+        "      $classname$, Builder> implements $classname$OrBuilder {\n",
         "classname", ClassName(descriptor_));
     } else {
       printer->Print(
         "public static final class Builder extends\n"
         "    com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n"
-        "      $classname$, Builder> {\n",
+        "      $classname$, Builder> implements $classname$OrBuilder {\n",
         "classname", ClassName(descriptor_));
     }
   } else {
     if (HasDescriptorMethods(descriptor_)) {
       printer->Print(
         "public static final class Builder extends\n"
-        "    com.google.protobuf.GeneratedMessage.Builder<Builder> {\n",
+        "    com.google.protobuf.GeneratedMessage.Builder<Builder>\n"
+         "   implements $classname$OrBuilder {\n",
         "classname", ClassName(descriptor_));
     } else {
       printer->Print(
         "public static final class Builder extends\n"
         "    com.google.protobuf.GeneratedMessageLite.Builder<\n"
-        "      $classname$, Builder> {\n",
+        "      $classname$, Builder>\n"
+        "    implements $classname$OrBuilder {\n",
         "classname", ClassName(descriptor_));
     }
   }
   printer->Indent();
 
+  GenerateDescriptorMethods(printer);
   GenerateCommonBuilderMethods(printer);
 
   if (HasGeneratedMethods(descriptor_)) {
+    GenerateIsInitialized(printer, DONT_MEMOIZE);
     GenerateBuilderParsingMethods(printer);
   }
 
+  // Integers for bit fields.
+  int totalBits = 0;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    totalBits += field_generators_.get(descriptor_->field(i))
+        .GetNumBitsForBuilder();
+  }
+  int totalInts = (totalBits + 31) / 32;
+  for (int i = 0; i < totalInts; i++) {
+    printer->Print("private int $bit_field_name$;\n",
+      "bit_field_name", GetBitFieldName(i));
+  }
+
   for (int i = 0; i < descriptor_->field_count(); i++) {
     printer->Print("\n");
     PrintFieldComment(printer, descriptor_->field(i));
@@ -657,36 +735,92 @@
   printer->Print("}\n");
 }
 
+void MessageGenerator::GenerateDescriptorMethods(io::Printer* printer) {
+  if (HasDescriptorMethods(descriptor_)) {
+    printer->Print(
+      "public static final com.google.protobuf.Descriptors.Descriptor\n"
+      "    getDescriptor() {\n"
+      "  return $fileclass$.internal_$identifier$_descriptor;\n"
+      "}\n"
+      "\n"
+      "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+      "    internalGetFieldAccessorTable() {\n"
+      "  return $fileclass$.internal_$identifier$_fieldAccessorTable;\n"
+      "}\n"
+      "\n",
+      "fileclass", ClassName(descriptor_->file()),
+      "identifier", UniqueFileScopeIdentifier(descriptor_));
+  }
+}
+
 // ===================================================================
 
 void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
   printer->Print(
-    "private $classname$ result;\n"
-    "\n"
     "// Construct using $classname$.newBuilder()\n"
-    "private Builder() {}\n"
-    "\n"
-    "private static Builder create() {\n"
-    "  Builder builder = new Builder();\n"
-    "  builder.result = new $classname$();\n"
-    "  return builder;\n"
+    "private Builder() {\n"
+    "  maybeForceBuilderInitialization();\n"
     "}\n"
-    "\n"
-    "protected $classname$ internalGetResult() {\n"
-    "  return result;\n"
+    "\n",
+    "classname", ClassName(descriptor_));
+
+  if (HasDescriptorMethods(descriptor_)) {
+    printer->Print(
+      "private Builder(BuilderParent parent) {\n"
+      "  super(parent);\n"
+      "  maybeForceBuilderInitialization();\n"
+      "}\n",
+      "classname", ClassName(descriptor_));
+  }
+
+
+  if (HasNestedBuilders(descriptor_)) {
+    printer->Print(
+      "private void maybeForceBuilderInitialization() {\n"
+      "  if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n");
+
+    printer->Indent();
+    printer->Indent();
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      field_generators_.get(descriptor_->field(i))
+          .GenerateFieldBuilderInitializationCode(printer);
+    }
+    printer->Outdent();
+    printer->Outdent();
+
+    printer->Print(
+      "  }\n"
+      "}\n");
+  } else {
+    printer->Print(
+      "private void maybeForceBuilderInitialization() {\n"
+      "}\n");
+  }
+
+  printer->Print(
+    "private static Builder create() {\n"
+    "  return new Builder();\n"
     "}\n"
     "\n"
     "public Builder clear() {\n"
-    "  if (result == null) {\n"
-    "    throw new IllegalStateException(\n"
-    "      \"Cannot call clear() after build().\");\n"
-    "  }\n"
-    "  result = new $classname$();\n"
+    "  super.clear();\n",
+    "classname", ClassName(descriptor_));
+
+  printer->Indent();
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(descriptor_->field(i))
+        .GenerateBuilderClearCode(printer);
+  }
+
+  printer->Outdent();
+
+  printer->Print(
     "  return this;\n"
     "}\n"
     "\n"
     "public Builder clone() {\n"
-    "  return create().mergeFrom(result);\n"
+    "  return create().mergeFrom(buildPartial());\n"
     "}\n"
     "\n",
     "classname", ClassName(descriptor_));
@@ -703,49 +837,78 @@
     "public $classname$ getDefaultInstanceForType() {\n"
     "  return $classname$.getDefaultInstance();\n"
     "}\n"
-    "\n"
-    "public boolean isInitialized() {\n"
-    "  return result.isInitialized();\n"
-    "}\n",
+    "\n",
     "classname", ClassName(descriptor_));
 
   // -----------------------------------------------------------------
 
   printer->Print(
     "public $classname$ build() {\n"
-    // If result == null, we'll throw an appropriate exception later.
-    "  if (result != null && !isInitialized()) {\n"
+    "  $classname$ result = buildPartial();\n"
+    "  if (!result.isInitialized()) {\n"
     "    throw newUninitializedMessageException(result);\n"
     "  }\n"
-    "  return buildPartial();\n"
+    "  return result;\n"
     "}\n"
     "\n"
     "private $classname$ buildParsed()\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
-    "  if (!isInitialized()) {\n"
+    "  $classname$ result = buildPartial();\n"
+    "  if (!result.isInitialized()) {\n"
     "    throw newUninitializedMessageException(\n"
     "      result).asInvalidProtocolBufferException();\n"
     "  }\n"
-    "  return buildPartial();\n"
+    "  return result;\n"
     "}\n"
     "\n"
     "public $classname$ buildPartial() {\n"
-    "  if (result == null) {\n"
-    "    throw new IllegalStateException(\n"
-    "      \"build() has already been called on this Builder.\");\n"
-    "  }\n",
+    "  $classname$ result = new $classname$(this);\n",
     "classname", ClassName(descriptor_));
+
   printer->Indent();
 
+  // Local vars for from and to bit fields to avoid accessing the builder and
+  // message over and over for these fields. Seems to provide a slight
+  // perforamance improvement in micro benchmark and this is also what proto1
+  // code does.
+  int totalBuilderBits = 0;
+  int totalMessageBits = 0;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldGenerator& field = field_generators_.get(descriptor_->field(i));
+    totalBuilderBits += field.GetNumBitsForBuilder();
+    totalMessageBits += field.GetNumBitsForMessage();
+  }
+  int totalBuilderInts = (totalBuilderBits + 31) / 32;
+  int totalMessageInts = (totalMessageBits + 31) / 32;
+  for (int i = 0; i < totalBuilderInts; i++) {
+    printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n",
+      "bit_field_name", GetBitFieldName(i));
+  }
+  for (int i = 0; i < totalMessageInts; i++) {
+    printer->Print("int to_$bit_field_name$ = 0;\n",
+      "bit_field_name", GetBitFieldName(i));
+  }
+
+  // Output generation code for each field.
   for (int i = 0; i < descriptor_->field_count(); i++) {
     field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer);
   }
 
+  // Copy the bit field results to the generated message
+  for (int i = 0; i < totalMessageInts; i++) {
+    printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n",
+      "bit_field_name", GetBitFieldName(i));
+  }
+
   printer->Outdent();
+
+  if (HasDescriptorMethods(descriptor_)) {
+    printer->Print(
+    "  onBuilt();\n");
+  }
+
   printer->Print(
-    "  $classname$ returnMe = result;\n"
-    "  result = null;\n"
-    "  return returnMe;\n"
+    "  return result;\n"
     "}\n"
     "\n",
     "classname", ClassName(descriptor_));
@@ -834,25 +997,31 @@
     printer->Print(
       "case 0:\n"          // zero signals EOF / limit reached
       "  this.setUnknownFields(unknownFields.build());\n"
+      "  $on_changed$\n"
       "  return this;\n"
       "default: {\n"
       "  if (!parseUnknownField(input, unknownFields,\n"
       "                         extensionRegistry, tag)) {\n"
       "    this.setUnknownFields(unknownFields.build());\n"
+      "    $on_changed$\n"
       "    return this;\n"   // it's an endgroup tag
       "  }\n"
       "  break;\n"
-      "}\n");
+      "}\n",
+      "on_changed", HasDescriptorMethods(descriptor_) ? "onChanged();" : "");
   } else {
     printer->Print(
       "case 0:\n"          // zero signals EOF / limit reached
+      "  $on_changed$\n"
       "  return this;\n"
       "default: {\n"
       "  if (!parseUnknownField(input, extensionRegistry, tag)) {\n"
+      "    $on_changed$\n"
       "    return this;\n"   // it's an endgroup tag
       "  }\n"
       "  break;\n"
-      "}\n");
+      "}\n",
+      "on_changed", HasDescriptorMethods(descriptor_) ? "onChanged();" : "");
   }
 
   for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -898,16 +1067,33 @@
     "    }\n"     // switch (tag)
     "  }\n"       // while (true)
     "}\n"
+
     "\n");
 }
 
 // ===================================================================
 
-void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
+void MessageGenerator::GenerateIsInitialized(
+    io::Printer* printer, UseMemoization useMemoization) {
+  bool memoization = useMemoization == MEMOIZE;
+  if (memoization) {
+    // Memoizes whether the protocol buffer is fully initialized (has all
+    // required fields). -1 means not yet computed. 0 means false and 1 means
+    // true.
+    printer->Print(
+      "private byte memoizedIsInitialized = -1;\n");
+  }
   printer->Print(
     "public final boolean isInitialized() {\n");
   printer->Indent();
 
+  if (memoization) {
+    printer->Print(
+      "byte isInitialized = memoizedIsInitialized;\n"
+      "if (isInitialized != -1) return isInitialized == 1;\n"
+      "\n");
+  }
+
   // Check that all required fields in this message are set.
   // TODO(kenton):  We can optimize this when we switch to putting all the
   //   "has" fields into a single bitfield.
@@ -916,8 +1102,12 @@
 
     if (field->is_required()) {
       printer->Print(
-        "if (!has$name$) return false;\n",
-        "name", UnderscoresToCapitalizedCamelCase(field));
+        "if (!has$name$()) {\n"
+        "  $memoize$\n"
+        "  return false;\n"
+        "}\n",
+        "name", UnderscoresToCapitalizedCamelCase(field),
+        "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
     }
   }
 
@@ -929,25 +1119,37 @@
       switch (field->label()) {
         case FieldDescriptor::LABEL_REQUIRED:
           printer->Print(
-            "if (!get$name$().isInitialized()) return false;\n",
+            "if (!get$name$().isInitialized()) {\n"
+             "  $memoize$\n"
+             "  return false;\n"
+             "}\n",
             "type", ClassName(field->message_type()),
-            "name", UnderscoresToCapitalizedCamelCase(field));
+            "name", UnderscoresToCapitalizedCamelCase(field),
+            "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
           break;
         case FieldDescriptor::LABEL_OPTIONAL:
           printer->Print(
             "if (has$name$()) {\n"
-            "  if (!get$name$().isInitialized()) return false;\n"
+            "  if (!get$name$().isInitialized()) {\n"
+            "    $memoize$\n"
+            "    return false;\n"
+            "  }\n"
             "}\n",
             "type", ClassName(field->message_type()),
-            "name", UnderscoresToCapitalizedCamelCase(field));
+            "name", UnderscoresToCapitalizedCamelCase(field),
+            "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
           break;
         case FieldDescriptor::LABEL_REPEATED:
           printer->Print(
-            "for ($type$ element : get$name$List()) {\n"
-            "  if (!element.isInitialized()) return false;\n"
+            "for (int i = 0; i < get$name$Count(); i++) {\n"
+            "  if (!get$name$(i).isInitialized()) {\n"
+            "    $memoize$\n"
+            "    return false;\n"
+            "  }\n"
             "}\n",
             "type", ClassName(field->message_type()),
-            "name", UnderscoresToCapitalizedCamelCase(field));
+            "name", UnderscoresToCapitalizedCamelCase(field),
+            "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
           break;
       }
     }
@@ -955,10 +1157,20 @@
 
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(
-      "if (!extensionsAreInitialized()) return false;\n");
+      "if (!extensionsAreInitialized()) {\n"
+      "  $memoize$\n"
+      "  return false;\n"
+      "}\n",
+      "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
   }
 
   printer->Outdent();
+
+  if (memoization) {
+    printer->Print(
+      "  memoizedIsInitialized = 1;\n");
+  }
+
   printer->Print(
     "  return true;\n"
     "}\n"
@@ -967,6 +1179,94 @@
 
 // ===================================================================
 
+void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) {
+  printer->Print(
+    "@java.lang.Override\n"
+    "public boolean equals(final Object obj) {\n");
+  printer->Indent();
+  printer->Print(
+    "if (obj == this) {\n"
+    " return true;\n"
+    "}\n"
+    "if (!(obj instanceof $classname$)) {\n"
+    "  return super.equals(obj);\n"
+    "}\n"
+    "$classname$ other = ($classname$) obj;\n"
+    "\n",
+    "classname", ClassName(descriptor_));
+
+  printer->Print("boolean result = true;\n");
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (!field->is_repeated()) {
+      printer->Print(
+        "result = result && (has$name$() == other.has$name$());\n"
+        "if (has$name$()) {\n",
+        "name", UnderscoresToCapitalizedCamelCase(field));
+      printer->Indent();
+    }
+    field_generators_.get(field).GenerateEqualsCode(printer);
+    if (!field->is_repeated()) {
+      printer->Outdent();
+      printer->Print(
+        "}\n");
+    }
+  }
+  if (HasDescriptorMethods(descriptor_)) {
+    printer->Print(
+      "result = result &&\n"
+      "    getUnknownFields().equals(other.getUnknownFields());\n");
+    if (descriptor_->extension_range_count() > 0) {
+      printer->Print(
+        "result = result &&\n"
+        "    getExtensionFields().equals(other.getExtensionFields());\n");
+    }
+  }
+  printer->Print(
+    "return result;\n");
+  printer->Outdent();
+  printer->Print(
+    "}\n"
+    "\n");
+
+  printer->Print(
+    "@java.lang.Override\n"
+    "public int hashCode() {\n");
+  printer->Indent();
+  printer->Print(
+    "int hash = 41;\n"
+    "hash = (19 * hash) + getDescriptorForType().hashCode();\n");
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (!field->is_repeated()) {
+      printer->Print(
+        "if (has$name$()) {\n",
+        "name", UnderscoresToCapitalizedCamelCase(field));
+      printer->Indent();
+    }
+    field_generators_.get(field).GenerateHashCode(printer);
+    if (!field->is_repeated()) {
+      printer->Outdent();
+      printer->Print("}\n");
+    }
+  }
+  if (HasDescriptorMethods(descriptor_)) {
+    if (descriptor_->extension_range_count() > 0) {
+      printer->Print(
+        "hash = hashFields(hash, getExtensionFields());\n");
+    }
+  }
+  printer->Print(
+    "hash = (29 * hash) + getUnknownFields().hashCode();\n"
+    "return hash;\n");
+  printer->Outdent();
+  printer->Print(
+    "}\n"
+    "\n");
+}
+
+// ===================================================================
+
 void MessageGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) {
   for (int i = 0; i < descriptor_->extension_count(); i++) {
     ExtensionGenerator(descriptor_->extension(i))
diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h
index 50ffae0..4c6fbbe 100644
--- a/src/google/protobuf/compiler/java/java_message.h
+++ b/src/google/protobuf/compiler/java/java_message.h
@@ -67,11 +67,19 @@
   // Generate the class itself.
   void Generate(io::Printer* printer);
 
+  // Generates the base interface that both the class and its builder implement
+  void GenerateInterface(io::Printer* printer);
+
   // Generate code to register all contained extensions with an
   // ExtensionRegistry.
   void GenerateExtensionRegistrationCode(io::Printer* printer);
 
  private:
+  enum UseMemoization {
+    MEMOIZE,
+    DONT_MEMOIZE
+  };
+
   void GenerateMessageSerializationMethods(io::Printer* printer);
   void GenerateParseFromMethods(io::Printer* printer);
   void GenerateSerializeOneField(io::Printer* printer,
@@ -81,8 +89,11 @@
 
   void GenerateBuilder(io::Printer* printer);
   void GenerateCommonBuilderMethods(io::Printer* printer);
+  void GenerateDescriptorMethods(io::Printer* printer);
   void GenerateBuilderParsingMethods(io::Printer* printer);
-  void GenerateIsInitialized(io::Printer* printer);
+  void GenerateIsInitialized(io::Printer* printer,
+      UseMemoization useMemoization);
+  void GenerateEqualsAndHashCode(io::Printer* printer);
 
   const Descriptor* descriptor_;
   FieldGeneratorMap field_generators_;
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index 71edc02..251945a 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -51,16 +51,43 @@
 // TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
 //   repeat code between this and the other field types.
 void SetMessageVariables(const FieldDescriptor* descriptor,
+                         int messageBitIndex,
+                         int builderBitIndex,
                          map<string, string>* variables) {
   (*variables)["name"] =
     UnderscoresToCamelCase(descriptor);
   (*variables)["capitalized_name"] =
     UnderscoresToCapitalizedCamelCase(descriptor);
+  (*variables)["constant_name"] = FieldConstantName(descriptor);
   (*variables)["number"] = SimpleItoa(descriptor->number());
   (*variables)["type"] = ClassName(descriptor->message_type());
   (*variables)["group_or_message"] =
     (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ?
     "Group" : "Message";
+  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+  // by the proto compiler
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
+  (*variables)["on_changed"] =
+      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+
+  // For singular messages and builders, one bit is used for the hasField bit.
+  (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+  (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_has_field_bit_builder"] =
+      GenerateClearBit(builderBitIndex);
+
+  // For repated builders, one bit is used for whether the array is immutable.
+  (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
+
+  (*variables)["get_has_field_bit_from_local"] =
+      GenerateGetBitFromLocal(builderBitIndex);
+  (*variables)["set_has_field_bit_to_local"] =
+      GenerateSetBitToLocal(messageBitIndex);
 }
 
 }  // namespace
@@ -68,68 +95,244 @@
 // ===================================================================
 
 MessageFieldGenerator::
-MessageFieldGenerator(const FieldDescriptor* descriptor)
-  : descriptor_(descriptor) {
-  SetMessageVariables(descriptor, &variables_);
+MessageFieldGenerator(const FieldDescriptor* descriptor,
+                      int messageBitIndex,
+                      int builderBitIndex)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex) {
+  SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+                      &variables_);
 }
 
 MessageFieldGenerator::~MessageFieldGenerator() {}
 
+int MessageFieldGenerator::GetNumBitsForMessage() const {
+  return 1;
+}
+
+int MessageFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void MessageFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  // TODO(jonp): In the future, consider having a method specific to the
+  // interface so that builders can choose dynamically to either return a
+  // message or a nested builder, so that asking for the interface doesn't
+  // cause a message to ever be built.
+  printer->Print(variables_,
+    "$deprecation$boolean has$capitalized_name$();\n"
+    "$deprecation$$type$ get$capitalized_name$();\n");
+
+  if (HasNestedBuilders(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n");
+  }
+}
+
 void MessageFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private boolean has$capitalized_name$;\n"
     "private $type$ $name$_;\n"
-    "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
-    "public $type$ get$capitalized_name$() { return $name$_; }\n");
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_message$;\n"
+    "}\n"
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return $name$_;\n"
+    "}\n");
+
+  if (HasNestedBuilders(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+      "  return $name$_;\n"
+      "}\n");
+  }
+}
+
+void MessageFieldGenerator::PrintNestedBuilderCondition(
+    io::Printer* printer,
+    const char* regular_case,
+    const char* nested_builder_case) const {
+  if (HasNestedBuilders(descriptor_->containing_type())) {
+     printer->Print(variables_, "if ($name$Builder_ == null) {\n");
+     printer->Indent();
+     printer->Print(variables_, regular_case);
+     printer->Outdent();
+     printer->Print("} else {\n");
+     printer->Indent();
+     printer->Print(variables_, nested_builder_case);
+     printer->Outdent();
+     printer->Print("}\n");
+   } else {
+     printer->Print(variables_, regular_case);
+   }
+}
+
+void MessageFieldGenerator::PrintNestedBuilderFunction(
+    io::Printer* printer,
+    const char* method_prototype,
+    const char* regular_case,
+    const char* nested_builder_case,
+    const char* trailing_code) const {
+  printer->Print(variables_, method_prototype);
+  printer->Print(" {\n");
+  printer->Indent();
+  PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
+  if (trailing_code != NULL) {
+    printer->Print(variables_, trailing_code);
+  }
+  printer->Outdent();
+  printer->Print("}\n");
 }
 
 void MessageFieldGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
+  // When using nested-builders, the code initially works just like the
+  // non-nested builder case. It only creates a nested builder lazily on
+  // demand and then forever delegates to it after creation.
+
   printer->Print(variables_,
-    "public boolean has$capitalized_name$() {\n"
-    "  return result.has$capitalized_name$();\n"
-    "}\n"
-    "public $type$ get$capitalized_name$() {\n"
-    "  return result.get$capitalized_name$();\n"
-    "}\n"
-    "public Builder set$capitalized_name$($type$ value) {\n"
-    "  if (value == null) {\n"
-    "    throw new NullPointerException();\n"
-    "  }\n"
-    "  result.has$capitalized_name$ = true;\n"
-    "  result.$name$_ = value;\n"
-    "  return this;\n"
-    "}\n"
-    "public Builder set$capitalized_name$($type$.Builder builderForValue) {\n"
-    "  result.has$capitalized_name$ = true;\n"
-    "  result.$name$_ = builderForValue.build();\n"
-    "  return this;\n"
-    "}\n"
-    "public Builder merge$capitalized_name$($type$ value) {\n"
-    "  if (result.has$capitalized_name$() &&\n"
-    "      result.$name$_ != $type$.getDefaultInstance()) {\n"
-    "    result.$name$_ =\n"
-    "      $type$.newBuilder(result.$name$_).mergeFrom(value).buildPartial();\n"
-    "  } else {\n"
-    "    result.$name$_ = value;\n"
-    "  }\n"
-    "  result.has$capitalized_name$ = true;\n"
-    "  return this;\n"
-    "}\n"
-    "public Builder clear$capitalized_name$() {\n"
-    "  result.has$capitalized_name$ = false;\n"
-    "  result.$name$_ = $type$.getDefaultInstance();\n"
-    "  return this;\n"
+    // Used when the builder is null.
+    "private $type$ $name$_ = $type$.getDefaultInstance();\n");
+
+  if (HasNestedBuilders(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      // If this builder is non-null, it is used and the other fields are
+      // ignored.
+      "private com.google.protobuf.SingleFieldBuilder<\n"
+      "    $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
+      "\n");
+  }
+
+  // The comments above the methods below are based on a hypothetical
+  // field of type "Field" called "Field".
+
+  // boolean hasField()
+  printer->Print(variables_,
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_builder$;\n"
     "}\n");
+
+  // Field getField()
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public $type$ get$capitalized_name$()",
+
+    "return $name$_;\n",
+
+    "return $name$Builder_.getMessage();\n",
+
+    NULL);
+
+  // Field.Builder setField(Field value)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$($type$ value)",
+
+    "if (value == null) {\n"
+    "  throw new NullPointerException();\n"
+    "}\n"
+    "$name$_ = value;\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.setMessage(value);\n",
+
+    "$set_has_field_bit_builder$;\n"
+    "return this;\n");
+
+  // Field.Builder setField(Field.Builder builderForValue)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    $type$.Builder builderForValue)",
+
+    "$name$_ = builderForValue.build();\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.setMessage(builderForValue.build());\n",
+
+    "$set_has_field_bit_builder$;\n"
+    "return this;\n");
+
+  // Field.Builder mergeField(Field value)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder merge$capitalized_name$($type$ value)",
+
+    "if ($get_has_field_bit_builder$ &&\n"
+    "    $name$_ != $type$.getDefaultInstance()) {\n"
+    "  $name$_ =\n"
+    "    $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
+    "} else {\n"
+    "  $name$_ = value;\n"
+    "}\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.mergeFrom(value);\n",
+
+    "$set_has_field_bit_builder$;\n"
+    "return this;\n");
+
+  // Field.Builder clearField()
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder clear$capitalized_name$()",
+
+    "$name$_ = $type$.getDefaultInstance();\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.clear();\n",
+
+    "$clear_has_field_bit_builder$;\n"
+    "return this;\n");
+
+  if (HasNestedBuilders(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
+      "  $set_has_field_bit_builder$;\n"
+      "  $on_changed$\n"
+      "  return get$capitalized_name$FieldBuilder().getBuilder();\n"
+      "}\n"
+      "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+      "  if ($name$Builder_ != null) {\n"
+      "    return $name$Builder_.getMessageOrBuilder();\n"
+      "  } else {\n"
+      "    return $name$_;\n"
+      "  }\n"
+      "}\n"
+      "private com.google.protobuf.SingleFieldBuilder<\n"
+      "    $type$, $type$.Builder, $type$OrBuilder> \n"
+      "    get$capitalized_name$FieldBuilder() {\n"
+      "  if ($name$Builder_ == null) {\n"
+      "    $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
+      "        $type$, $type$.Builder, $type$OrBuilder>(\n"
+      "            $name$_,\n"
+      "            getParentForChildren(),\n"
+      "            isClean());\n"
+      "    $name$_ = null;\n"
+      "  }\n"
+      "  return $name$Builder_;\n"
+      "}\n");
+  }
 }
 
 void MessageFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  printer->Print(variables_,
+    "get$capitalized_name$FieldBuilder();\n");
+}
+
+
+void MessageFieldGenerator::
 GenerateInitializationCode(io::Printer* printer) const {
   printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n");
 }
 
 void MessageFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  PrintNestedBuilderCondition(printer,
+    "$name$_ = $type$.getDefaultInstance();\n",
+
+    "$name$Builder_.clear();\n");
+  printer->Print(variables_, "$clear_has_field_bit_builder$;\n");
+}
+
+void MessageFieldGenerator::
 GenerateMergingCode(io::Printer* printer) const {
   printer->Print(variables_,
     "if (other.has$capitalized_name$()) {\n"
@@ -139,7 +342,16 @@
 
 void MessageFieldGenerator::
 GenerateBuildingCode(io::Printer* printer) const {
-  // Nothing to do for singular fields.
+
+  printer->Print(variables_,
+      "if ($get_has_field_bit_from_local$) {\n"
+      "  $set_has_field_bit_to_local$;\n"
+      "}\n");
+
+  PrintNestedBuilderCondition(printer,
+    "result.$name$_ = $name$_;\n",
+
+    "result.$name$_ = $name$Builder_.build();\n");
 }
 
 void MessageFieldGenerator::
@@ -165,20 +377,34 @@
 void MessageFieldGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (has$capitalized_name$()) {\n"
-    "  output.write$group_or_message$($number$, get$capitalized_name$());\n"
+    "if ($get_has_field_bit_message$) {\n"
+    "  output.write$group_or_message$($number$, $name$_);\n"
     "}\n");
 }
 
 void MessageFieldGenerator::
 GenerateSerializedSizeCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (has$capitalized_name$()) {\n"
+    "if ($get_has_field_bit_message$) {\n"
     "  size += com.google.protobuf.CodedOutputStream\n"
-    "    .compute$group_or_message$Size($number$, get$capitalized_name$());\n"
+    "    .compute$group_or_message$Size($number$, $name$_);\n"
     "}\n");
 }
 
+void MessageFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$()\n"
+    "    .equals(other.get$capitalized_name$());\n");
+}
+
+void MessageFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "hash = (37 * hash) + $constant_name$;\n"
+    "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+}
+
 string MessageFieldGenerator::GetBoxedType() const {
   return ClassName(descriptor_->message_type());
 }
@@ -186,109 +412,416 @@
 // ===================================================================
 
 RepeatedMessageFieldGenerator::
-RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor)
-  : descriptor_(descriptor) {
-  SetMessageVariables(descriptor, &variables_);
+RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+                              int messageBitIndex,
+                              int builderBitIndex)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex) {
+  SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+                      &variables_);
 }
 
 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
 
+int RepeatedMessageFieldGenerator::GetNumBitsForMessage() const {
+  return 0;
+}
+
+int RepeatedMessageFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  // TODO(jonp): In the future, consider having methods specific to the
+  // interface so that builders can choose dynamically to either return a
+  // message or a nested builder, so that asking for the interface doesn't
+  // cause a message to ever be built.
+  printer->Print(variables_,
+    "$deprecation$java.util.List<$type$> \n"
+    "    get$capitalized_name$List();\n"
+    "$deprecation$$type$ get$capitalized_name$(int index);\n"
+    "$deprecation$int get$capitalized_name$Count();\n");
+  if (HasNestedBuilders(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      "$deprecation$java.util.List<? extends $type$OrBuilder> \n"
+      "    get$capitalized_name$OrBuilderList();\n"
+      "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n"
+      "    int index);\n");
+  }
+}
+
 void RepeatedMessageFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private java.util.List<$type$> $name$_ =\n"
-    "  java.util.Collections.emptyList();\n"
-    "public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "private java.util.List<$type$> $name$_;\n"
+    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
     "}\n"
-    "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
-    "public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
+    "    get$capitalized_name$OrBuilderList() {\n"
+    "  return $name$_;\n"
+    "}\n"
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n"
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return $name$_.get(index);\n"
+    "}\n"
+    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+    "    int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+
+}
+
+void RepeatedMessageFieldGenerator::PrintNestedBuilderCondition(
+    io::Printer* printer,
+    const char* regular_case,
+    const char* nested_builder_case) const {
+  if (HasNestedBuilders(descriptor_->containing_type())) {
+     printer->Print(variables_, "if ($name$Builder_ == null) {\n");
+     printer->Indent();
+     printer->Print(variables_, regular_case);
+     printer->Outdent();
+     printer->Print("} else {\n");
+     printer->Indent();
+     printer->Print(variables_, nested_builder_case);
+     printer->Outdent();
+     printer->Print("}\n");
+   } else {
+     printer->Print(variables_, regular_case);
+   }
+}
+
+void RepeatedMessageFieldGenerator::PrintNestedBuilderFunction(
+    io::Printer* printer,
+    const char* method_prototype,
+    const char* regular_case,
+    const char* nested_builder_case,
+    const char* trailing_code) const {
+  printer->Print(variables_, method_prototype);
+  printer->Print(" {\n");
+  printer->Indent();
+  PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
+  if (trailing_code != NULL) {
+    printer->Print(variables_, trailing_code);
+  }
+  printer->Outdent();
+  printer->Print("}\n");
 }
 
 void RepeatedMessageFieldGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
+  // When using nested-builders, the code initially works just like the
+  // non-nested builder case. It only creates a nested builder lazily on
+  // demand and then forever delegates to it after creation.
+
   printer->Print(variables_,
-    // Note:  We return an unmodifiable list because otherwise the caller
-    //   could hold on to the returned list and modify it after the message
-    //   has been built, thus mutating the message which is supposed to be
-    //   immutable.
-    "public java.util.List<$type$> get$capitalized_name$List() {\n"
-    "  return java.util.Collections.unmodifiableList(result.$name$_);\n"
+    // Used when the builder is null.
+    // One field is the list and the other field keeps track of whether the
+    // list is immutable. If it's immutable, the invariant is that it must
+    // either an instance of Collections.emptyList() or it's an ArrayList
+    // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
+    // a refererence to the underlying ArrayList. This invariant allows us to
+    // share instances of lists between protocol buffers avoiding expensive
+    // memory allocations. Note, immutable is a strong guarantee here -- not
+    // just that the list cannot be modified via the reference but that the
+    // list can never be modified.
+    "private java.util.List<$type$> $name$_ =\n"
+    "  java.util.Collections.emptyList();\n"
+
+    "private void ensure$capitalized_name$IsMutable() {\n"
+    "  if (!$get_mutable_bit_builder$) {\n"
+    "    $name$_ = new java.util.ArrayList<$type$>($name$_);\n"
+    "    $set_mutable_bit_builder$;\n"
+    "   }\n"
     "}\n"
-    "public int get$capitalized_name$Count() {\n"
-    "  return result.get$capitalized_name$Count();\n"
+    "\n");
+
+  if (HasNestedBuilders(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      // If this builder is non-null, it is used and the other fields are
+      // ignored.
+      "private com.google.protobuf.RepeatedFieldBuilder<\n"
+      "    $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
+      "\n");
+  }
+
+  // The comments above the methods below are based on a hypothetical
+  // repeated field of type "Field" called "RepeatedField".
+
+  // List<Field> getRepeatedFieldList()
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public java.util.List<$type$> get$capitalized_name$List()",
+
+    "return java.util.Collections.unmodifiableList($name$_);\n",
+    "return $name$Builder_.getMessageList();\n",
+
+    NULL);
+
+  // int getRepeatedFieldCount()
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public int get$capitalized_name$Count()",
+
+    "return $name$_.size();\n",
+    "return $name$Builder_.getCount();\n",
+
+    NULL);
+
+  // Field getRepeatedField(int index)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public $type$ get$capitalized_name$(int index)",
+
+    "return $name$_.get(index);\n",
+
+    "return $name$Builder_.getMessage(index);\n",
+
+    NULL);
+
+  // Builder setRepeatedField(int index, Field value)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$ value)",
+    "if (value == null) {\n"
+    "  throw new NullPointerException();\n"
     "}\n"
-    "public $type$ get$capitalized_name$(int index) {\n"
-    "  return result.get$capitalized_name$(index);\n"
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.set(index, value);\n"
+    "$on_changed$\n",
+    "$name$Builder_.setMessage(index, value);\n",
+    "return this;\n");
+
+  // Builder setRepeatedField(int index, Field.Builder builderForValue)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$.Builder builderForValue)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.set(index, builderForValue.build());\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.setMessage(index, builderForValue.build());\n",
+
+    "return this;\n");
+
+  // Builder addRepeatedField(Field value)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder add$capitalized_name$($type$ value)",
+
+    "if (value == null) {\n"
+    "  throw new NullPointerException();\n"
     "}\n"
-    "public Builder set$capitalized_name$(int index, $type$ value) {\n"
-    "  if (value == null) {\n"
-    "    throw new NullPointerException();\n"
-    "  }\n"
-    "  result.$name$_.set(index, value);\n"
-    "  return this;\n"
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(value);\n"
+
+    "$on_changed$\n",
+
+    "$name$Builder_.addMessage(value);\n",
+
+    "return this;\n");
+
+  // Builder addRepeatedField(int index, Field value)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    int index, $type$ value)",
+
+    "if (value == null) {\n"
+    "  throw new NullPointerException();\n"
     "}\n"
-    "public Builder set$capitalized_name$(int index, "
-      "$type$.Builder builderForValue) {\n"
-    "  result.$name$_.set(index, builderForValue.build());\n"
-    "  return this;\n"
-    "}\n"
-    "public Builder add$capitalized_name$($type$ value) {\n"
-    "  if (value == null) {\n"
-    "    throw new NullPointerException();\n"
-    "  }\n"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
-    "  }\n"
-    "  result.$name$_.add(value);\n"
-    "  return this;\n"
-    "}\n"
-    "public Builder add$capitalized_name$($type$.Builder builderForValue) {\n"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
-    "  }\n"
-    "  result.$name$_.add(builderForValue.build());\n"
-    "  return this;\n"
-    "}\n"
-    "public Builder addAll$capitalized_name$(\n"
-    "    java.lang.Iterable<? extends $type$> values) {\n"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
-    "  }\n"
-    "  super.addAll(values, result.$name$_);\n"
-    "  return this;\n"
-    "}\n"
-    "public Builder clear$capitalized_name$() {\n"
-    "  result.$name$_ = java.util.Collections.emptyList();\n"
-    "  return this;\n"
-    "}\n");
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(index, value);\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.addMessage(index, value);\n",
+
+    "return this;\n");
+
+  // Builder addRepeatedField(Field.Builder builderForValue)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    $type$.Builder builderForValue)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(builderForValue.build());\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.addMessage(builderForValue.build());\n",
+
+    "return this;\n");
+
+  // Builder addRepeatedField(int index, Field.Builder builderForValue)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder add$capitalized_name$(\n"
+    "    int index, $type$.Builder builderForValue)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(index, builderForValue.build());\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.addMessage(index, builderForValue.build());\n",
+
+    "return this;\n");
+
+  // Builder addAllRepeatedField(Iterable<Field> values)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<? extends $type$> values)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "super.addAll(values, $name$_);\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.addAllMessages(values);\n",
+
+    "return this;\n");
+
+  // Builder clearAllRepeatedField()
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder clear$capitalized_name$()",
+
+    "$name$_ = java.util.Collections.emptyList();\n"
+    "$clear_mutable_bit_builder$;\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.clear();\n",
+
+    "return this;\n");
+
+  // Builder removeRepeatedField(int index)
+  PrintNestedBuilderFunction(printer,
+    "$deprecation$public Builder remove$capitalized_name$(int index)",
+
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.remove(index);\n"
+    "$on_changed$\n",
+
+    "$name$Builder_.remove(index);\n",
+
+    "return this;\n");
+
+  if (HasNestedBuilders(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
+      "    int index) {\n"
+      "  return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
+      "}\n"
+
+      "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+      "    int index) {\n"
+      "  if ($name$Builder_ == null) {\n"
+      "    return $name$_.get(index);"
+      "  } else {\n"
+      "    return $name$Builder_.getMessageOrBuilder(index);\n"
+      "  }\n"
+      "}\n"
+
+      "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
+      "     get$capitalized_name$OrBuilderList() {\n"
+      "  if ($name$Builder_ != null) {\n"
+      "    return $name$Builder_.getMessageOrBuilderList();\n"
+      "  } else {\n"
+      "    return java.util.Collections.unmodifiableList($name$_);\n"
+      "  }\n"
+      "}\n"
+
+      "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
+      "  return get$capitalized_name$FieldBuilder().addBuilder(\n"
+      "      $type$.getDefaultInstance());\n"
+      "}\n"
+      "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
+      "    int index) {\n"
+      "  return get$capitalized_name$FieldBuilder().addBuilder(\n"
+      "      index, $type$.getDefaultInstance());\n"
+      "}\n"
+      "$deprecation$public java.util.List<$type$.Builder> \n"
+      "     get$capitalized_name$BuilderList() {\n"
+      "  return get$capitalized_name$FieldBuilder().getBuilderList();\n"
+      "}\n"
+      "private com.google.protobuf.RepeatedFieldBuilder<\n"
+      "    $type$, $type$.Builder, $type$OrBuilder> \n"
+      "    get$capitalized_name$FieldBuilder() {\n"
+      "  if ($name$Builder_ == null) {\n"
+      "    $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n"
+      "        $type$, $type$.Builder, $type$OrBuilder>(\n"
+      "            $name$_,\n"
+      "            $get_mutable_bit_builder$,\n"
+      "            getParentForChildren(),\n"
+      "            isClean());\n"
+      "    $name$_ = null;\n"
+      "  }\n"
+      "  return $name$Builder_;\n"
+      "}\n");
+  }
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  printer->Print(variables_,
+    "get$capitalized_name$FieldBuilder();\n");
 }
 
 void RepeatedMessageFieldGenerator::
 GenerateInitializationCode(io::Printer* printer) const {
-  // Initialized inline.
+  printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  PrintNestedBuilderCondition(printer,
+    "$name$_ = java.util.Collections.emptyList();\n"
+    "$clear_mutable_bit_builder$;\n",
+
+    "$name$Builder_.clear();\n");
 }
 
 void RepeatedMessageFieldGenerator::
 GenerateMergingCode(io::Printer* printer) const {
-  printer->Print(variables_,
+  // The code below does two optimizations (non-nested builder case):
+  //   1. If the other list is empty, there's nothing to do. This ensures we
+  //      don't allocate a new array if we already have an immutable one.
+  //   2. If the other list is non-empty and our current list is empty, we can
+  //      reuse the other list which is guaranteed to be immutable.
+  PrintNestedBuilderCondition(printer,
     "if (!other.$name$_.isEmpty()) {\n"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$type$>();\n"
+    "  if ($name$_.isEmpty()) {\n"
+    "    $name$_ = other.$name$_;\n"
+    "    $clear_mutable_bit_builder$;\n"
+    "  } else {\n"
+    "    ensure$capitalized_name$IsMutable();\n"
+    "    $name$_.addAll(other.$name$_);\n"
     "  }\n"
-    "  result.$name$_.addAll(other.$name$_);\n"
+    "  $on_changed$\n"
+    "}\n",
+
+    "if (!other.$name$_.isEmpty()) {\n"
+    "  if ($name$Builder_.isEmpty()) {\n"
+    "    $name$Builder_.dispose();\n"
+    "    $name$Builder_ = null;\n"
+    "    $name$_ = other.$name$_;\n"
+    "    $clear_mutable_bit_builder$;\n"
+    "    $name$Builder_ = \n"
+    "      com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?\n"
+    "         get$capitalized_name$FieldBuilder() : null;\n"
+    "  } else {\n"
+    "    $name$Builder_.addAllMessages(other.$name$_);\n"
+    "  }\n"
     "}\n");
 }
 
 void RepeatedMessageFieldGenerator::
 GenerateBuildingCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n"
-    "  result.$name$_ =\n"
-    "    java.util.Collections.unmodifiableList(result.$name$_);\n"
-    "}\n");
+  // The code below (non-nested builder case) ensures that the result has an
+  // immutable list. If our list is immutable, we can just reuse it. If not,
+  // we make it immutable.
+  PrintNestedBuilderCondition(printer,
+    "if ($get_mutable_bit_builder$) {\n"
+    "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "}\n"
+    "result.$name$_ = $name$_;\n",
+
+    "result.$name$_ = $name$Builder_.build();\n");
 }
 
 void RepeatedMessageFieldGenerator::
@@ -311,17 +844,33 @@
 void RepeatedMessageFieldGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "for ($type$ element : get$capitalized_name$List()) {\n"
-    "  output.write$group_or_message$($number$, element);\n"
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
+    "  output.write$group_or_message$($number$, $name$_.get(i));\n"
     "}\n");
 }
 
 void RepeatedMessageFieldGenerator::
 GenerateSerializedSizeCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "for ($type$ element : get$capitalized_name$List()) {\n"
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
     "  size += com.google.protobuf.CodedOutputStream\n"
-    "    .compute$group_or_message$Size($number$, element);\n"
+    "    .compute$group_or_message$Size($number$, $name$_.get(i));\n"
+    "}\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$List()\n"
+    "    .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (get$capitalized_name$Count() > 0) {\n"
+    "  hash = (37 * hash) + $constant_name$;\n"
+    "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
     "}\n");
 }
 
diff --git a/src/google/protobuf/compiler/java/java_message_field.h b/src/google/protobuf/compiler/java/java_message_field.h
index 66bdd88..2efbcd9 100644
--- a/src/google/protobuf/compiler/java/java_message_field.h
+++ b/src/google/protobuf/compiler/java/java_message_field.h
@@ -46,50 +46,84 @@
 
 class MessageFieldGenerator : public FieldGenerator {
  public:
-  explicit MessageFieldGenerator(const FieldDescriptor* descriptor);
+  explicit MessageFieldGenerator(const FieldDescriptor* descriptor,
+      int messageBitIndex, int builderBitIndex);
   ~MessageFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
 
   string GetBoxedType() const;
 
  private:
   const FieldDescriptor* descriptor_;
   map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
+
+  void PrintNestedBuilderCondition(io::Printer* printer,
+      const char* regular_case, const char* nested_builder_case) const;
+  void PrintNestedBuilderFunction(io::Printer* printer,
+      const char* method_prototype, const char* regular_case,
+      const char* nested_builder_case,
+      const char* trailing_code) const;
 };
 
 class RepeatedMessageFieldGenerator : public FieldGenerator {
  public:
-  explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor);
+  explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+      int messageBitIndex, int builderBitIndex);
   ~RepeatedMessageFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
 
   string GetBoxedType() const;
 
  private:
   const FieldDescriptor* descriptor_;
   map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
+
+  void PrintNestedBuilderCondition(io::Printer* printer,
+      const char* regular_case, const char* nested_builder_case) const;
+  void PrintNestedBuilderFunction(io::Printer* printer,
+      const char* method_prototype, const char* regular_case,
+      const char* nested_builder_case,
+      const char* trailing_code) const;
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/java_plugin_unittest.cc b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
index cfe0188..ccc94c9 100644
--- a/src/google/protobuf/compiler/java/java_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
@@ -56,21 +56,22 @@
 
   virtual bool Generate(const FileDescriptor* file,
                         const string& parameter,
-                        OutputDirectory* output_directory,
+                        GeneratorContext* context,
                         string* error) const {
-    TryInsert("Test.java", "outer_class_scope", output_directory);
-    TryInsert("Test.java", "class_scope:foo.Bar", output_directory);
-    TryInsert("Test.java", "class_scope:foo.Bar.Baz", output_directory);
-    TryInsert("Test.java", "builder_scope:foo.Bar", output_directory);
-    TryInsert("Test.java", "builder_scope:foo.Bar.Baz", output_directory);
-    TryInsert("Test.java", "enum_scope:foo.Qux", output_directory);
+    string filename = "Test.java";
+    TryInsert(filename, "outer_class_scope", context);
+    TryInsert(filename, "class_scope:foo.Bar", context);
+    TryInsert(filename, "class_scope:foo.Bar.Baz", context);
+    TryInsert(filename, "builder_scope:foo.Bar", context);
+    TryInsert(filename, "builder_scope:foo.Bar.Baz", context);
+    TryInsert(filename, "enum_scope:foo.Qux", context);
     return true;
   }
 
   void TryInsert(const string& filename, const string& insertion_point,
-                 OutputDirectory* output_directory) const {
+                 GeneratorContext* context) const {
     scoped_ptr<io::ZeroCopyOutputStream> output(
-      output_directory->OpenForInsert(filename, insertion_point));
+      context->OpenForInsert(filename, insertion_point));
     io::Printer printer(output.get(), '$');
     printer.Print("// inserted $name$\n", "name", insertion_point);
   }
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index f6179bf..addb881 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -154,15 +154,24 @@
 }
 
 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+                           int messageBitIndex,
+                           int builderBitIndex,
                            map<string, string>* variables) {
   (*variables)["name"] =
     UnderscoresToCamelCase(descriptor);
   (*variables)["capitalized_name"] =
     UnderscoresToCapitalizedCamelCase(descriptor);
+  (*variables)["constant_name"] = FieldConstantName(descriptor);
   (*variables)["number"] = SimpleItoa(descriptor->number());
   (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
   (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
+  (*variables)["field_type"] = (*variables)["type"];
+  (*variables)["field_list_type"] = "java.util.List<" +
+      (*variables)["boxed_type"] + ">";
+  (*variables)["empty_list"] = "java.util.Collections.emptyList();";
   (*variables)["default"] = DefaultValue(descriptor);
+  (*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ?
+      "" : ("= " + DefaultValue(descriptor));
   (*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
   (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
   (*variables)["tag_size"] = SimpleItoa(
@@ -175,67 +184,135 @@
   } else {
     (*variables)["null_check"] = "";
   }
+  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+  // by the proto compiler
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
   int fixed_size = FixedSize(GetType(descriptor));
   if (fixed_size != -1) {
     (*variables)["fixed_size"] = SimpleItoa(fixed_size);
   }
+  (*variables)["on_changed"] =
+      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+
+  // For singular messages and builders, one bit is used for the hasField bit.
+  (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+  (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_has_field_bit_builder"] =
+      GenerateClearBit(builderBitIndex);
+
+  // For repated builders, one bit is used for whether the array is immutable.
+  (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
+
+  (*variables)["get_has_field_bit_from_local"] =
+      GenerateGetBitFromLocal(builderBitIndex);
+  (*variables)["set_has_field_bit_to_local"] =
+      GenerateSetBitToLocal(messageBitIndex);
 }
+
 }  // namespace
 
 // ===================================================================
 
 PrimitiveFieldGenerator::
-PrimitiveFieldGenerator(const FieldDescriptor* descriptor)
-  : descriptor_(descriptor) {
-  SetPrimitiveVariables(descriptor, &variables_);
+PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                        int messageBitIndex,
+                        int builderBitIndex)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex) {
+  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+                        &variables_);
 }
 
 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
 
+int PrimitiveFieldGenerator::GetNumBitsForMessage() const {
+  return 1;
+}
+
+int PrimitiveFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void PrimitiveFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$deprecation$boolean has$capitalized_name$();\n"
+    "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
 void PrimitiveFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private boolean has$capitalized_name$;\n"
-    "private $type$ $name$_ = $default$;\n"
-    "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
-    "public $type$ get$capitalized_name$() { return $name$_; }\n");
+    "private $field_type$ $name$_;\n"
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_message$;\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return $name$_;\n"
+    "}\n");
 }
 
 void PrimitiveFieldGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "public boolean has$capitalized_name$() {\n"
-    "  return result.has$capitalized_name$();\n"
-    "}\n"
-    "public $type$ get$capitalized_name$() {\n"
-    "  return result.get$capitalized_name$();\n"
-    "}\n"
-    "public Builder set$capitalized_name$($type$ value) {\n"
+    "private $field_type$ $name$_ $default_init$;\n"
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_builder$;\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  return $name$_;\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
     "$null_check$"
-    "  result.has$capitalized_name$ = true;\n"
-    "  result.$name$_ = value;\n"
+    "  $set_has_field_bit_builder$;\n"
+    "  $name$_ = value;\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n"
-    "public Builder clear$capitalized_name$() {\n"
-    "  result.has$capitalized_name$ = false;\n");
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  $clear_has_field_bit_builder$;\n");
   JavaType type = GetJavaType(descriptor_);
   if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
     // The default value is not a simple literal so we want to avoid executing
     // it multiple times.  Instead, get the default out of the default instance.
     printer->Print(variables_,
-      "  result.$name$_ = getDefaultInstance().get$capitalized_name$();\n");
+      "  $name$_ = getDefaultInstance().get$capitalized_name$();\n");
   } else {
     printer->Print(variables_,
-      "  result.$name$_ = $default$;\n");
+      "  $name$_ = $default$;\n");
   }
   printer->Print(variables_,
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n");
 }
 
 void PrimitiveFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for primitives
+}
+
+void PrimitiveFieldGenerator::
 GenerateInitializationCode(io::Printer* printer) const {
-  // Initialized inline.
+  printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void PrimitiveFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = $default$;\n"
+    "$clear_has_field_bit_builder$;\n");
 }
 
 void PrimitiveFieldGenerator::
@@ -248,32 +325,121 @@
 
 void PrimitiveFieldGenerator::
 GenerateBuildingCode(io::Printer* printer) const {
-  // Nothing to do here for primitive types.
+  printer->Print(variables_,
+    "if ($get_has_field_bit_from_local$) {\n"
+    "  $set_has_field_bit_to_local$;\n"
+    "}\n"
+    "result.$name$_ = $name$_;\n");
 }
 
 void PrimitiveFieldGenerator::
 GenerateParsingCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "set$capitalized_name$(input.read$capitalized_type$());\n");
+    "$set_has_field_bit_builder$;\n"
+    "$name$_ = input.read$capitalized_type$();\n");
 }
 
 void PrimitiveFieldGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (has$capitalized_name$()) {\n"
-    "  output.write$capitalized_type$($number$, get$capitalized_name$());\n"
+    "if ($get_has_field_bit_message$) {\n"
+    "  output.write$capitalized_type$($number$, $name$_);\n"
     "}\n");
 }
 
 void PrimitiveFieldGenerator::
 GenerateSerializedSizeCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (has$capitalized_name$()) {\n"
+    "if ($get_has_field_bit_message$) {\n"
     "  size += com.google.protobuf.CodedOutputStream\n"
-    "    .compute$capitalized_type$Size($number$, get$capitalized_name$());\n"
+    "    .compute$capitalized_type$Size($number$, $name$_);\n"
     "}\n");
 }
 
+void PrimitiveFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  switch (GetJavaType(descriptor_)) {
+    case JAVATYPE_INT:
+    case JAVATYPE_LONG:
+    case JAVATYPE_BOOLEAN:
+      printer->Print(variables_,
+        "result = result && (get$capitalized_name$()\n"
+        "    == other.get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_FLOAT:
+      printer->Print(variables_,
+        "result = result && (Float.floatToIntBits(get$capitalized_name$())"
+        "    == Float.floatToIntBits(other.get$capitalized_name$()));\n");
+      break;
+
+    case JAVATYPE_DOUBLE:
+      printer->Print(variables_,
+        "result = result && (Double.doubleToLongBits(get$capitalized_name$())"
+        "    == Double.doubleToLongBits(other.get$capitalized_name$()));\n");
+      break;
+
+    case JAVATYPE_STRING:
+    case JAVATYPE_BYTES:
+      printer->Print(variables_,
+        "result = result && get$capitalized_name$()\n"
+        "    .equals(other.get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_ENUM:
+    case JAVATYPE_MESSAGE:
+    default:
+      GOOGLE_LOG(FATAL) << "Can't get here.";
+      break;
+  }
+}
+
+void PrimitiveFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "hash = (37 * hash) + $constant_name$;\n");
+  switch (GetJavaType(descriptor_)) {
+    case JAVATYPE_INT:
+      printer->Print(variables_,
+        "hash = (53 * hash) + get$capitalized_name$();\n");
+      break;
+
+    case JAVATYPE_LONG:
+      printer->Print(variables_,
+        "hash = (53 * hash) + hashLong(get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_BOOLEAN:
+      printer->Print(variables_,
+        "hash = (53 * hash) + hashBoolean(get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_FLOAT:
+      printer->Print(variables_,
+        "hash = (53 * hash) + Float.floatToIntBits(\n"
+        "    get$capitalized_name$());\n");
+      break;
+
+    case JAVATYPE_DOUBLE:
+      printer->Print(variables_,
+        "hash = (53 * hash) + hashLong(\n"
+        "    Double.doubleToLongBits(get$capitalized_name$()));\n");
+      break;
+
+    case JAVATYPE_STRING:
+    case JAVATYPE_BYTES:
+      printer->Print(variables_,
+        "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+      break;
+
+    case JAVATYPE_ENUM:
+    case JAVATYPE_MESSAGE:
+    default:
+      GOOGLE_LOG(FATAL) << "Can't get here.";
+      break;
+  }
+}
+
 string PrimitiveFieldGenerator::GetBoxedType() const {
   return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
 }
@@ -281,23 +447,46 @@
 // ===================================================================
 
 RepeatedPrimitiveFieldGenerator::
-RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor)
-  : descriptor_(descriptor) {
-  SetPrimitiveVariables(descriptor, &variables_);
+RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                                int messageBitIndex,
+                                int builderBitIndex)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex) {
+  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+                        &variables_);
 }
 
 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
 
+int RepeatedPrimitiveFieldGenerator::GetNumBitsForMessage() const {
+  return 0;
+}
+
+int RepeatedPrimitiveFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n"
+    "$deprecation$int get$capitalized_name$Count();\n"
+    "$deprecation$$type$ get$capitalized_name$(int index);\n");
+}
+
+
 void RepeatedPrimitiveFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private java.util.List<$boxed_type$> $name$_ =\n"
-    "  java.util.Collections.emptyList();\n"
-    "public java.util.List<$boxed_type$> get$capitalized_name$List() {\n"
+    "private $field_list_type$ $name$_;\n"
+    "$deprecation$public java.util.List<$boxed_type$>\n"
+    "    get$capitalized_name$List() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
     "}\n"
-    "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
-    "public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n"
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
 
@@ -310,76 +499,125 @@
 
 void RepeatedPrimitiveFieldGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
+  // One field is the list and the bit field keeps track of whether the
+  // list is immutable. If it's immutable, the invariant is that it must
+  // either an instance of Collections.emptyList() or it's an ArrayList
+  // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
+  // a refererence to the underlying ArrayList. This invariant allows us to
+  // share instances of lists between protocol buffers avoiding expensive
+  // memory allocations. Note, immutable is a strong guarantee here -- not
+  // just that the list cannot be modified via the reference but that the
+  // list can never be modified.
   printer->Print(variables_,
+    "private $field_list_type$ $name$_ = $empty_list$;\n");
+
+  printer->Print(variables_,
+    "private void ensure$capitalized_name$IsMutable() {\n"
+    "  if (!$get_mutable_bit_builder$) {\n"
+    "    $name$_ = new java.util.ArrayList<$boxed_type$>($name$_);\n"
+    "    $set_mutable_bit_builder$;\n"
+    "   }\n"
+    "}\n");
+
     // Note:  We return an unmodifiable list because otherwise the caller
     //   could hold on to the returned list and modify it after the message
     //   has been built, thus mutating the message which is supposed to be
     //   immutable.
-    "public java.util.List<$boxed_type$> get$capitalized_name$List() {\n"
-    "  return java.util.Collections.unmodifiableList(result.$name$_);\n"
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<$boxed_type$>\n"
+    "    get$capitalized_name$List() {\n"
+    "  return java.util.Collections.unmodifiableList($name$_);\n"
     "}\n"
-    "public int get$capitalized_name$Count() {\n"
-    "  return result.get$capitalized_name$Count();\n"
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
     "}\n"
-    "public $type$ get$capitalized_name$(int index) {\n"
-    "  return result.get$capitalized_name$(index);\n"
+    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "  return $name$_.get(index);\n"
     "}\n"
-    "public Builder set$capitalized_name$(int index, $type$ value) {\n"
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, $type$ value) {\n"
     "$null_check$"
-    "  result.$name$_.set(index, value);\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.set(index, value);\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n"
-    "public Builder add$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
     "$null_check$"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n"
-    "  }\n"
-    "  result.$name$_.add(value);\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(value);\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n"
-    "public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder addAll$capitalized_name$(\n"
     "    java.lang.Iterable<? extends $boxed_type$> values) {\n"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n"
-    "  }\n"
-    "  super.addAll(values, result.$name$_);\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  super.addAll(values, $name$_);\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n"
-    "public Builder clear$capitalized_name$() {\n"
-    "  result.$name$_ = java.util.Collections.emptyList();\n"
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  $name$_ = $empty_list$;\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "  $on_changed$\n"
     "  return this;\n"
     "}\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for primitives
+}
+
+void RepeatedPrimitiveFieldGenerator::
 GenerateInitializationCode(io::Printer* printer) const {
-  // Initialized inline.
+  printer->Print(variables_, "$name$_ = $empty_list$;\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = $empty_list$;\n"
+    "$clear_mutable_bit_builder$;\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::
 GenerateMergingCode(io::Printer* printer) const {
+  // The code below does two optimizations:
+  //   1. If the other list is empty, there's nothing to do. This ensures we
+  //      don't allocate a new array if we already have an immutable one.
+  //   2. If the other list is non-empty and our current list is empty, we can
+  //      reuse the other list which is guaranteed to be immutable.
   printer->Print(variables_,
     "if (!other.$name$_.isEmpty()) {\n"
-    "  if (result.$name$_.isEmpty()) {\n"
-    "    result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n"
+    "  if ($name$_.isEmpty()) {\n"
+    "    $name$_ = other.$name$_;\n"
+    "    $clear_mutable_bit_builder$;\n"
+    "  } else {\n"
+    "    ensure$capitalized_name$IsMutable();\n"
+    "    $name$_.addAll(other.$name$_);\n"
     "  }\n"
-    "  result.$name$_.addAll(other.$name$_);\n"
+    "  $on_changed$\n"
     "}\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::
 GenerateBuildingCode(io::Printer* printer) const {
+  // The code below ensures that the result has an immutable list. If our
+  // list is immutable, we can just reuse it. If not, we make it immutable.
   printer->Print(variables_,
-    "if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n"
-    "  result.$name$_ =\n"
-    "    java.util.Collections.unmodifiableList(result.$name$_);\n"
-    "}\n");
+    "if ($get_mutable_bit_builder$) {\n"
+    "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "}\n"
+    "result.$name$_ = $name$_;\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::
 GenerateParsingCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "add$capitalized_name$(input.read$capitalized_type$());\n");
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(input.read$capitalized_type$());\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::
@@ -401,13 +639,13 @@
       "  output.writeRawVarint32($tag$);\n"
       "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
       "}\n"
-      "for ($type$ element : get$capitalized_name$List()) {\n"
-      "  output.write$capitalized_type$NoTag(element);\n"
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.write$capitalized_type$NoTag($name$_.get(i));\n"
       "}\n");
   } else {
     printer->Print(variables_,
-      "for ($type$ element : get$capitalized_name$List()) {\n"
-      "  output.write$capitalized_type$($number$, element);\n"
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.write$capitalized_type$($number$, $name$_.get(i));\n"
       "}\n");
   }
 }
@@ -421,9 +659,9 @@
 
   if (FixedSize(GetType(descriptor_)) == -1) {
     printer->Print(variables_,
-      "for ($type$ element : get$capitalized_name$List()) {\n"
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
       "  dataSize += com.google.protobuf.CodedOutputStream\n"
-      "    .compute$capitalized_type$SizeNoTag(element);\n"
+      "    .compute$capitalized_type$SizeNoTag($name$_.get(i));\n"
       "}\n");
   } else {
     printer->Print(variables_,
@@ -455,6 +693,22 @@
   printer->Print("}\n");
 }
 
+void RepeatedPrimitiveFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$List()\n"
+    "    .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (get$capitalized_name$Count() > 0) {\n"
+    "  hash = (37 * hash) + $constant_name$;\n"
+    "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+    "}\n");
+}
+
 string RepeatedPrimitiveFieldGenerator::GetBoxedType() const {
   return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
 }
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.h b/src/google/protobuf/compiler/java/java_primitive_field.h
index 4e482a0..7900fac 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.h
+++ b/src/google/protobuf/compiler/java/java_primitive_field.h
@@ -46,49 +46,69 @@
 
 class PrimitiveFieldGenerator : public FieldGenerator {
  public:
-  explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+  explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+      int messageBitIndex, int builderBitIndex);
   ~PrimitiveFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
 
   string GetBoxedType() const;
 
  private:
   const FieldDescriptor* descriptor_;
   map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
 };
 
 class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
  public:
-  explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+  explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+      int messageBitIndex, int builderBitIndex);
   ~RepeatedPrimitiveFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateParsingCodeFromPacked(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
 
   string GetBoxedType() const;
 
  private:
   const FieldDescriptor* descriptor_;
   map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
 };
diff --git a/src/google/protobuf/compiler/java/java_service.cc b/src/google/protobuf/compiler/java/java_service.cc
index 5545bf7..1ae4f46 100644
--- a/src/google/protobuf/compiler/java/java_service.cc
+++ b/src/google/protobuf/compiler/java/java_service.cc
@@ -118,7 +118,7 @@
 
   for (int i = 0; i < descriptor_->method_count(); i++) {
     const MethodDescriptor* method = descriptor_->method(i);
-    printer->Print("@Override\n");
+    printer->Print("@java.lang.Override\n");
     GenerateMethodSignature(printer, method, IS_CONCRETE);
     printer->Print(
       " {\n"
diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
new file mode 100644
index 0000000..a93ff43
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -0,0 +1,605 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Author: jonp@google.com (Jon Perlow)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/java/java_string_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+                           int messageBitIndex,
+                           int builderBitIndex,
+                           map<string, string>* variables) {
+  (*variables)["name"] =
+    UnderscoresToCamelCase(descriptor);
+  (*variables)["capitalized_name"] =
+    UnderscoresToCapitalizedCamelCase(descriptor);
+  (*variables)["constant_name"] = FieldConstantName(descriptor);
+  (*variables)["number"] = SimpleItoa(descriptor->number());
+  (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY";
+
+  (*variables)["default"] = DefaultValue(descriptor);
+  (*variables)["default_init"] = ("= " + DefaultValue(descriptor));
+  (*variables)["capitalized_type"] = "String";
+  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+  (*variables)["tag_size"] = SimpleItoa(
+      WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+  (*variables)["null_check"] =
+      "  if (value == null) {\n"
+      "    throw new NullPointerException();\n"
+      "  }\n";
+
+  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+  // by the proto compiler
+  (*variables)["deprecation"] = descriptor->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
+  (*variables)["on_changed"] =
+      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+
+  // For singular messages and builders, one bit is used for the hasField bit.
+  (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+  (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_has_field_bit_builder"] =
+      GenerateClearBit(builderBitIndex);
+
+  // For repated builders, one bit is used for whether the array is immutable.
+  (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
+  (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
+  (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
+
+  (*variables)["get_has_field_bit_from_local"] =
+      GenerateGetBitFromLocal(builderBitIndex);
+  (*variables)["set_has_field_bit_to_local"] =
+      GenerateSetBitToLocal(messageBitIndex);
+}
+
+}  // namespace
+
+// ===================================================================
+
+StringFieldGenerator::
+StringFieldGenerator(const FieldDescriptor* descriptor,
+                     int messageBitIndex,
+                     int builderBitIndex)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex) {
+  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+                        &variables_);
+}
+
+StringFieldGenerator::~StringFieldGenerator() {}
+
+int StringFieldGenerator::GetNumBitsForMessage() const {
+  return 1;
+}
+
+int StringFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+// A note about how strings are handled. This code used to just store a String
+// in the Message. This had two issues:
+//
+//  1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded
+//     strings, but rather fields that were raw bytes incorrectly marked
+//     as strings in the proto file. This is common because in the proto1
+//     syntax, string was the way to indicate bytes and C++ engineers can
+//     easily make this mistake without affecting the C++ API. By converting to
+//     strings immediately, some java code might corrupt these byte arrays as
+//     it passes through a java server even if the field was never accessed by
+//     application code.
+//
+//  2. There's a performance hit to converting between bytes and strings and
+//     it many cases, the field is never even read by the application code. This
+//     avoids unnecessary conversions in the common use cases.
+//
+// So now, the field for String is maintained as an Object reference which can
+// either store a String or a ByteString. The code uses an instanceof check
+// to see which one it has and converts to the other one if needed. It remembers
+// the last value requested (in a thread safe manner) as this is most likely
+// the one needed next. The thread safety is such that if two threads both
+// convert the field because the changes made by each thread were not visible to
+// the other, they may cause a conversion to happen more times than would
+// otherwise be necessary. This was deemed better than adding synchronization
+// overhead. It will not cause any corruption issues or affect the behavior of
+// the API. The instanceof check is also highly optimized in the JVM and we
+// decided it was better to reduce the memory overhead by not having two
+// separate fields but rather use dynamic type checking.
+//
+// For single fields, the logic for this is done inside the generated code. For
+// repeated fields, the logic is done in LazyStringArrayList and
+// UnmodifiableLazyStringList.
+void StringFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$deprecation$boolean has$capitalized_name$();\n"
+    "$deprecation$String get$capitalized_name$();\n");
+}
+
+void StringFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private Object $name$_;\n"
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_message$;\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "$deprecation$public String get$capitalized_name$() {\n"
+    "  Object ref = $name$_;\n"
+    "  if (ref instanceof String) {\n"
+    "    return (String) ref;\n"
+    "  } else {\n"
+    "    com.google.protobuf.ByteString bs = \n"
+    "        (com.google.protobuf.ByteString) ref;\n"
+    "    String s = bs.toStringUtf8();\n"
+    "    if (com.google.protobuf.Internal.isValidUtf8(bs)) {\n"
+    "      $name$_ = s;\n"
+    "    }\n"
+    "    return s;\n"
+    "  }\n"
+    "}\n"
+    "private com.google.protobuf.ByteString get$capitalized_name$Bytes() {\n"
+    "  Object ref = $name$_;\n"
+    "  if (ref instanceof String) {\n"
+    "    com.google.protobuf.ByteString b = \n"
+    "        com.google.protobuf.ByteString.copyFromUtf8((String) ref);\n"
+    "    $name$_ = b;\n"
+    "    return b;\n"
+    "  } else {\n"
+    "    return (com.google.protobuf.ByteString) ref;\n"
+    "  }\n"
+    "}\n");
+}
+
+void StringFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private Object $name$_ $default_init$;\n"
+    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "  return $get_has_field_bit_builder$;\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "$deprecation$public String get$capitalized_name$() {\n"
+    "  Object ref = $name$_;\n"
+    "  if (!(ref instanceof String)) {\n"
+    "    String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();\n"
+    "    $name$_ = s;\n"
+    "    return s;\n"
+    "  } else {\n"
+    "    return (String) ref;\n"
+    "  }\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "$deprecation$public Builder set$capitalized_name$(String value) {\n"
+    "$null_check$"
+    "  $set_has_field_bit_builder$;\n"
+    "  $name$_ = value;\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n"
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  $clear_has_field_bit_builder$;\n");
+  // The default value is not a simple literal so we want to avoid executing
+  // it multiple times.  Instead, get the default out of the default instance.
+  printer->Print(variables_,
+    "  $name$_ = getDefaultInstance().get$capitalized_name$();\n");
+  printer->Print(variables_,
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "void set$capitalized_name$(com.google.protobuf.ByteString value) {\n"
+    "  $set_has_field_bit_builder$;\n"
+    "  $name$_ = value;\n"
+    "  $on_changed$\n"
+    "}\n");
+}
+
+void StringFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for primitives
+}
+
+void StringFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void StringFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = $default$;\n"
+    "$clear_has_field_bit_builder$;\n");
+}
+
+void StringFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (other.has$capitalized_name$()) {\n"
+    "  set$capitalized_name$(other.get$capitalized_name$());\n"
+    "}\n");
+}
+
+void StringFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_has_field_bit_from_local$) {\n"
+    "  $set_has_field_bit_to_local$;\n"
+    "}\n"
+    "result.$name$_ = $name$_;\n");
+}
+
+void StringFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$set_has_field_bit_builder$;\n"
+    "$name$_ = input.readBytes();\n");
+}
+
+void StringFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_has_field_bit_message$) {\n"
+    "  output.writeBytes($number$, get$capitalized_name$Bytes());\n"
+    "}\n");
+}
+
+void StringFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if ($get_has_field_bit_message$) {\n"
+    "  size += com.google.protobuf.CodedOutputStream\n"
+    "    .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
+    "}\n");
+}
+
+void StringFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$()\n"
+    "    .equals(other.get$capitalized_name$());\n");
+}
+
+void StringFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "hash = (37 * hash) + $constant_name$;\n");
+  printer->Print(variables_,
+    "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+}
+
+string StringFieldGenerator::GetBoxedType() const {
+  return "String";
+}
+
+
+// ===================================================================
+
+RepeatedStringFieldGenerator::
+RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
+                             int messageBitIndex,
+                             int builderBitIndex)
+  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+    builderBitIndex_(builderBitIndex) {
+  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+                        &variables_);
+}
+
+RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
+
+int RepeatedStringFieldGenerator::GetNumBitsForMessage() const {
+  return 0;
+}
+
+int RepeatedStringFieldGenerator::GetNumBitsForBuilder() const {
+  return 1;
+}
+
+void RepeatedStringFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$deprecation$java.util.List<String> get$capitalized_name$List();\n"
+    "$deprecation$int get$capitalized_name$Count();\n"
+    "$deprecation$String get$capitalized_name$(int index);\n");
+}
+
+
+void RepeatedStringFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+  printer->Print(variables_,
+    "private com.google.protobuf.LazyStringList $name$_;\n"
+    "$deprecation$public java.util.List<String>\n"
+    "    get$capitalized_name$List() {\n"
+    "  return $name$_;\n"   // note:  unmodifiable list
+    "}\n"
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n"
+    "$deprecation$public String get$capitalized_name$(int index) {\n"
+    "  return $name$_.get(index);\n"
+    "}\n");
+
+  if (descriptor_->options().packed() &&
+      HasGeneratedMethods(descriptor_->containing_type())) {
+    printer->Print(variables_,
+      "private int $name$MemoizedSerializedSize = -1;\n");
+  }
+}
+
+void RepeatedStringFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+  // One field is the list and the bit field keeps track of whether the
+  // list is immutable. If it's immutable, the invariant is that it must
+  // either an instance of Collections.emptyList() or it's an ArrayList
+  // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
+  // a refererence to the underlying ArrayList. This invariant allows us to
+  // share instances of lists between protocol buffers avoiding expensive
+  // memory allocations. Note, immutable is a strong guarantee here -- not
+  // just that the list cannot be modified via the reference but that the
+  // list can never be modified.
+  printer->Print(variables_,
+    "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n");
+
+  printer->Print(variables_,
+    "private void ensure$capitalized_name$IsMutable() {\n"
+    "  if (!$get_mutable_bit_builder$) {\n"
+    "    $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n"
+    "    $set_mutable_bit_builder$;\n"
+    "   }\n"
+    "}\n");
+
+    // Note:  We return an unmodifiable list because otherwise the caller
+    //   could hold on to the returned list and modify it after the message
+    //   has been built, thus mutating the message which is supposed to be
+    //   immutable.
+  printer->Print(variables_,
+    "$deprecation$public java.util.List<String>\n"
+    "    get$capitalized_name$List() {\n"
+    "  return java.util.Collections.unmodifiableList($name$_);\n"
+    "}\n"
+    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "  return $name$_.size();\n"
+    "}\n"
+    "$deprecation$public String get$capitalized_name$(int index) {\n"
+    "  return $name$_.get(index);\n"
+    "}\n"
+    "$deprecation$public Builder set$capitalized_name$(\n"
+    "    int index, String value) {\n"
+    "$null_check$"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.set(index, value);\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n"
+    "$deprecation$public Builder add$capitalized_name$(String value) {\n"
+    "$null_check$"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(value);\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n"
+    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "    java.lang.Iterable<String> values) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  super.addAll(values, $name$_);\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n"
+    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "  $name$_ = $empty_list$;\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "  $on_changed$\n"
+    "  return this;\n"
+    "}\n");
+
+  printer->Print(variables_,
+    "void add$capitalized_name$(com.google.protobuf.ByteString value) {\n"
+    "  ensure$capitalized_name$IsMutable();\n"
+    "  $name$_.add(value);\n"
+    "  $on_changed$\n"
+    "}\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
+  // noop for primitives
+}
+
+void RepeatedStringFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = $empty_list$;\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_ = $empty_list$;\n"
+    "$clear_mutable_bit_builder$;\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+  // The code below does two optimizations:
+  //   1. If the other list is empty, there's nothing to do. This ensures we
+  //      don't allocate a new array if we already have an immutable one.
+  //   2. If the other list is non-empty and our current list is empty, we can
+  //      reuse the other list which is guaranteed to be immutable.
+  printer->Print(variables_,
+    "if (!other.$name$_.isEmpty()) {\n"
+    "  if ($name$_.isEmpty()) {\n"
+    "    $name$_ = other.$name$_;\n"
+    "    $clear_mutable_bit_builder$;\n"
+    "  } else {\n"
+    "    ensure$capitalized_name$IsMutable();\n"
+    "    $name$_.addAll(other.$name$_);\n"
+    "  }\n"
+    "  $on_changed$\n"
+    "}\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+  // The code below ensures that the result has an immutable list. If our
+  // list is immutable, we can just reuse it. If not, we make it immutable.
+
+  printer->Print(variables_,
+    "if ($get_mutable_bit_builder$) {\n"
+    "  $name$_ = new com.google.protobuf.UnmodifiableLazyStringList(\n"
+    "      $name$_);\n"
+    "  $clear_mutable_bit_builder$;\n"
+    "}\n"
+    "result.$name$_ = $name$_;\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "ensure$capitalized_name$IsMutable();\n"
+    "$name$_.add(input.readBytes());\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+  printer->Print(variables_,
+    "int length = input.readRawVarint32();\n"
+    "int limit = input.pushLimit(length);\n"
+    "while (input.getBytesUntilLimit() > 0) {\n"
+    "  add$capitalized_name$(input.read$capitalized_type$());\n"
+    "}\n"
+    "input.popLimit(limit);\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+  if (descriptor_->options().packed()) {
+    printer->Print(variables_,
+      "if (get$capitalized_name$List().size() > 0) {\n"
+      "  output.writeRawVarint32($tag$);\n"
+      "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+      "}\n"
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.write$capitalized_type$NoTag($name$_.get(i));\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "for (int i = 0; i < $name$_.size(); i++) {\n"
+      "  output.writeBytes($number$, $name$_.getByteString(i));\n"
+      "}\n");
+  }
+}
+
+void RepeatedStringFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "{\n"
+    "  int dataSize = 0;\n");
+  printer->Indent();
+
+  printer->Print(variables_,
+    "for (int i = 0; i < $name$_.size(); i++) {\n"
+    "  dataSize += com.google.protobuf.CodedOutputStream\n"
+    "    .computeBytesSizeNoTag($name$_.getByteString(i));\n"
+    "}\n");
+
+  printer->Print(
+      "size += dataSize;\n");
+
+  if (descriptor_->options().packed()) {
+    printer->Print(variables_,
+      "if (!get$capitalized_name$List().isEmpty()) {\n"
+      "  size += $tag_size$;\n"
+      "  size += com.google.protobuf.CodedOutputStream\n"
+      "      .computeInt32SizeNoTag(dataSize);\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "size += $tag_size$ * get$capitalized_name$List().size();\n");
+  }
+
+  // cache the data size for packed fields.
+  if (descriptor_->options().packed()) {
+    printer->Print(variables_,
+      "$name$MemoizedSerializedSize = dataSize;\n");
+  }
+
+  printer->Outdent();
+  printer->Print("}\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "result = result && get$capitalized_name$List()\n"
+    "    .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (get$capitalized_name$Count() > 0) {\n"
+    "  hash = (37 * hash) + $constant_name$;\n"
+    "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+    "}\n");
+}
+
+string RepeatedStringFieldGenerator::GetBoxedType() const {
+  return "String";
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/java/java_string_field.h b/src/google/protobuf/compiler/java/java_string_field.h
new file mode 100644
index 0000000..8cb4146
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_string_field.h
@@ -0,0 +1,120 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Author: jonp@google.com (Jon Perlow)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class StringFieldGenerator : public FieldGenerator {
+ public:
+  explicit StringFieldGenerator(const FieldDescriptor* descriptor,
+      int messageBitIndex, int builderBitIndex);
+  ~StringFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+  string GetBoxedType() const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator);
+};
+
+class RepeatedStringFieldGenerator : public FieldGenerator {
+ public:
+  explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
+      int messageBitIndex, int builderBitIndex);
+  ~RepeatedStringFieldGenerator();
+
+  // implements FieldGenerator ---------------------------------------
+  int GetNumBitsForMessage() const;
+  int GetNumBitsForBuilder() const;
+  void GenerateInterfaceMembers(io::Printer* printer) const;
+  void GenerateMembers(io::Printer* printer) const;
+  void GenerateBuilderMembers(io::Printer* printer) const;
+  void GenerateInitializationCode(io::Printer* printer) const;
+  void GenerateBuilderClearCode(io::Printer* printer) const;
+  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateBuildingCode(io::Printer* printer) const;
+  void GenerateParsingCode(io::Printer* printer) const;
+  void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+  void GenerateSerializationCode(io::Printer* printer) const;
+  void GenerateSerializedSizeCode(io::Printer* printer) const;
+  void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+  void GenerateEqualsCode(io::Printer* printer) const;
+  void GenerateHashCode(io::Printer* printer) const;
+  string GetBoxedType() const;
+
+ private:
+  const FieldDescriptor* descriptor_;
+  map<string, string> variables_;
+  const int messageBitIndex_;
+  const int builderBitIndex_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__
diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc
index 83d5a4e..5b76af2 100644
--- a/src/google/protobuf/compiler/mock_code_generator.cc
+++ b/src/google/protobuf/compiler/mock_code_generator.cc
@@ -45,6 +45,16 @@
 namespace protobuf {
 namespace compiler {
 
+// Returns the list of the names of files in all_files in the form of a
+// comma-separated string.
+string CommaSeparatedList(const vector<const FileDescriptor*> all_files) {
+  vector<string> names;
+  for (int i = 0; i < all_files.size(); i++) {
+    names.push_back(all_files[i]->name());
+  }
+  return JoinStrings(names, ",");
+}
+
 static const char* kFirstInsertionPointName = "first_mock_insertion_point";
 static const char* kSecondInsertionPointName = "second_mock_insertion_point";
 static const char* kFirstInsertionPoint =
@@ -63,6 +73,7 @@
     const string& insertions,
     const string& file,
     const string& first_message_name,
+    const string& first_parsed_file_name,
     const string& output_directory) {
   string content;
   ASSERT_TRUE(File::ReadFileToString(
@@ -84,7 +95,8 @@
   }
 
   ASSERT_EQ(lines.size(), 3 + insertion_list.size() * 2);
-  EXPECT_EQ(GetOutputFileContent(name, parameter, file, first_message_name),
+  EXPECT_EQ(GetOutputFileContent(name, parameter, file,
+                                 first_parsed_file_name, first_message_name),
             lines[0]);
 
   EXPECT_EQ(kFirstInsertionPoint, lines[1 + insertion_list.size()]);
@@ -92,12 +104,12 @@
 
   for (int i = 0; i < insertion_list.size(); i++) {
     EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert",
-                                   file, first_message_name),
+                                   file, file, first_message_name),
               lines[1 + i]);
     // Second insertion point is indented, so the inserted text should
     // automatically be indented too.
     EXPECT_EQ("  " + GetOutputFileContent(insertion_list[i], "second_insert",
-                                          file, first_message_name),
+                                          file, file, first_message_name),
               lines[2 + insertion_list.size() + i]);
   }
 }
@@ -105,7 +117,7 @@
 bool MockCodeGenerator::Generate(
     const FileDescriptor* file,
     const string& parameter,
-    OutputDirectory* output_directory,
+    GeneratorContext* context,
     string* error) const {
   for (int i = 0; i < file->message_type_count(); i++) {
     if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) {
@@ -134,11 +146,12 @@
     for (int i = 0; i < insert_into.size(); i++) {
       {
         scoped_ptr<io::ZeroCopyOutputStream> output(
-            output_directory->OpenForInsert(
+            context->OpenForInsert(
               GetOutputFileName(insert_into[i], file),
               kFirstInsertionPointName));
         io::Printer printer(output.get(), '$');
-        printer.PrintRaw(GetOutputFileContent(name_, "first_insert", file));
+        printer.PrintRaw(GetOutputFileContent(name_, "first_insert",
+                                              file, context));
         if (printer.failed()) {
           *error = "MockCodeGenerator detected write error.";
           return false;
@@ -147,11 +160,12 @@
 
       {
         scoped_ptr<io::ZeroCopyOutputStream> output(
-            output_directory->OpenForInsert(
+            context->OpenForInsert(
               GetOutputFileName(insert_into[i], file),
               kSecondInsertionPointName));
         io::Printer printer(output.get(), '$');
-        printer.PrintRaw(GetOutputFileContent(name_, "second_insert", file));
+        printer.PrintRaw(GetOutputFileContent(name_, "second_insert",
+                                              file, context));
         if (printer.failed()) {
           *error = "MockCodeGenerator detected write error.";
           return false;
@@ -160,10 +174,11 @@
     }
   } else {
     scoped_ptr<io::ZeroCopyOutputStream> output(
-        output_directory->Open(GetOutputFileName(name_, file)));
+        context->Open(GetOutputFileName(name_, file)));
 
     io::Printer printer(output.get(), '$');
-    printer.PrintRaw(GetOutputFileContent(name_, parameter, file));
+    printer.PrintRaw(GetOutputFileContent(name_, parameter,
+                                          file, context));
     printer.PrintRaw(kFirstInsertionPoint);
     printer.PrintRaw(kSecondInsertionPoint);
 
@@ -186,11 +201,16 @@
   return file + ".MockCodeGenerator." + generator_name;
 }
 
-string MockCodeGenerator::GetOutputFileContent(const string& generator_name,
-                                               const string& parameter,
-                                               const FileDescriptor* file) {
+string MockCodeGenerator::GetOutputFileContent(
+    const string& generator_name,
+    const string& parameter,
+    const FileDescriptor* file,
+    GeneratorContext *context) {
+  vector<const FileDescriptor*> all_files;
+  context->ListParsedFiles(&all_files);
   return GetOutputFileContent(
       generator_name, parameter, file->name(),
+      CommaSeparatedList(all_files),
       file->message_type_count() > 0 ?
           file->message_type(0)->name() : "(none)");
 }
@@ -199,9 +219,11 @@
     const string& generator_name,
     const string& parameter,
     const string& file,
+    const string& parsed_file_list,
     const string& first_message_name) {
-  return strings::Substitute("$0: $1, $2, $3\n",
-      generator_name, parameter, file, first_message_name);
+  return strings::Substitute("$0: $1, $2, $3, $4\n",
+      generator_name, parameter, file,
+      first_message_name, parsed_file_list);
 }
 
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/mock_code_generator.h b/src/google/protobuf/compiler/mock_code_generator.h
index 01d69dd..5c7942b 100644
--- a/src/google/protobuf/compiler/mock_code_generator.h
+++ b/src/google/protobuf/compiler/mock_code_generator.h
@@ -69,11 +69,14 @@
   //
   // |insertions| is a comma-separated list of names of MockCodeGenerators which
   // should have inserted lines into this file.
+  // |parsed_file_list| is a comma-separated list of names of the files
+  // that are being compiled together in this run.
   static void ExpectGenerated(const string& name,
                               const string& parameter,
                               const string& insertions,
                               const string& file,
                               const string& first_message_name,
+                              const string& parsed_file_list,
                               const string& output_directory);
 
   // Get the name of the file which would be written by the given generator.
@@ -86,7 +89,7 @@
 
   virtual bool Generate(const FileDescriptor* file,
                         const string& parameter,
-                        OutputDirectory* output_directory,
+                        GeneratorContext* context,
                         string* error) const;
 
  private:
@@ -94,10 +97,12 @@
 
   static string GetOutputFileContent(const string& generator_name,
                                      const string& parameter,
-                                     const FileDescriptor* file);
+                                     const FileDescriptor* file,
+                                     GeneratorContext *context);
   static string GetOutputFileContent(const string& generator_name,
                                      const string& parameter,
                                      const string& file,
+                                     const string& parsed_file_list,
                                      const string& first_message_name);
 };
 
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index 9fcb131..34317b1 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -250,20 +250,69 @@
   AddError(input_->current().line, input_->current().column, error);
 }
 
-void Parser::RecordLocation(
-    const Message* descriptor,
-    DescriptorPool::ErrorCollector::ErrorLocation location,
-    int line, int column) {
-  if (source_location_table_ != NULL) {
-    source_location_table_->Add(descriptor, location, line, column);
+// -------------------------------------------------------------------
+
+Parser::LocationRecorder::LocationRecorder(Parser* parser)
+  : parser_(parser),
+    location_(parser_->source_code_info_->add_location()) {
+  location_->add_span(parser_->input_->current().line);
+  location_->add_span(parser_->input_->current().column);
+}
+
+Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent) {
+  Init(parent);
+}
+
+Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent,
+                                           int path1) {
+  Init(parent);
+  AddPath(path1);
+}
+
+Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent,
+                                           int path1, int path2) {
+  Init(parent);
+  AddPath(path1);
+  AddPath(path2);
+}
+
+void Parser::LocationRecorder::Init(const LocationRecorder& parent) {
+  parser_ = parent.parser_;
+  location_ = parser_->source_code_info_->add_location();
+  location_->mutable_path()->CopyFrom(parent.location_->path());
+
+  location_->add_span(parser_->input_->current().line);
+  location_->add_span(parser_->input_->current().column);
+}
+
+Parser::LocationRecorder::~LocationRecorder() {
+  if (location_->span_size() <= 2) {
+    EndAt(parser_->input_->previous());
   }
 }
 
-void Parser::RecordLocation(
-    const Message* descriptor,
+void Parser::LocationRecorder::AddPath(int path_component) {
+  location_->add_path(path_component);
+}
+
+void Parser::LocationRecorder::StartAt(const io::Tokenizer::Token& token) {
+  location_->set_span(0, token.line);
+  location_->set_span(1, token.column);
+}
+
+void Parser::LocationRecorder::EndAt(const io::Tokenizer::Token& token) {
+  if (token.line != location_->span(0)) {
+    location_->add_span(token.line);
+  }
+  location_->add_span(token.end_column);
+}
+
+void Parser::LocationRecorder::RecordLegacyLocation(const Message* descriptor,
     DescriptorPool::ErrorCollector::ErrorLocation location) {
-  RecordLocation(descriptor, location,
-                 input_->current().line, input_->current().column);
+  if (parser_->source_location_table_ != NULL) {
+    parser_->source_location_table_->Add(
+        descriptor, location, location_->span(0), location_->span(1));
+  }
 }
 
 // -------------------------------------------------------------------
@@ -308,38 +357,51 @@
   had_errors_ = false;
   syntax_identifier_.clear();
 
+  // Note that |file| could be NULL at this point if
+  // stop_after_syntax_identifier_ is true.  So, we conservatively allocate
+  // SourceCodeInfo on the stack, then swap it into the FileDescriptorProto
+  // later on.
+  SourceCodeInfo source_code_info;
+  source_code_info_ = &source_code_info;
+
   if (LookingAtType(io::Tokenizer::TYPE_START)) {
     // Advance to first token.
     input_->Next();
   }
 
-  if (require_syntax_identifier_ || LookingAt("syntax")) {
-    if (!ParseSyntaxIdentifier()) {
-      // Don't attempt to parse the file if we didn't recognize the syntax
-      // identifier.
-      return false;
+  {
+    LocationRecorder root_location(this);
+
+    if (require_syntax_identifier_ || LookingAt("syntax")) {
+      if (!ParseSyntaxIdentifier()) {
+        // Don't attempt to parse the file if we didn't recognize the syntax
+        // identifier.
+        return false;
+      }
+    } else if (!stop_after_syntax_identifier_) {
+      syntax_identifier_ = "proto2";
     }
-  } else if (!stop_after_syntax_identifier_) {
-    syntax_identifier_ = "proto2";
-  }
 
-  if (stop_after_syntax_identifier_) return !had_errors_;
+    if (stop_after_syntax_identifier_) return !had_errors_;
 
-  // Repeatedly parse statements until we reach the end of the file.
-  while (!AtEnd()) {
-    if (!ParseTopLevelStatement(file)) {
-      // This statement failed to parse.  Skip it, but keep looping to parse
-      // other statements.
-      SkipStatement();
+    // Repeatedly parse statements until we reach the end of the file.
+    while (!AtEnd()) {
+      if (!ParseTopLevelStatement(file, root_location)) {
+        // This statement failed to parse.  Skip it, but keep looping to parse
+        // other statements.
+        SkipStatement();
 
-      if (LookingAt("}")) {
-        AddError("Unmatched \"}\".");
-        input_->Next();
+        if (LookingAt("}")) {
+          AddError("Unmatched \"}\".");
+          input_->Next();
+        }
       }
     }
   }
 
   input_ = NULL;
+  source_code_info_ = NULL;
+  source_code_info.Swap(file->mutable_source_code_info());
   return !had_errors_;
 }
 
@@ -363,25 +425,40 @@
   return true;
 }
 
-bool Parser::ParseTopLevelStatement(FileDescriptorProto* file) {
+bool Parser::ParseTopLevelStatement(FileDescriptorProto* file,
+                                    const LocationRecorder& root_location) {
   if (TryConsume(";")) {
     // empty statement; ignore
     return true;
   } else if (LookingAt("message")) {
-    return ParseMessageDefinition(file->add_message_type());
+    LocationRecorder location(root_location,
+      FileDescriptorProto::kMessageTypeFieldNumber, file->message_type_size());
+    return ParseMessageDefinition(file->add_message_type(), location);
   } else if (LookingAt("enum")) {
-    return ParseEnumDefinition(file->add_enum_type());
+    LocationRecorder location(root_location,
+      FileDescriptorProto::kEnumTypeFieldNumber, file->enum_type_size());
+    return ParseEnumDefinition(file->add_enum_type(), location);
   } else if (LookingAt("service")) {
-    return ParseServiceDefinition(file->add_service());
+    LocationRecorder location(root_location,
+      FileDescriptorProto::kServiceFieldNumber, file->service_size());
+    return ParseServiceDefinition(file->add_service(), location);
   } else if (LookingAt("extend")) {
+    LocationRecorder location(root_location,
+        FileDescriptorProto::kExtensionFieldNumber);
     return ParseExtend(file->mutable_extension(),
-                       file->mutable_message_type());
+                       file->mutable_message_type(),
+                       root_location,
+                       FileDescriptorProto::kMessageTypeFieldNumber,
+                       location);
   } else if (LookingAt("import")) {
-    return ParseImport(file->add_dependency());
+    int index = file->dependency_size();
+    return ParseImport(file->add_dependency(), root_location, index);
   } else if (LookingAt("package")) {
-    return ParsePackage(file);
+    return ParsePackage(file, root_location);
   } else if (LookingAt("option")) {
-    return ParseOption(file->mutable_options());
+    LocationRecorder location(root_location,
+        FileDescriptorProto::kOptionsFieldNumber);
+    return ParseOption(file->mutable_options(), location);
   } else {
     AddError("Expected top-level statement (e.g. \"message\").");
     return false;
@@ -391,15 +468,22 @@
 // -------------------------------------------------------------------
 // Messages
 
-bool Parser::ParseMessageDefinition(DescriptorProto* message) {
+bool Parser::ParseMessageDefinition(DescriptorProto* message,
+                                    const LocationRecorder& message_location) {
   DO(Consume("message"));
-  RecordLocation(message, DescriptorPool::ErrorCollector::NAME);
-  DO(ConsumeIdentifier(message->mutable_name(), "Expected message name."));
-  DO(ParseMessageBlock(message));
+  {
+    LocationRecorder location(message_location,
+                              DescriptorProto::kNameFieldNumber);
+    location.RecordLegacyLocation(
+        message, DescriptorPool::ErrorCollector::NAME);
+    DO(ConsumeIdentifier(message->mutable_name(), "Expected message name."));
+  }
+  DO(ParseMessageBlock(message, message_location));
   return true;
 }
 
-bool Parser::ParseMessageBlock(DescriptorProto* message) {
+bool Parser::ParseMessageBlock(DescriptorProto* message,
+                               const LocationRecorder& message_location) {
   DO(Consume("{"));
 
   while (!TryConsume("}")) {
@@ -408,7 +492,7 @@
       return false;
     }
 
-    if (!ParseMessageStatement(message)) {
+    if (!ParseMessageStatement(message, message_location)) {
       // This statement failed to parse.  Skip it, but keep looping to parse
       // other statements.
       SkipStatement();
@@ -418,66 +502,133 @@
   return true;
 }
 
-bool Parser::ParseMessageStatement(DescriptorProto* message) {
+bool Parser::ParseMessageStatement(DescriptorProto* message,
+                                   const LocationRecorder& message_location) {
   if (TryConsume(";")) {
     // empty statement; ignore
     return true;
   } else if (LookingAt("message")) {
-    return ParseMessageDefinition(message->add_nested_type());
+    LocationRecorder location(message_location,
+                              DescriptorProto::kNestedTypeFieldNumber,
+                              message->nested_type_size());
+    return ParseMessageDefinition(message->add_nested_type(), location);
   } else if (LookingAt("enum")) {
-    return ParseEnumDefinition(message->add_enum_type());
+    LocationRecorder location(message_location,
+                              DescriptorProto::kEnumTypeFieldNumber,
+                              message->enum_type_size());
+    return ParseEnumDefinition(message->add_enum_type(), location);
   } else if (LookingAt("extensions")) {
-    return ParseExtensions(message);
+    LocationRecorder location(message_location,
+                              DescriptorProto::kExtensionRangeFieldNumber);
+    return ParseExtensions(message, location);
   } else if (LookingAt("extend")) {
+    LocationRecorder location(message_location,
+                              DescriptorProto::kExtensionFieldNumber);
     return ParseExtend(message->mutable_extension(),
-                       message->mutable_nested_type());
+                       message->mutable_nested_type(),
+                       message_location,
+                       DescriptorProto::kNestedTypeFieldNumber,
+                       location);
   } else if (LookingAt("option")) {
-    return ParseOption(message->mutable_options());
+    LocationRecorder location(message_location,
+                              DescriptorProto::kOptionsFieldNumber);
+    return ParseOption(message->mutable_options(), location);
   } else {
+    LocationRecorder location(message_location,
+                              DescriptorProto::kFieldFieldNumber,
+                              message->field_size());
     return ParseMessageField(message->add_field(),
-                             message->mutable_nested_type());
+                             message->mutable_nested_type(),
+                             message_location,
+                             DescriptorProto::kNestedTypeFieldNumber,
+                             location);
   }
 }
 
 bool Parser::ParseMessageField(FieldDescriptorProto* field,
-                               RepeatedPtrField<DescriptorProto>* messages) {
+                               RepeatedPtrField<DescriptorProto>* messages,
+                               const LocationRecorder& parent_location,
+                               int location_field_number_for_nested_type,
+                               const LocationRecorder& field_location) {
   // Parse label and type.
-  FieldDescriptorProto::Label label;
-  DO(ParseLabel(&label));
-  field->set_label(label);
+  io::Tokenizer::Token label_token = input_->current();
+  {
+    LocationRecorder location(field_location,
+                              FieldDescriptorProto::kLabelFieldNumber);
+    FieldDescriptorProto::Label label;
+    DO(ParseLabel(&label));
+    field->set_label(label);
+  }
 
-  RecordLocation(field, DescriptorPool::ErrorCollector::TYPE);
-  FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32;
-  string type_name;
-  DO(ParseType(&type, &type_name));
-  if (type_name.empty()) {
-    field->set_type(type);
-  } else {
-    field->set_type_name(type_name);
+  {
+    LocationRecorder location(field_location);  // add path later
+    location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::TYPE);
+
+    FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32;
+    string type_name;
+    DO(ParseType(&type, &type_name));
+    if (type_name.empty()) {
+      location.AddPath(FieldDescriptorProto::kTypeFieldNumber);
+      field->set_type(type);
+    } else {
+      location.AddPath(FieldDescriptorProto::kTypeNameFieldNumber);
+      field->set_type_name(type_name);
+    }
   }
 
   // Parse name and '='.
-  RecordLocation(field, DescriptorPool::ErrorCollector::NAME);
   io::Tokenizer::Token name_token = input_->current();
-  DO(ConsumeIdentifier(field->mutable_name(), "Expected field name."));
+  {
+    LocationRecorder location(field_location,
+                              FieldDescriptorProto::kNameFieldNumber);
+    location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::NAME);
+    DO(ConsumeIdentifier(field->mutable_name(), "Expected field name."));
+  }
   DO(Consume("=", "Missing field number."));
 
   // Parse field number.
-  RecordLocation(field, DescriptorPool::ErrorCollector::NUMBER);
-  int number;
-  DO(ConsumeInteger(&number, "Expected field number."));
-  field->set_number(number);
+  {
+    LocationRecorder location(field_location,
+                              FieldDescriptorProto::kNumberFieldNumber);
+    location.RecordLegacyLocation(
+        field, DescriptorPool::ErrorCollector::NUMBER);
+    int number;
+    DO(ConsumeInteger(&number, "Expected field number."));
+    field->set_number(number);
+  }
 
   // Parse options.
-  DO(ParseFieldOptions(field));
+  DO(ParseFieldOptions(field, field_location));
 
   // Deal with groups.
-  if (type_name.empty() && type == FieldDescriptorProto::TYPE_GROUP) {
+  if (field->has_type() && field->type() == FieldDescriptorProto::TYPE_GROUP) {
+    // Awkward:  Since a group declares both a message type and a field, we
+    //   have to create overlapping locations.
+    LocationRecorder group_location(parent_location);
+    group_location.StartAt(label_token);
+    group_location.AddPath(location_field_number_for_nested_type);
+    group_location.AddPath(messages->size());
+
     DescriptorProto* group = messages->Add();
     group->set_name(field->name());
+
     // Record name location to match the field name's location.
-    RecordLocation(group, DescriptorPool::ErrorCollector::NAME,
-                   name_token.line, name_token.column);
+    {
+      LocationRecorder location(group_location,
+                                DescriptorProto::kNameFieldNumber);
+      location.StartAt(name_token);
+      location.EndAt(name_token);
+      location.RecordLegacyLocation(
+          group, DescriptorPool::ErrorCollector::NAME);
+    }
+
+    // The field's type_name also comes from the name.  Confusing!
+    {
+      LocationRecorder location(field_location,
+                                FieldDescriptorProto::kTypeNameFieldNumber);
+      location.StartAt(name_token);
+      location.EndAt(name_token);
+    }
 
     // As a hack for backwards-compatibility, we force the group name to start
     // with a capital letter and lower-case the field name.  New code should
@@ -490,7 +641,7 @@
 
     field->set_type_name(group->name());
     if (LookingAt("{")) {
-      DO(ParseMessageBlock(group));
+      DO(ParseMessageBlock(group, group_location));
     } else {
       AddError("Missing group body.");
       return false;
@@ -502,15 +653,23 @@
   return true;
 }
 
-bool Parser::ParseFieldOptions(FieldDescriptorProto* field) {
-  if (!TryConsume("[")) return true;
+bool Parser::ParseFieldOptions(FieldDescriptorProto* field,
+                               const LocationRecorder& field_location) {
+  if (!LookingAt("[")) return true;
+
+  LocationRecorder location(field_location,
+                            FieldDescriptorProto::kOptionsFieldNumber);
+
+  DO(Consume("["));
 
   // Parse field options.
   do {
     if (LookingAt("default")) {
-      DO(ParseDefaultAssignment(field));
+      // We intentionally pass field_location rather than location here, since
+      // the default value is not actually an option.
+      DO(ParseDefaultAssignment(field, field_location));
     } else {
-      DO(ParseOptionAssignment(field->mutable_options()));
+      DO(ParseOptionAssignment(field->mutable_options(), location));
     }
   } while (TryConsume(","));
 
@@ -518,7 +677,8 @@
   return true;
 }
 
-bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field) {
+bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field,
+                                    const LocationRecorder& field_location) {
   if (field->has_default_value()) {
     AddError("Already set option \"default\".");
     field->clear_default_value();
@@ -527,7 +687,10 @@
   DO(Consume("default"));
   DO(Consume("="));
 
-  RecordLocation(field, DescriptorPool::ErrorCollector::DEFAULT_VALUE);
+  LocationRecorder location(field_location,
+                            FieldDescriptorProto::kDefaultValueFieldNumber);
+  location.RecordLegacyLocation(
+      field, DescriptorPool::ErrorCollector::DEFAULT_VALUE);
   string* default_value = field->mutable_default_value();
 
   if (!field->has_type()) {
@@ -634,26 +797,35 @@
   return true;
 }
 
-bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option) {
+bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
+                                 const LocationRecorder& part_location) {
   UninterpretedOption::NamePart* name = uninterpreted_option->add_name();
   string identifier;  // We parse identifiers into this string.
   if (LookingAt("(")) {  // This is an extension.
     DO(Consume("("));
-    // An extension name consists of dot-separated identifiers, and may begin
-    // with a dot.
-    if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
-      DO(ConsumeIdentifier(&identifier, "Expected identifier."));
-      name->mutable_name_part()->append(identifier);
+
+    {
+      LocationRecorder location(
+          part_location, UninterpretedOption::NamePart::kNamePartFieldNumber);
+      // An extension name consists of dot-separated identifiers, and may begin
+      // with a dot.
+      if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
+        DO(ConsumeIdentifier(&identifier, "Expected identifier."));
+        name->mutable_name_part()->append(identifier);
+      }
+      while (LookingAt(".")) {
+        DO(Consume("."));
+        name->mutable_name_part()->append(".");
+        DO(ConsumeIdentifier(&identifier, "Expected identifier."));
+        name->mutable_name_part()->append(identifier);
+      }
     }
-    while (LookingAt(".")) {
-      DO(Consume("."));
-      name->mutable_name_part()->append(".");
-      DO(ConsumeIdentifier(&identifier, "Expected identifier."));
-      name->mutable_name_part()->append(identifier);
-    }
+
     DO(Consume(")"));
     name->set_is_extension(true);
   } else {  // This is a regular field.
+    LocationRecorder location(
+        part_location, UninterpretedOption::NamePart::kNamePartFieldNumber);
     DO(ConsumeIdentifier(&identifier, "Expected identifier."));
     name->mutable_name_part()->append(identifier);
     name->set_is_extension(false);
@@ -661,34 +833,75 @@
   return true;
 }
 
+bool Parser::ParseUninterpretedBlock(string* value) {
+  // Note that enclosing braces are not added to *value.
+  DO(Consume("{"));
+  int brace_depth = 1;
+  while (!AtEnd()) {
+    if (LookingAt("{")) {
+      brace_depth++;
+    } else if (LookingAt("}")) {
+      brace_depth--;
+      if (brace_depth == 0) {
+        input_->Next();
+        return true;
+      }
+    }
+    // TODO(sanjay): Interpret line/column numbers to preserve formatting
+    if (!value->empty()) value->push_back(' ');
+    value->append(input_->current().text);
+    input_->Next();
+  }
+  AddError("Unexpected end of stream while parsing aggregate value.");
+  return false;
+}
+
 // We don't interpret the option here. Instead we store it in an
 // UninterpretedOption, to be interpreted later.
-bool Parser::ParseOptionAssignment(Message* options) {
+bool Parser::ParseOptionAssignment(Message* options,
+                                   const LocationRecorder& options_location) {
   // Create an entry in the uninterpreted_option field.
   const FieldDescriptor* uninterpreted_option_field = options->GetDescriptor()->
       FindFieldByName("uninterpreted_option");
   GOOGLE_CHECK(uninterpreted_option_field != NULL)
       << "No field named \"uninterpreted_option\" in the Options proto.";
 
+  const Reflection* reflection = options->GetReflection();
+
+  LocationRecorder location(
+      options_location, uninterpreted_option_field->number(),
+      reflection->FieldSize(*options, uninterpreted_option_field));
+
   UninterpretedOption* uninterpreted_option = down_cast<UninterpretedOption*>(
       options->GetReflection()->AddMessage(options,
                                            uninterpreted_option_field));
 
   // Parse dot-separated name.
-  RecordLocation(uninterpreted_option,
-                 DescriptorPool::ErrorCollector::OPTION_NAME);
+  {
+    LocationRecorder name_location(location,
+                                   UninterpretedOption::kNameFieldNumber);
+    name_location.RecordLegacyLocation(
+        uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_NAME);
 
-  DO(ParseOptionNamePart(uninterpreted_option));
+    {
+      LocationRecorder part_location(name_location,
+                                     uninterpreted_option->name_size());
+      DO(ParseOptionNamePart(uninterpreted_option, part_location));
+    }
 
-  while (LookingAt(".")) {
-    DO(Consume("."));
-    DO(ParseOptionNamePart(uninterpreted_option));
+    while (LookingAt(".")) {
+      DO(Consume("."));
+      LocationRecorder part_location(name_location,
+                                     uninterpreted_option->name_size());
+      DO(ParseOptionNamePart(uninterpreted_option, part_location));
+    }
   }
 
   DO(Consume("="));
 
-  RecordLocation(uninterpreted_option,
-                 DescriptorPool::ErrorCollector::OPTION_VALUE);
+  LocationRecorder value_location(location);
+  value_location.RecordLegacyLocation(
+      uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_VALUE);
 
   // All values are a single token, except for negative numbers, which consist
   // of a single '-' symbol, followed by a positive number.
@@ -704,6 +917,7 @@
       return false;
 
     case io::Tokenizer::TYPE_IDENTIFIER: {
+      value_location.AddPath(UninterpretedOption::kIdentifierValueFieldNumber);
       if (is_negative) {
         AddError("Invalid '-' symbol before identifier.");
         return false;
@@ -720,15 +934,19 @@
           is_negative ? static_cast<uint64>(kint64max) + 1 : kuint64max;
       DO(ConsumeInteger64(max_value, &value, "Expected integer."));
       if (is_negative) {
-        uninterpreted_option->set_negative_int_value(
-            -static_cast<int64>(value));
+        value_location.AddPath(
+            UninterpretedOption::kNegativeIntValueFieldNumber);
+        uninterpreted_option->set_negative_int_value(-static_cast<int64>(value));
       } else {
+        value_location.AddPath(
+            UninterpretedOption::kPositiveIntValueFieldNumber);
         uninterpreted_option->set_positive_int_value(value);
       }
       break;
     }
 
     case io::Tokenizer::TYPE_FLOAT: {
+      value_location.AddPath(UninterpretedOption::kDoubleValueFieldNumber);
       double value;
       DO(ConsumeNumber(&value, "Expected number."));
       uninterpreted_option->set_double_value(is_negative ? -value : value);
@@ -736,6 +954,7 @@
     }
 
     case io::Tokenizer::TYPE_STRING: {
+      value_location.AddPath(UninterpretedOption::kStringValueFieldNumber);
       if (is_negative) {
         AddError("Invalid '-' symbol before string.");
         return false;
@@ -747,31 +966,57 @@
     }
 
     case io::Tokenizer::TYPE_SYMBOL:
-      AddError("Expected option value.");
-      return false;
+      if (LookingAt("{")) {
+        value_location.AddPath(UninterpretedOption::kAggregateValueFieldNumber);
+        DO(ParseUninterpretedBlock(
+            uninterpreted_option->mutable_aggregate_value()));
+      } else {
+        AddError("Expected option value.");
+        return false;
+      }
+      break;
   }
 
   return true;
 }
 
-bool Parser::ParseExtensions(DescriptorProto* message) {
+bool Parser::ParseExtensions(DescriptorProto* message,
+                             const LocationRecorder& extensions_location) {
   // Parse the declaration.
   DO(Consume("extensions"));
 
   do {
+    // Note that kExtensionRangeFieldNumber was already pushed by the parent.
+    LocationRecorder location(extensions_location,
+                              message->extension_range_size());
+
     DescriptorProto::ExtensionRange* range = message->add_extension_range();
-    RecordLocation(range, DescriptorPool::ErrorCollector::NUMBER);
+    location.RecordLegacyLocation(
+        range, DescriptorPool::ErrorCollector::NUMBER);
 
     int start, end;
-    DO(ConsumeInteger(&start, "Expected field number range."));
+    io::Tokenizer::Token start_token;
+
+    {
+      LocationRecorder start_location(
+          location, DescriptorProto::ExtensionRange::kStartFieldNumber);
+      start_token = input_->current();
+      DO(ConsumeInteger(&start, "Expected field number range."));
+    }
 
     if (TryConsume("to")) {
+      LocationRecorder end_location(
+          location, DescriptorProto::ExtensionRange::kEndFieldNumber);
       if (TryConsume("max")) {
         end = FieldDescriptor::kMaxNumber;
       } else {
         DO(ConsumeInteger(&end, "Expected integer."));
       }
     } else {
+      LocationRecorder end_location(
+          location, DescriptorProto::ExtensionRange::kEndFieldNumber);
+      end_location.StartAt(start_token);
+      end_location.EndAt(start_token);
       end = start;
     }
 
@@ -788,16 +1033,17 @@
 }
 
 bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
-                         RepeatedPtrField<DescriptorProto>* messages) {
+                         RepeatedPtrField<DescriptorProto>* messages,
+                         const LocationRecorder& parent_location,
+                         int location_field_number_for_nested_type,
+                         const LocationRecorder& extend_location) {
   DO(Consume("extend"));
 
-  // We expect to see at least one extension field defined in the extend block.
-  // We need to create it now so we can record the extendee's location.
-  FieldDescriptorProto* first_field = extensions->Add();
-
   // Parse the extendee type.
-  RecordLocation(first_field, DescriptorPool::ErrorCollector::EXTENDEE);
-  DO(ParseUserDefinedType(first_field->mutable_extendee()));
+  io::Tokenizer::Token extendee_start = input_->current();
+  string extendee;
+  DO(ParseUserDefinedType(&extendee));
+  io::Tokenizer::Token extendee_end = input_->previous();
 
   // Parse the block.
   DO(Consume("{"));
@@ -810,16 +1056,29 @@
       return false;
     }
 
-    FieldDescriptorProto* field;
-    if (is_first) {
-      field = first_field;
-      is_first = false;
-    } else {
-      field = extensions->Add();
-      field->set_extendee(first_field->extendee());
+    // Note that kExtensionFieldNumber was already pushed by the parent.
+    LocationRecorder location(extend_location, extensions->size());
+
+    FieldDescriptorProto* field = extensions->Add();
+
+    {
+      LocationRecorder extendee_location(
+          location, FieldDescriptorProto::kExtendeeFieldNumber);
+      extendee_location.StartAt(extendee_start);
+      extendee_location.EndAt(extendee_end);
+
+      if (is_first) {
+        extendee_location.RecordLegacyLocation(
+            field, DescriptorPool::ErrorCollector::EXTENDEE);
+        is_first = false;
+      }
     }
 
-    if (!ParseMessageField(field, messages)) {
+    field->set_extendee(extendee);
+
+    if (!ParseMessageField(field, messages, parent_location,
+                           location_field_number_for_nested_type,
+                           location)) {
       // This statement failed to parse.  Skip it, but keep looping to parse
       // other statements.
       SkipStatement();
@@ -832,15 +1091,24 @@
 // -------------------------------------------------------------------
 // Enums
 
-bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type) {
+bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type,
+                                 const LocationRecorder& enum_location) {
   DO(Consume("enum"));
-  RecordLocation(enum_type, DescriptorPool::ErrorCollector::NAME);
-  DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name."));
-  DO(ParseEnumBlock(enum_type));
+
+  {
+    LocationRecorder location(enum_location,
+                              EnumDescriptorProto::kNameFieldNumber);
+    location.RecordLegacyLocation(
+        enum_type, DescriptorPool::ErrorCollector::NAME);
+    DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name."));
+  }
+
+  DO(ParseEnumBlock(enum_type, enum_location));
   return true;
 }
 
-bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type) {
+bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type,
+                            const LocationRecorder& enum_location) {
   DO(Consume("{"));
 
   while (!TryConsume("}")) {
@@ -849,7 +1117,7 @@
       return false;
     }
 
-    if (!ParseEnumStatement(enum_type)) {
+    if (!ParseEnumStatement(enum_type, enum_location)) {
       // This statement failed to parse.  Skip it, but keep looping to parse
       // other statements.
       SkipStatement();
@@ -859,41 +1127,69 @@
   return true;
 }
 
-bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type) {
+bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type,
+                                const LocationRecorder& enum_location) {
   if (TryConsume(";")) {
     // empty statement; ignore
     return true;
   } else if (LookingAt("option")) {
-    return ParseOption(enum_type->mutable_options());
+    LocationRecorder location(enum_location,
+                              EnumDescriptorProto::kOptionsFieldNumber);
+    return ParseOption(enum_type->mutable_options(), location);
   } else {
-    return ParseEnumConstant(enum_type->add_value());
+    LocationRecorder location(enum_location,
+        EnumDescriptorProto::kValueFieldNumber, enum_type->value_size());
+    return ParseEnumConstant(enum_type->add_value(), location);
   }
 }
 
-bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value) {
-  RecordLocation(enum_value, DescriptorPool::ErrorCollector::NAME);
-  DO(ConsumeIdentifier(enum_value->mutable_name(),
-                       "Expected enum constant name."));
+bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value,
+                               const LocationRecorder& enum_value_location) {
+  // Parse name.
+  {
+    LocationRecorder location(enum_value_location,
+                              EnumValueDescriptorProto::kNameFieldNumber);
+    location.RecordLegacyLocation(
+        enum_value, DescriptorPool::ErrorCollector::NAME);
+    DO(ConsumeIdentifier(enum_value->mutable_name(),
+                         "Expected enum constant name."));
+  }
+
   DO(Consume("=", "Missing numeric value for enum constant."));
 
-  bool is_negative = TryConsume("-");
-  int number;
-  DO(ConsumeInteger(&number, "Expected integer."));
-  if (is_negative) number *= -1;
-  enum_value->set_number(number);
+  // Parse value.
+  {
+    LocationRecorder location(
+        enum_value_location, EnumValueDescriptorProto::kNumberFieldNumber);
+    location.RecordLegacyLocation(
+        enum_value, DescriptorPool::ErrorCollector::NUMBER);
 
-  DO(ParseEnumConstantOptions(enum_value));
+    bool is_negative = TryConsume("-");
+    int number;
+    DO(ConsumeInteger(&number, "Expected integer."));
+    if (is_negative) number *= -1;
+    enum_value->set_number(number);
+  }
+
+  DO(ParseEnumConstantOptions(enum_value, enum_value_location));
 
   DO(Consume(";"));
 
   return true;
 }
 
-bool Parser::ParseEnumConstantOptions(EnumValueDescriptorProto* value) {
-  if (!TryConsume("[")) return true;
+bool Parser::ParseEnumConstantOptions(
+    EnumValueDescriptorProto* value,
+    const LocationRecorder& enum_value_location) {
+  if (!LookingAt("[")) return true;
+
+  LocationRecorder location(
+      enum_value_location, EnumValueDescriptorProto::kOptionsFieldNumber);
+
+  DO(Consume("["));
 
   do {
-    DO(ParseOptionAssignment(value->mutable_options()));
+    DO(ParseOptionAssignment(value->mutable_options(), location));
   } while (TryConsume(","));
 
   DO(Consume("]"));
@@ -903,15 +1199,24 @@
 // -------------------------------------------------------------------
 // Services
 
-bool Parser::ParseServiceDefinition(ServiceDescriptorProto* service) {
+bool Parser::ParseServiceDefinition(ServiceDescriptorProto* service,
+                                    const LocationRecorder& service_location) {
   DO(Consume("service"));
-  RecordLocation(service, DescriptorPool::ErrorCollector::NAME);
-  DO(ConsumeIdentifier(service->mutable_name(), "Expected service name."));
-  DO(ParseServiceBlock(service));
+
+  {
+    LocationRecorder location(service_location,
+                              ServiceDescriptorProto::kNameFieldNumber);
+    location.RecordLegacyLocation(
+        service, DescriptorPool::ErrorCollector::NAME);
+    DO(ConsumeIdentifier(service->mutable_name(), "Expected service name."));
+  }
+
+  DO(ParseServiceBlock(service, service_location));
   return true;
 }
 
-bool Parser::ParseServiceBlock(ServiceDescriptorProto* service) {
+bool Parser::ParseServiceBlock(ServiceDescriptorProto* service,
+                               const LocationRecorder& service_location) {
   DO(Consume("{"));
 
   while (!TryConsume("}")) {
@@ -920,7 +1225,7 @@
       return false;
     }
 
-    if (!ParseServiceStatement(service)) {
+    if (!ParseServiceStatement(service, service_location)) {
       // This statement failed to parse.  Skip it, but keep looping to parse
       // other statements.
       SkipStatement();
@@ -930,33 +1235,55 @@
   return true;
 }
 
-bool Parser::ParseServiceStatement(ServiceDescriptorProto* service) {
+bool Parser::ParseServiceStatement(ServiceDescriptorProto* service,
+                                   const LocationRecorder& service_location) {
   if (TryConsume(";")) {
     // empty statement; ignore
     return true;
   } else if (LookingAt("option")) {
-    return ParseOption(service->mutable_options());
+    LocationRecorder location(
+        service_location, ServiceDescriptorProto::kOptionsFieldNumber);
+    return ParseOption(service->mutable_options(), location);
   } else {
-    return ParseServiceMethod(service->add_method());
+    LocationRecorder location(service_location,
+        ServiceDescriptorProto::kMethodFieldNumber, service->method_size());
+    return ParseServiceMethod(service->add_method(), location);
   }
 }
 
-bool Parser::ParseServiceMethod(MethodDescriptorProto* method) {
+bool Parser::ParseServiceMethod(MethodDescriptorProto* method,
+                                const LocationRecorder& method_location) {
   DO(Consume("rpc"));
-  RecordLocation(method, DescriptorPool::ErrorCollector::NAME);
-  DO(ConsumeIdentifier(method->mutable_name(), "Expected method name."));
+
+  {
+    LocationRecorder location(method_location,
+                              MethodDescriptorProto::kNameFieldNumber);
+    location.RecordLegacyLocation(
+        method, DescriptorPool::ErrorCollector::NAME);
+    DO(ConsumeIdentifier(method->mutable_name(), "Expected method name."));
+  }
 
   // Parse input type.
   DO(Consume("("));
-  RecordLocation(method, DescriptorPool::ErrorCollector::INPUT_TYPE);
-  DO(ParseUserDefinedType(method->mutable_input_type()));
+  {
+    LocationRecorder location(method_location,
+                              MethodDescriptorProto::kInputTypeFieldNumber);
+    location.RecordLegacyLocation(
+        method, DescriptorPool::ErrorCollector::INPUT_TYPE);
+    DO(ParseUserDefinedType(method->mutable_input_type()));
+  }
   DO(Consume(")"));
 
   // Parse output type.
   DO(Consume("returns"));
   DO(Consume("("));
-  RecordLocation(method, DescriptorPool::ErrorCollector::OUTPUT_TYPE);
-  DO(ParseUserDefinedType(method->mutable_output_type()));
+  {
+    LocationRecorder location(method_location,
+                              MethodDescriptorProto::kOutputTypeFieldNumber);
+    location.RecordLegacyLocation(
+        method, DescriptorPool::ErrorCollector::OUTPUT_TYPE);
+    DO(ParseUserDefinedType(method->mutable_output_type()));
+  }
   DO(Consume(")"));
 
   if (TryConsume("{")) {
@@ -970,7 +1297,9 @@
       if (TryConsume(";")) {
         // empty statement; ignore
       } else {
-        if (!ParseOption(method->mutable_options())) {
+        LocationRecorder location(method_location,
+                                  MethodDescriptorProto::kOptionsFieldNumber);
+        if (!ParseOption(method->mutable_options(), location)) {
           // This statement failed to parse.  Skip it, but keep looping to
           // parse other statements.
           SkipStatement();
@@ -1054,7 +1383,8 @@
 
 // ===================================================================
 
-bool Parser::ParsePackage(FileDescriptorProto* file) {
+bool Parser::ParsePackage(FileDescriptorProto* file,
+                          const LocationRecorder& root_location) {
   if (file->has_package()) {
     AddError("Multiple package definitions.");
     // Don't append the new package to the old one.  Just replace it.  Not
@@ -1064,31 +1394,43 @@
 
   DO(Consume("package"));
 
-  RecordLocation(file, DescriptorPool::ErrorCollector::NAME);
+  {
+    LocationRecorder location(root_location,
+                              FileDescriptorProto::kPackageFieldNumber);
+    location.RecordLegacyLocation(file, DescriptorPool::ErrorCollector::NAME);
 
-  while (true) {
-    string identifier;
-    DO(ConsumeIdentifier(&identifier, "Expected identifier."));
-    file->mutable_package()->append(identifier);
-    if (!TryConsume(".")) break;
-    file->mutable_package()->append(".");
+    while (true) {
+      string identifier;
+      DO(ConsumeIdentifier(&identifier, "Expected identifier."));
+      file->mutable_package()->append(identifier);
+      if (!TryConsume(".")) break;
+      file->mutable_package()->append(".");
+    }
   }
 
   DO(Consume(";"));
   return true;
 }
 
-bool Parser::ParseImport(string* import_filename) {
+bool Parser::ParseImport(string* import_filename,
+                         const LocationRecorder& root_location,
+                         int index) {
   DO(Consume("import"));
-  DO(ConsumeString(import_filename,
-    "Expected a string naming the file to import."));
+  {
+    LocationRecorder location(root_location,
+                              FileDescriptorProto::kDependencyFieldNumber,
+                              index);
+    DO(ConsumeString(import_filename,
+      "Expected a string naming the file to import."));
+  }
   DO(Consume(";"));
   return true;
 }
 
-bool Parser::ParseOption(Message* options) {
+bool Parser::ParseOption(Message* options,
+                         const LocationRecorder& options_location) {
   DO(Consume("option"));
-  DO(ParseOptionAssignment(options));
+  DO(ParseOptionAssignment(options, options_location));
   DO(Consume(";"));
   return true;
 }
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index 72c96d0..4cc90a2 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -74,6 +74,9 @@
 
   // Optional fetaures:
 
+  // DEPRECATED:  New code should use the SourceCodeInfo embedded in the
+  //   FileDescriptorProto.
+  //
   // Requests that locations of certain definitions be recorded to the given
   // SourceLocationTable while parsing.  This can be used to look up exact line
   // and column numbers for errors reported by DescriptorPool during validation.
@@ -82,7 +85,7 @@
     source_location_table_ = location_table;
   }
 
-  // Requsets that errors be recorded to the given ErrorCollector while
+  // Requests that errors be recorded to the given ErrorCollector while
   // parsing.  Set to NULL (the default) to discard error messages.
   void RecordErrorsTo(io::ErrorCollector* error_collector) {
     error_collector_ = error_collector;
@@ -180,16 +183,56 @@
   // of the current token.
   void AddError(const string& error);
 
-  // Record the given line and column and associate it with this descriptor
-  // in the SourceLocationTable.
-  void RecordLocation(const Message* descriptor,
-                      DescriptorPool::ErrorCollector::ErrorLocation location,
-                      int line, int column);
+  // Records a location in the SourceCodeInfo.location table (see
+  // descriptor.proto).  We use RAII to ensure that the start and end locations
+  // are recorded -- the constructor records the start location and the
+  // destructor records the end location.  Since the parser is
+  // recursive-descent, this works out beautifully.
+  class LIBPROTOBUF_EXPORT LocationRecorder {
+   public:
+    // Construct the file's "root" location.
+    LocationRecorder(Parser* parser);
 
-  // Record the current line and column and associate it with this descriptor
-  // in the SourceLocationTable.
-  void RecordLocation(const Message* descriptor,
-                      DescriptorPool::ErrorCollector::ErrorLocation location);
+    // Construct a location that represents a declaration nested within the
+    // given parent.  E.g. a field's location is nested within the location
+    // for a message type.  The parent's path will be copied, so you should
+    // call AddPath() only to add the path components leading from the parent
+    // to the child (as opposed to leading from the root to the child).
+    LocationRecorder(const LocationRecorder& parent);
+
+    // Convenience constructors that call AddPath() one or two times.
+    LocationRecorder(const LocationRecorder& parent, int path1);
+    LocationRecorder(const LocationRecorder& parent, int path1, int path2);
+
+    ~LocationRecorder();
+
+    // Add a path component.  See SourceCodeInfo.Location.path in
+    // descriptor.proto.
+    void AddPath(int path_component);
+
+    // By default the location is considered to start at the current token at
+    // the time the LocationRecorder is created.  StartAt() sets the start
+    // location to the given token instead.
+    void StartAt(const io::Tokenizer::Token& token);
+
+    // By default the location is considered to end at the previous token at
+    // the time the LocationRecorder is destroyed.  EndAt() sets the end
+    // location to the given token instead.
+    void EndAt(const io::Tokenizer::Token& token);
+
+    // Records the start point of this location to the SourceLocationTable that
+    // was passed to RecordSourceLocationsTo(), if any.  SourceLocationTable
+    // is an older way of keeping track of source locations which is still
+    // used in some places.
+    void RecordLegacyLocation(const Message* descriptor,
+        DescriptorPool::ErrorCollector::ErrorLocation location);
+
+   private:
+    Parser* parser_;
+    SourceCodeInfo::Location* location_;
+
+    void Init(const LocationRecorder& parent);
+  };
 
   // =================================================================
   // Parsers for various language constructs
@@ -210,50 +253,81 @@
   // makes logic much simpler for the caller.
 
   // Parse a top-level message, enum, service, etc.
-  bool ParseTopLevelStatement(FileDescriptorProto* file);
+  bool ParseTopLevelStatement(FileDescriptorProto* file,
+                              const LocationRecorder& root_location);
 
   // Parse various language high-level language construrcts.
-  bool ParseMessageDefinition(DescriptorProto* message);
-  bool ParseEnumDefinition(EnumDescriptorProto* enum_type);
-  bool ParseServiceDefinition(ServiceDescriptorProto* service);
-  bool ParsePackage(FileDescriptorProto* file);
-  bool ParseImport(string* import_filename);
-  bool ParseOption(Message* options);
+  bool ParseMessageDefinition(DescriptorProto* message,
+                              const LocationRecorder& message_location);
+  bool ParseEnumDefinition(EnumDescriptorProto* enum_type,
+                           const LocationRecorder& enum_location);
+  bool ParseServiceDefinition(ServiceDescriptorProto* service,
+                              const LocationRecorder& service_location);
+  bool ParsePackage(FileDescriptorProto* file,
+                    const LocationRecorder& root_location);
+  bool ParseImport(string* import_filename,
+                   const LocationRecorder& root_location,
+                   int index);
+  bool ParseOption(Message* options,
+                   const LocationRecorder& options_location);
 
   // These methods parse the contents of a message, enum, or service type and
   // add them to the given object.  They consume the entire block including
   // the beginning and ending brace.
-  bool ParseMessageBlock(DescriptorProto* message);
-  bool ParseEnumBlock(EnumDescriptorProto* enum_type);
-  bool ParseServiceBlock(ServiceDescriptorProto* service);
+  bool ParseMessageBlock(DescriptorProto* message,
+                         const LocationRecorder& message_location);
+  bool ParseEnumBlock(EnumDescriptorProto* enum_type,
+                      const LocationRecorder& enum_location);
+  bool ParseServiceBlock(ServiceDescriptorProto* service,
+                         const LocationRecorder& service_location);
 
   // Parse one statement within a message, enum, or service block, inclunding
   // final semicolon.
-  bool ParseMessageStatement(DescriptorProto* message);
-  bool ParseEnumStatement(EnumDescriptorProto* message);
-  bool ParseServiceStatement(ServiceDescriptorProto* message);
+  bool ParseMessageStatement(DescriptorProto* message,
+                             const LocationRecorder& message_location);
+  bool ParseEnumStatement(EnumDescriptorProto* message,
+                          const LocationRecorder& enum_location);
+  bool ParseServiceStatement(ServiceDescriptorProto* message,
+                             const LocationRecorder& service_location);
 
   // Parse a field of a message.  If the field is a group, its type will be
   // added to "messages".
+  //
+  // parent_location and location_field_number_for_nested_type are needed when
+  // parsing groups -- we need to generate a nested message type within the
+  // parent and record its location accordingly.  Since the parent could be
+  // either a FileDescriptorProto or a DescriptorProto, we must pass in the
+  // correct field number to use.
   bool ParseMessageField(FieldDescriptorProto* field,
-                         RepeatedPtrField<DescriptorProto>* messages);
+                         RepeatedPtrField<DescriptorProto>* messages,
+                         const LocationRecorder& parent_location,
+                         int location_field_number_for_nested_type,
+                         const LocationRecorder& field_location);
 
   // Parse an "extensions" declaration.
-  bool ParseExtensions(DescriptorProto* message);
+  bool ParseExtensions(DescriptorProto* message,
+                       const LocationRecorder& extensions_location);
 
-  // Parse an "extend" declaration.
+  // Parse an "extend" declaration.  (See also comments for
+  // ParseMessageField().)
   bool ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
-                   RepeatedPtrField<DescriptorProto>* messages);
+                   RepeatedPtrField<DescriptorProto>* messages,
+                   const LocationRecorder& parent_location,
+                   int location_field_number_for_nested_type,
+                   const LocationRecorder& extend_location);
 
   // Parse a single enum value within an enum block.
-  bool ParseEnumConstant(EnumValueDescriptorProto* enum_value);
+  bool ParseEnumConstant(EnumValueDescriptorProto* enum_value,
+                         const LocationRecorder& enum_value_location);
 
   // Parse enum constant options, i.e. the list in square brackets at the end
   // of the enum constant value definition.
-  bool ParseEnumConstantOptions(EnumValueDescriptorProto* value);
+  bool ParseEnumConstantOptions(EnumValueDescriptorProto* value,
+                                const LocationRecorder& enum_value_location);
 
   // Parse a single method within a service definition.
-  bool ParseServiceMethod(MethodDescriptorProto* method);
+  bool ParseServiceMethod(MethodDescriptorProto* method,
+                          const LocationRecorder& method_location);
 
   // Parse "required", "optional", or "repeated" and fill in "label"
   // with the value.
@@ -269,28 +343,45 @@
 
   // Parses field options, i.e. the stuff in square brackets at the end
   // of a field definition.  Also parses default value.
-  bool ParseFieldOptions(FieldDescriptorProto* field);
+  bool ParseFieldOptions(FieldDescriptorProto* field,
+                         const LocationRecorder& field_location);
 
   // Parse the "default" option.  This needs special handling because its
   // type is the field's type.
-  bool ParseDefaultAssignment(FieldDescriptorProto* field);
+  bool ParseDefaultAssignment(FieldDescriptorProto* field,
+                              const LocationRecorder& field_location);
 
   // Parse a single option name/value pair, e.g. "ctype = CORD".  The name
   // identifies a field of the given Message, and the value of that field
   // is set to the parsed value.
-  bool ParseOptionAssignment(Message* options);
+  bool ParseOptionAssignment(Message* options,
+                             const LocationRecorder& options_location);
 
   // Parses a single part of a multipart option name. A multipart name consists
   // of names separated by dots. Each name is either an identifier or a series
   // of identifiers separated by dots and enclosed in parentheses. E.g.,
   // "foo.(bar.baz).qux".
-  bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option);
+  bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
+                           const LocationRecorder& part_location);
+
+  // Parses a string surrounded by balanced braces.  Strips off the outer
+  // braces and stores the enclosed string in *value.
+  // E.g.,
+  //     { foo }                     *value gets 'foo'
+  //     { foo { bar: box } }        *value gets 'foo { bar: box }'
+  //     {}                          *value gets ''
+  //
+  // REQUIRES: LookingAt("{")
+  // When finished successfully, we are looking at the first token past
+  // the ending brace.
+  bool ParseUninterpretedBlock(string* value);
 
   // =================================================================
 
   io::Tokenizer* input_;
   io::ErrorCollector* error_collector_;
-  SourceLocationTable* source_location_table_;
+  SourceCodeInfo* source_code_info_;
+  SourceLocationTable* source_location_table_;  // legacy
   bool had_errors_;
   bool require_syntax_identifier_;
   bool stop_after_syntax_identifier_;
@@ -302,6 +393,11 @@
 // A table mapping (descriptor, ErrorLocation) pairs -- as reported by
 // DescriptorPool when validating descriptors -- to line and column numbers
 // within the original source code.
+//
+// This is semi-obsolete:  FileDescriptorProto.source_code_info now contains
+// far more complete information about source locations.  However, as of this
+// writing you still need to use SourceLocationTable when integrating with
+// DescriptorPool.
 class LIBPROTOBUF_EXPORT SourceLocationTable {
  public:
   SourceLocationTable();
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index e2262b8..156c0dc 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -34,6 +34,7 @@
 
 #include <vector>
 #include <algorithm>
+#include <map>
 
 #include <google/protobuf/compiler/parser.h>
 
@@ -45,6 +46,7 @@
 #include <google/protobuf/unittest.pb.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/map-util.h>
 
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
@@ -118,6 +120,9 @@
     EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
     ASSERT_EQ("", error_collector_.text_);
 
+    // We don't cover SourceCodeInfo in these tests.
+    actual.clear_source_code_info();
+
     // Parse the ASCII representation in order to canonicalize it.  We could
     // just compare directly to actual.DebugString(), but that would require
     // that the caller precisely match the formatting that DebugString()
@@ -930,6 +935,12 @@
     "3:25: Expected \";\".\n");
 }
 
+TEST_F(ParseErrorTest, EofInAggregateValue) {
+  ExpectHasErrors(
+      "option (fileopt) = { i:100\n",
+      "1:0: Unexpected end of stream while parsing aggregate value.\n");
+}
+
 // -------------------------------------------------------------------
 // Enum errors
 
@@ -1248,6 +1259,861 @@
 }
 
 // ===================================================================
+// SourceCodeInfo tests.
+
+// Follows a path -- as defined by SourceCodeInfo.Location.path -- from a
+// message to a particular sub-field.
+// * If the target is itself a message, sets *output_message to point at it,
+//   *output_field to NULL, and *output_index to -1.
+// * Otherwise, if the target is an element of a repeated field, sets
+//   *output_message to the containing message, *output_field to the descriptor
+//   of the field, and *output_index to the index of the element.
+// * Otherwise, the target is a field (possibly a repeated field, but not any
+//   one element).  Sets *output_message to the containing message,
+//   *output_field to the descriptor of the field, and *output_index to -1.
+// Returns true if the path was valid, false otherwise.  A gTest failure is
+// recorded before returning false.
+bool FollowPath(const Message& root,
+                const int* path_begin, const int* path_end,
+                const Message** output_message,
+                const FieldDescriptor** output_field,
+                int* output_index) {
+  if (path_begin == path_end) {
+    // Path refers to this whole message.
+    *output_message = &root;
+    *output_field = NULL;
+    *output_index = -1;
+    return true;
+  }
+
+  const Descriptor* descriptor = root.GetDescriptor();
+  const Reflection* reflection = root.GetReflection();
+
+  const FieldDescriptor* field = descriptor->FindFieldByNumber(*path_begin);
+
+  if (field == NULL) {
+    ADD_FAILURE() << descriptor->name() << " has no field number: "
+                  << *path_begin;
+    return false;
+  }
+
+  ++path_begin;
+
+  if (field->is_repeated()) {
+    if (path_begin == path_end) {
+      // Path refers to the whole repeated field.
+      *output_message = &root;
+      *output_field = field;
+      *output_index = -1;
+      return true;
+    }
+
+    int index = *path_begin++;
+    int size = reflection->FieldSize(root, field);
+
+    if (index >= size) {
+      ADD_FAILURE() << descriptor->name() << "." << field->name()
+                    << " has size " << size << ", but path contained index: "
+                    << index;
+      return false;
+    }
+
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      // Descend into child message.
+      const Message& child = reflection->GetRepeatedMessage(root, field, index);
+      return FollowPath(child, path_begin, path_end,
+                        output_message, output_field, output_index);
+    } else if (path_begin == path_end) {
+      // Path refers to this element.
+      *output_message = &root;
+      *output_field = field;
+      *output_index = index;
+      return true;
+    } else {
+      ADD_FAILURE() << descriptor->name() << "." << field->name()
+                    << " is not a message; cannot descend into it.";
+      return false;
+    }
+  } else {
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      const Message& child = reflection->GetMessage(root, field);
+      return FollowPath(child, path_begin, path_end,
+                        output_message, output_field, output_index);
+    } else if (path_begin == path_end) {
+      // Path refers to this field.
+      *output_message = &root;
+      *output_field = field;
+      *output_index = -1;
+      return true;
+    } else {
+      ADD_FAILURE() << descriptor->name() << "." << field->name()
+                    << " is not a message; cannot descend into it.";
+      return false;
+    }
+  }
+}
+
+// Split some text on line breaks.  The line breaks are retained in the output,
+// so each line (except the last) ends with a '\n', and the lines can be
+// concatenated to produce the original text.
+//
+// I couldn't find the proper string utility function for this.  Our
+// split-on-delimiter functions don't include the delimiter in the output.
+void SplitLines(const string& text, vector<string>* lines) {
+  string::size_type pos = 0;
+
+  while (pos != string::npos) {
+    string::size_type last_pos = pos;
+    pos = text.find_first_of('\n', pos);
+    if (pos != string::npos) ++pos;
+    lines->push_back(text.substr(last_pos, pos - last_pos));
+  }
+}
+
+// Look for the given tags in the given text and construct a span (as defined
+// by SourceCodeInfo.Location.span) from them.  E.g. for text like:
+//   /*a*/message /*b*/Foo/*c*/ {}/*d*/
+// There are four tags:  "a", "b", "c", and "d".  The constructed span starts
+// immediately after the start tag's trailing '/' and ends immediately before
+// the end tags leading '/'.
+void MakeExpectedSpan(const vector<string>& lines,
+                      const string& start_tag, const string& end_tag,
+                      RepeatedField<int>* output) {
+  string start_comment = "/*" + start_tag + "*/";
+  string end_comment = "/*" + end_tag + "*/";
+
+  int start_line = -1;
+  int start_column = -1;
+  for (int i = 0; i < lines.size(); i++) {
+    string::size_type pos = lines[i].find(start_comment);
+    if (pos != string::npos) {
+      start_line = i;
+      start_column = pos + start_comment.size();
+      break;
+    }
+  }
+  ASSERT_NE(start_line, -1)
+      << "Tag \"" << start_comment << "\" not found in text.";
+
+  int end_line = -1;
+  int end_column = -1;
+  for (int i = start_line; i < lines.size(); i++) {
+    string::size_type pos = lines[i].find(end_comment);
+    if (pos != string::npos) {
+      end_line = i;
+      end_column = pos;
+      break;
+    }
+  }
+  ASSERT_NE(end_line, -1)
+      << "Tag \"" << end_comment << "\" not found in text.";
+
+  output->Add(start_line);
+  output->Add(start_column);
+  if (end_line != start_line) output->Add(end_line);
+  output->Add(end_column);
+}
+
+// Check if two spans are equal.
+bool CompareSpans(const RepeatedField<int>& span1,
+                  const RepeatedField<int>& span2) {
+  if (span1.size() != span2.size()) return false;
+  for (int i = 0; i < span1.size(); i++) {
+    if (span1.Get(i) != span2.Get(i)) return false;
+  }
+  return true;
+}
+
+// Test fixture for source info tests, which check that source locations are
+// recorded correctly in FileDescriptorProto.source_code_info.location.
+class SourceInfoTest : public ParserTest {
+ protected:
+  // The parsed file (initialized by Parse()).
+  FileDescriptorProto file_;
+
+  // Parse the given text as a .proto file and populate the spans_ map with
+  // all the source location spans in its SourceCodeInfo table.
+  bool Parse(const char* text) {
+    SetupParser(text);
+    SplitLines(text, &lines_);
+    if (!parser_->Parse(input_.get(), &file_)) {
+      return false;
+    }
+
+    const SourceCodeInfo& source_info = file_.source_code_info();
+    for (int i = 0; i < source_info.location_size(); i++) {
+      const SourceCodeInfo::Location& location = source_info.location(i);
+      const Message* descriptor_proto = NULL;
+      const FieldDescriptor* field = NULL;
+      int index = 0;
+      if (!FollowPath(file_, location.path().begin(), location.path().end(),
+                      &descriptor_proto, &field, &index)) {
+        return false;
+      }
+
+      spans_.insert(make_pair(SpanKey(*descriptor_proto, field, index),
+                              &location));
+    }
+
+    return true;
+  }
+
+  virtual void TearDown() {
+    EXPECT_TRUE(spans_.empty())
+        << "Forgot to call HasSpan() for:\n"
+        << spans_.begin()->second->DebugString();
+  }
+
+  // -----------------------------------------------------------------
+  // HasSpan() checks that the span of source code delimited by the given
+  // tags (comments) correspond via the SourceCodeInfo table to the given
+  // part of the FileDescriptorProto.  (If unclear, look at the actual tests;
+  // it should quickly become obvious.)
+
+  bool HasSpan(const char* start_tag, const char* end_tag,
+               const Message& descriptor_proto) {
+    return HasSpan(start_tag, end_tag, descriptor_proto, NULL, -1);
+  }
+
+  bool HasSpan(const char* start_tag, const char* end_tag,
+               const Message& descriptor_proto, const string& field_name) {
+    return HasSpan(start_tag, end_tag, descriptor_proto, field_name, -1);
+  }
+
+  bool HasSpan(const char* start_tag, const char* end_tag,
+               const Message& descriptor_proto, const string& field_name,
+               int index) {
+    const FieldDescriptor* field =
+        descriptor_proto.GetDescriptor()->FindFieldByName(field_name);
+    if (field == NULL) {
+      ADD_FAILURE() << descriptor_proto.GetDescriptor()->name()
+                    << " has no such field: " << field_name;
+      return false;
+    }
+
+    return HasSpan(start_tag, end_tag, descriptor_proto, field, index);
+  }
+
+  bool HasSpan(const Message& descriptor_proto) {
+    return HasSpan(NULL, NULL, descriptor_proto, NULL, -1);
+  }
+
+  bool HasSpan(const Message& descriptor_proto, const string& field_name) {
+    return HasSpan(NULL, NULL, descriptor_proto, field_name, -1);
+  }
+
+  bool HasSpan(const Message& descriptor_proto, const string& field_name,
+               int index) {
+    return HasSpan(NULL, NULL, descriptor_proto, field_name, index);
+  }
+
+  bool HasSpan(const char* start_tag, const char* end_tag,
+               const Message& descriptor_proto, const FieldDescriptor* field,
+               int index) {
+    pair<SpanMap::iterator, SpanMap::iterator> range =
+        spans_.equal_range(SpanKey(descriptor_proto, field, index));
+
+    if (start_tag == NULL) {
+      if (range.first == range.second) {
+        return false;
+      } else {
+        spans_.erase(range.first);
+        return true;
+      }
+    } else {
+      RepeatedField<int> expected_span;
+      MakeExpectedSpan(lines_, start_tag, end_tag, &expected_span);
+
+      for (SpanMap::iterator iter = range.first; iter != range.second; ++iter) {
+        if (CompareSpans(expected_span, iter->second->span())) {
+          spans_.erase(iter);
+          return true;
+        }
+      }
+
+      return false;
+    }
+  }
+
+ private:
+  struct SpanKey {
+    const Message* descriptor_proto;
+    const FieldDescriptor* field;
+    int index;
+
+    inline SpanKey() {}
+    inline SpanKey(const Message& descriptor_proto,
+                   const FieldDescriptor* field,
+                   int index)
+        : descriptor_proto(&descriptor_proto), field(field), index(index) {}
+
+    inline bool operator<(const SpanKey& other) const {
+      if (descriptor_proto < other.descriptor_proto) return true;
+      if (descriptor_proto > other.descriptor_proto) return false;
+      if (field < other.field) return true;
+      if (field > other.field) return false;
+      return index < other.index;
+    }
+  };
+
+  typedef multimap<SpanKey, const SourceCodeInfo::Location*> SpanMap;
+  SpanMap spans_;
+  vector<string> lines_;
+};
+
+TEST_F(SourceInfoTest, BasicFileDecls) {
+  EXPECT_TRUE(Parse(
+      "/*a*/syntax = \"proto2\";\n"
+      "package /*b*/foo.bar/*c*/;\n"
+      "import /*d*/\"baz.proto\"/*e*/;\n"
+      "import /*f*/\"qux.proto\"/*g*/;/*h*/\n"
+      "// comment ignored\n"));
+
+  EXPECT_TRUE(HasSpan("a", "h", file_));
+  EXPECT_TRUE(HasSpan("b", "c", file_, "package"));
+  EXPECT_TRUE(HasSpan("d", "e", file_, "dependency", 0));
+  EXPECT_TRUE(HasSpan("f", "g", file_, "dependency", 1));
+}
+
+TEST_F(SourceInfoTest, Messages) {
+  EXPECT_TRUE(Parse(
+      "/*a*/message /*b*/Foo/*c*/ {}/*d*/\n"
+      "/*e*/message /*f*/Bar/*g*/ {}/*h*/\n"));
+
+  EXPECT_TRUE(HasSpan("a", "d", file_.message_type(0)));
+  EXPECT_TRUE(HasSpan("b", "c", file_.message_type(0), "name"));
+  EXPECT_TRUE(HasSpan("e", "h", file_.message_type(1)));
+  EXPECT_TRUE(HasSpan("f", "g", file_.message_type(1), "name"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+}
+
+TEST_F(SourceInfoTest, Fields) {
+  EXPECT_TRUE(Parse(
+      "message Foo {\n"
+      "  /*a*/optional/*b*/ /*c*/int32/*d*/ /*e*/bar/*f*/ = /*g*/1/*h*/;/*i*/\n"
+      "  /*j*/repeated/*k*/ /*l*/X.Y/*m*/ /*n*/baz/*o*/ = /*p*/2/*q*/;/*r*/\n"
+      "}\n"));
+
+  const FieldDescriptorProto& field1 = file_.message_type(0).field(0);
+  const FieldDescriptorProto& field2 = file_.message_type(0).field(1);
+
+  EXPECT_TRUE(HasSpan("a", "i", field1));
+  EXPECT_TRUE(HasSpan("a", "b", field1, "label"));
+  EXPECT_TRUE(HasSpan("c", "d", field1, "type"));
+  EXPECT_TRUE(HasSpan("e", "f", field1, "name"));
+  EXPECT_TRUE(HasSpan("g", "h", field1, "number"));
+
+  EXPECT_TRUE(HasSpan("j", "r", field2));
+  EXPECT_TRUE(HasSpan("j", "k", field2, "label"));
+  EXPECT_TRUE(HasSpan("l", "m", field2, "type_name"));
+  EXPECT_TRUE(HasSpan("n", "o", field2, "name"));
+  EXPECT_TRUE(HasSpan("p", "q", field2, "number"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, Extensions) {
+  EXPECT_TRUE(Parse(
+      "/*a*/extend /*b*/Foo/*c*/ {\n"
+      "  /*d*/optional/*e*/ int32 bar = 1;/*f*/\n"
+      "  /*g*/repeated/*h*/ X.Y baz = 2;/*i*/\n"
+      "}/*j*/\n"
+      "/*k*/extend /*l*/Bar/*m*/ {\n"
+      "  /*n*/optional int32 qux = 1;/*o*/\n"
+      "}/*p*/\n"));
+
+  const FieldDescriptorProto& field1 = file_.extension(0);
+  const FieldDescriptorProto& field2 = file_.extension(1);
+  const FieldDescriptorProto& field3 = file_.extension(2);
+
+  EXPECT_TRUE(HasSpan("a", "j", file_, "extension"));
+  EXPECT_TRUE(HasSpan("k", "p", file_, "extension"));
+
+  EXPECT_TRUE(HasSpan("d", "f", field1));
+  EXPECT_TRUE(HasSpan("d", "e", field1, "label"));
+  EXPECT_TRUE(HasSpan("b", "c", field1, "extendee"));
+
+  EXPECT_TRUE(HasSpan("g", "i", field2));
+  EXPECT_TRUE(HasSpan("g", "h", field2, "label"));
+  EXPECT_TRUE(HasSpan("b", "c", field2, "extendee"));
+
+  EXPECT_TRUE(HasSpan("n", "o", field3));
+  EXPECT_TRUE(HasSpan("l", "m", field3, "extendee"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(field1, "type"));
+  EXPECT_TRUE(HasSpan(field1, "name"));
+  EXPECT_TRUE(HasSpan(field1, "number"));
+  EXPECT_TRUE(HasSpan(field2, "type_name"));
+  EXPECT_TRUE(HasSpan(field2, "name"));
+  EXPECT_TRUE(HasSpan(field2, "number"));
+  EXPECT_TRUE(HasSpan(field3, "label"));
+  EXPECT_TRUE(HasSpan(field3, "type"));
+  EXPECT_TRUE(HasSpan(field3, "name"));
+  EXPECT_TRUE(HasSpan(field3, "number"));
+}
+
+TEST_F(SourceInfoTest, NestedExtensions) {
+  EXPECT_TRUE(Parse(
+      "message Message {\n"
+      "  /*a*/extend /*b*/Foo/*c*/ {\n"
+      "    /*d*/optional/*e*/ int32 bar = 1;/*f*/\n"
+      "    /*g*/repeated/*h*/ X.Y baz = 2;/*i*/\n"
+      "  }/*j*/\n"
+      "  /*k*/extend /*l*/Bar/*m*/ {\n"
+      "    /*n*/optional int32 qux = 1;/*o*/\n"
+      "  }/*p*/\n"
+      "}\n"));
+
+  const FieldDescriptorProto& field1 = file_.message_type(0).extension(0);
+  const FieldDescriptorProto& field2 = file_.message_type(0).extension(1);
+  const FieldDescriptorProto& field3 = file_.message_type(0).extension(2);
+
+  EXPECT_TRUE(HasSpan("a", "j", file_.message_type(0), "extension"));
+  EXPECT_TRUE(HasSpan("k", "p", file_.message_type(0), "extension"));
+
+  EXPECT_TRUE(HasSpan("d", "f", field1));
+  EXPECT_TRUE(HasSpan("d", "e", field1, "label"));
+  EXPECT_TRUE(HasSpan("b", "c", field1, "extendee"));
+
+  EXPECT_TRUE(HasSpan("g", "i", field2));
+  EXPECT_TRUE(HasSpan("g", "h", field2, "label"));
+  EXPECT_TRUE(HasSpan("b", "c", field2, "extendee"));
+
+  EXPECT_TRUE(HasSpan("n", "o", field3));
+  EXPECT_TRUE(HasSpan("l", "m", field3, "extendee"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+  EXPECT_TRUE(HasSpan(field1, "type"));
+  EXPECT_TRUE(HasSpan(field1, "name"));
+  EXPECT_TRUE(HasSpan(field1, "number"));
+  EXPECT_TRUE(HasSpan(field2, "type_name"));
+  EXPECT_TRUE(HasSpan(field2, "name"));
+  EXPECT_TRUE(HasSpan(field2, "number"));
+  EXPECT_TRUE(HasSpan(field3, "label"));
+  EXPECT_TRUE(HasSpan(field3, "type"));
+  EXPECT_TRUE(HasSpan(field3, "name"));
+  EXPECT_TRUE(HasSpan(field3, "number"));
+}
+
+TEST_F(SourceInfoTest, ExtensionRanges) {
+  EXPECT_TRUE(Parse(
+      "message Message {\n"
+      "  /*a*/extensions /*b*/1/*c*/ to /*d*/4/*e*/, /*f*/6/*g*/;/*h*/\n"
+      "  /*i*/extensions /*j*/8/*k*/ to /*l*/max/*m*/;/*n*/\n"
+      "}\n"));
+
+  const DescriptorProto::ExtensionRange& range1 =
+      file_.message_type(0).extension_range(0);
+  const DescriptorProto::ExtensionRange& range2 =
+      file_.message_type(0).extension_range(1);
+  const DescriptorProto::ExtensionRange& range3 =
+      file_.message_type(0).extension_range(2);
+
+  EXPECT_TRUE(HasSpan("a", "h", file_.message_type(0), "extension_range"));
+  EXPECT_TRUE(HasSpan("i", "n", file_.message_type(0), "extension_range"));
+
+  EXPECT_TRUE(HasSpan("b", "e", range1));
+  EXPECT_TRUE(HasSpan("b", "c", range1, "start"));
+  EXPECT_TRUE(HasSpan("d", "e", range1, "end"));
+
+  EXPECT_TRUE(HasSpan("f", "g", range2));
+  EXPECT_TRUE(HasSpan("f", "g", range2, "start"));
+  EXPECT_TRUE(HasSpan("f", "g", range2, "end"));
+
+  EXPECT_TRUE(HasSpan("j", "m", range3));
+  EXPECT_TRUE(HasSpan("j", "k", range3, "start"));
+  EXPECT_TRUE(HasSpan("l", "m", range3, "end"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, NestedMessages) {
+  EXPECT_TRUE(Parse(
+      "message Foo {\n"
+      "  /*a*/message /*b*/Bar/*c*/ {\n"
+      "    /*d*/message /*e*/Baz/*f*/ {}/*g*/\n"
+      "  }/*h*/\n"
+      "  /*i*/message /*j*/Qux/*k*/ {}/*l*/\n"
+      "}\n"));
+
+  const DescriptorProto& bar = file_.message_type(0).nested_type(0);
+  const DescriptorProto& baz = bar.nested_type(0);
+  const DescriptorProto& qux = file_.message_type(0).nested_type(1);
+
+  EXPECT_TRUE(HasSpan("a", "h", bar));
+  EXPECT_TRUE(HasSpan("b", "c", bar, "name"));
+  EXPECT_TRUE(HasSpan("d", "g", baz));
+  EXPECT_TRUE(HasSpan("e", "f", baz, "name"));
+  EXPECT_TRUE(HasSpan("i", "l", qux));
+  EXPECT_TRUE(HasSpan("j", "k", qux, "name"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, Groups) {
+  EXPECT_TRUE(Parse(
+      "message Foo {\n"
+      "  message Bar {}\n"
+      "  /*a*/optional/*b*/ /*c*/group/*d*/ /*e*/Baz/*f*/ = /*g*/1/*h*/ {\n"
+      "    /*i*/message Qux {}/*j*/\n"
+      "  }/*k*/\n"
+      "}\n"));
+
+  const DescriptorProto& bar = file_.message_type(0).nested_type(0);
+  const DescriptorProto& baz = file_.message_type(0).nested_type(1);
+  const DescriptorProto& qux = baz.nested_type(0);
+  const FieldDescriptorProto& field = file_.message_type(0).field(0);
+
+  EXPECT_TRUE(HasSpan("a", "k", field));
+  EXPECT_TRUE(HasSpan("a", "b", field, "label"));
+  EXPECT_TRUE(HasSpan("c", "d", field, "type"));
+  EXPECT_TRUE(HasSpan("e", "f", field, "name"));
+  EXPECT_TRUE(HasSpan("e", "f", field, "type_name"));
+  EXPECT_TRUE(HasSpan("g", "h", field, "number"));
+
+  EXPECT_TRUE(HasSpan("a", "k", baz));
+  EXPECT_TRUE(HasSpan("e", "f", baz, "name"));
+  EXPECT_TRUE(HasSpan("i", "j", qux));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+  EXPECT_TRUE(HasSpan(bar));
+  EXPECT_TRUE(HasSpan(bar, "name"));
+  EXPECT_TRUE(HasSpan(qux, "name"));
+}
+
+TEST_F(SourceInfoTest, Enums) {
+  EXPECT_TRUE(Parse(
+      "/*a*/enum /*b*/Foo/*c*/ {}/*d*/\n"
+      "/*e*/enum /*f*/Bar/*g*/ {}/*h*/\n"));
+
+  EXPECT_TRUE(HasSpan("a", "d", file_.enum_type(0)));
+  EXPECT_TRUE(HasSpan("b", "c", file_.enum_type(0), "name"));
+  EXPECT_TRUE(HasSpan("e", "h", file_.enum_type(1)));
+  EXPECT_TRUE(HasSpan("f", "g", file_.enum_type(1), "name"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+}
+
+TEST_F(SourceInfoTest, EnumValues) {
+  EXPECT_TRUE(Parse(
+      "enum Foo {\n"
+      "  /*a*/BAR/*b*/ = /*c*/1/*d*/;/*e*/\n"
+      "  /*f*/BAZ/*g*/ = /*h*/2/*i*/;/*j*/\n"
+      "}"));
+
+  const EnumValueDescriptorProto& bar = file_.enum_type(0).value(0);
+  const EnumValueDescriptorProto& baz = file_.enum_type(0).value(1);
+
+  EXPECT_TRUE(HasSpan("a", "e", bar));
+  EXPECT_TRUE(HasSpan("a", "b", bar, "name"));
+  EXPECT_TRUE(HasSpan("c", "d", bar, "number"));
+  EXPECT_TRUE(HasSpan("f", "j", baz));
+  EXPECT_TRUE(HasSpan("f", "g", baz, "name"));
+  EXPECT_TRUE(HasSpan("h", "i", baz, "number"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, NestedEnums) {
+  EXPECT_TRUE(Parse(
+      "message Foo {\n"
+      "  /*a*/enum /*b*/Bar/*c*/ {}/*d*/\n"
+      "  /*e*/enum /*f*/Baz/*g*/ {}/*h*/\n"
+      "}\n"));
+
+  const EnumDescriptorProto& bar = file_.message_type(0).enum_type(0);
+  const EnumDescriptorProto& baz = file_.message_type(0).enum_type(1);
+
+  EXPECT_TRUE(HasSpan("a", "d", bar));
+  EXPECT_TRUE(HasSpan("b", "c", bar, "name"));
+  EXPECT_TRUE(HasSpan("e", "h", baz));
+  EXPECT_TRUE(HasSpan("f", "g", baz, "name"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+}
+
+TEST_F(SourceInfoTest, Services) {
+  EXPECT_TRUE(Parse(
+      "/*a*/service /*b*/Foo/*c*/ {}/*d*/\n"
+      "/*e*/service /*f*/Bar/*g*/ {}/*h*/\n"));
+
+  EXPECT_TRUE(HasSpan("a", "d", file_.service(0)));
+  EXPECT_TRUE(HasSpan("b", "c", file_.service(0), "name"));
+  EXPECT_TRUE(HasSpan("e", "h", file_.service(1)));
+  EXPECT_TRUE(HasSpan("f", "g", file_.service(1), "name"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+}
+
+TEST_F(SourceInfoTest, Methods) {
+  EXPECT_TRUE(Parse(
+      "service Foo {\n"
+      "  /*a*/rpc /*b*/Bar/*c*/(/*d*/X/*e*/) returns(/*f*/Y/*g*/);/*h*/"
+      "  /*i*/rpc /*j*/Baz/*k*/(/*l*/Z/*m*/) returns(/*n*/W/*o*/);/*p*/"
+      "}"));
+
+  const MethodDescriptorProto& bar = file_.service(0).method(0);
+  const MethodDescriptorProto& baz = file_.service(0).method(1);
+
+  EXPECT_TRUE(HasSpan("a", "h", bar));
+  EXPECT_TRUE(HasSpan("b", "c", bar, "name"));
+  EXPECT_TRUE(HasSpan("d", "e", bar, "input_type"));
+  EXPECT_TRUE(HasSpan("f", "g", bar, "output_type"));
+
+  EXPECT_TRUE(HasSpan("i", "p", baz));
+  EXPECT_TRUE(HasSpan("j", "k", baz, "name"));
+  EXPECT_TRUE(HasSpan("l", "m", baz, "input_type"));
+  EXPECT_TRUE(HasSpan("n", "o", baz, "output_type"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.service(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0), "name"));
+}
+
+TEST_F(SourceInfoTest, Options) {
+  EXPECT_TRUE(Parse(
+      "/*a*/option /*b*/foo/*c*/./*d*/(/*e*/bar.baz/*f*/)/*g*/ = "
+          "/*h*/123/*i*/;/*j*/\n"
+      "/*k*/option qux = /*l*/-123/*m*/;/*n*/\n"
+      "/*o*/option corge = /*p*/abc/*q*/;/*r*/\n"
+      "/*s*/option grault = /*t*/'blah'/*u*/;/*v*/\n"
+      "/*w*/option garply = /*x*/{ yadda yadda }/*y*/;/*z*/\n"
+      "/*0*/option waldo = /*1*/123.0/*2*/;/*3*/\n"
+  ));
+
+  const UninterpretedOption& option1 = file_.options().uninterpreted_option(0);
+  const UninterpretedOption& option2 = file_.options().uninterpreted_option(1);
+  const UninterpretedOption& option3 = file_.options().uninterpreted_option(2);
+  const UninterpretedOption& option4 = file_.options().uninterpreted_option(3);
+  const UninterpretedOption& option5 = file_.options().uninterpreted_option(4);
+  const UninterpretedOption& option6 = file_.options().uninterpreted_option(5);
+
+  EXPECT_TRUE(HasSpan("a", "j", file_.options()));
+  EXPECT_TRUE(HasSpan("b", "i", option1));
+  EXPECT_TRUE(HasSpan("b", "g", option1, "name"));
+  EXPECT_TRUE(HasSpan("b", "c", option1.name(0)));
+  EXPECT_TRUE(HasSpan("b", "c", option1.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan("d", "g", option1.name(1)));
+  EXPECT_TRUE(HasSpan("e", "f", option1.name(1), "name_part"));
+  EXPECT_TRUE(HasSpan("h", "i", option1, "positive_int_value"));
+
+  EXPECT_TRUE(HasSpan("k", "n", file_.options()));
+  EXPECT_TRUE(HasSpan("l", "m", option2, "negative_int_value"));
+
+  EXPECT_TRUE(HasSpan("o", "r", file_.options()));
+  EXPECT_TRUE(HasSpan("p", "q", option3, "identifier_value"));
+
+  EXPECT_TRUE(HasSpan("s", "v", file_.options()));
+  EXPECT_TRUE(HasSpan("t", "u", option4, "string_value"));
+
+  EXPECT_TRUE(HasSpan("w", "z", file_.options()));
+  EXPECT_TRUE(HasSpan("x", "y", option5, "aggregate_value"));
+
+  EXPECT_TRUE(HasSpan("0", "3", file_.options()));
+  EXPECT_TRUE(HasSpan("1", "2", option6, "double_value"));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(option2));
+  EXPECT_TRUE(HasSpan(option3));
+  EXPECT_TRUE(HasSpan(option4));
+  EXPECT_TRUE(HasSpan(option5));
+  EXPECT_TRUE(HasSpan(option6));
+  EXPECT_TRUE(HasSpan(option2, "name"));
+  EXPECT_TRUE(HasSpan(option3, "name"));
+  EXPECT_TRUE(HasSpan(option4, "name"));
+  EXPECT_TRUE(HasSpan(option5, "name"));
+  EXPECT_TRUE(HasSpan(option6, "name"));
+  EXPECT_TRUE(HasSpan(option2.name(0)));
+  EXPECT_TRUE(HasSpan(option3.name(0)));
+  EXPECT_TRUE(HasSpan(option4.name(0)));
+  EXPECT_TRUE(HasSpan(option5.name(0)));
+  EXPECT_TRUE(HasSpan(option6.name(0)));
+  EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option3.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option4.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option5.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option6.name(0), "name_part"));
+}
+
+TEST_F(SourceInfoTest, ScopedOptions) {
+  EXPECT_TRUE(Parse(
+    "message Foo {\n"
+    "  /*a*/option mopt = 1;/*b*/\n"
+    "}\n"
+    "enum Bar {\n"
+    "  /*c*/option eopt = 1;/*d*/\n"
+    "}\n"
+    "service Baz {\n"
+    "  /*e*/option sopt = 1;/*f*/\n"
+    "  rpc M(X) returns(Y) {\n"
+    "    /*g*/option mopt = 1;/*h*/\n"
+    "  }\n"
+    "}\n"));
+
+  EXPECT_TRUE(HasSpan("a", "b", file_.message_type(0).options()));
+  EXPECT_TRUE(HasSpan("c", "d", file_.enum_type(0).options()));
+  EXPECT_TRUE(HasSpan("e", "f", file_.service(0).options()));
+  EXPECT_TRUE(HasSpan("g", "h", file_.service(0).method(0).options()));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
+                      .uninterpreted_option(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
+                      .uninterpreted_option(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
+                      .uninterpreted_option(0).name(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
+                      .uninterpreted_option(0).name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
+                      .uninterpreted_option(0), "positive_int_value"));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
+                      .uninterpreted_option(0)));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
+                      .uninterpreted_option(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
+                      .uninterpreted_option(0).name(0)));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
+                      .uninterpreted_option(0).name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
+                      .uninterpreted_option(0), "positive_int_value"));
+  EXPECT_TRUE(HasSpan(file_.service(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).options()
+                      .uninterpreted_option(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).options()
+                      .uninterpreted_option(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.service(0).options()
+                      .uninterpreted_option(0).name(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).options()
+                      .uninterpreted_option(0).name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(file_.service(0).options()
+                      .uninterpreted_option(0), "positive_int_value"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0), "input_type"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0), "output_type"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
+                      .uninterpreted_option(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
+                      .uninterpreted_option(0), "name"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
+                      .uninterpreted_option(0).name(0)));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
+                      .uninterpreted_option(0).name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
+                      .uninterpreted_option(0), "positive_int_value"));
+}
+
+TEST_F(SourceInfoTest, FieldOptions) {
+  // The actual "name = value" pairs are parsed by the same code as for
+  // top-level options so we won't re-test that -- just make sure that the
+  // syntax used for field options is understood.
+  EXPECT_TRUE(Parse(
+      "message Foo {"
+      "  optional int32 bar = 1 "
+          "/*a*/[default=/*b*/123/*c*/,/*d*/opt1=123/*e*/,"
+          "/*f*/opt2='hi'/*g*/]/*h*/;"
+      "}\n"
+  ));
+
+  const FieldDescriptorProto& field = file_.message_type(0).field(0);
+  const UninterpretedOption& option1 = field.options().uninterpreted_option(0);
+  const UninterpretedOption& option2 = field.options().uninterpreted_option(1);
+
+  EXPECT_TRUE(HasSpan("a", "h", field.options()));
+  EXPECT_TRUE(HasSpan("b", "c", field, "default_value"));
+  EXPECT_TRUE(HasSpan("d", "e", option1));
+  EXPECT_TRUE(HasSpan("f", "g", option2));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.message_type(0)));
+  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
+  EXPECT_TRUE(HasSpan(field));
+  EXPECT_TRUE(HasSpan(field, "label"));
+  EXPECT_TRUE(HasSpan(field, "type"));
+  EXPECT_TRUE(HasSpan(field, "name"));
+  EXPECT_TRUE(HasSpan(field, "number"));
+  EXPECT_TRUE(HasSpan(option1, "name"));
+  EXPECT_TRUE(HasSpan(option2, "name"));
+  EXPECT_TRUE(HasSpan(option1.name(0)));
+  EXPECT_TRUE(HasSpan(option2.name(0)));
+  EXPECT_TRUE(HasSpan(option1.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option1, "positive_int_value"));
+  EXPECT_TRUE(HasSpan(option2, "string_value"));
+}
+
+TEST_F(SourceInfoTest, EnumValueOptions) {
+  // The actual "name = value" pairs are parsed by the same code as for
+  // top-level options so we won't re-test that -- just make sure that the
+  // syntax used for enum options is understood.
+  EXPECT_TRUE(Parse(
+      "enum Foo {"
+      "  BAR = 1 /*a*/[/*b*/opt1=123/*c*/,/*d*/opt2='hi'/*e*/]/*f*/;"
+      "}\n"
+  ));
+
+  const EnumValueDescriptorProto& value = file_.enum_type(0).value(0);
+  const UninterpretedOption& option1 = value.options().uninterpreted_option(0);
+  const UninterpretedOption& option2 = value.options().uninterpreted_option(1);
+
+  EXPECT_TRUE(HasSpan("a", "f", value.options()));
+  EXPECT_TRUE(HasSpan("b", "c", option1));
+  EXPECT_TRUE(HasSpan("d", "e", option2));
+
+  // Ignore these.
+  EXPECT_TRUE(HasSpan(file_));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
+  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
+  EXPECT_TRUE(HasSpan(value));
+  EXPECT_TRUE(HasSpan(value, "name"));
+  EXPECT_TRUE(HasSpan(value, "number"));
+  EXPECT_TRUE(HasSpan(option1, "name"));
+  EXPECT_TRUE(HasSpan(option2, "name"));
+  EXPECT_TRUE(HasSpan(option1.name(0)));
+  EXPECT_TRUE(HasSpan(option2.name(0)));
+  EXPECT_TRUE(HasSpan(option1.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
+  EXPECT_TRUE(HasSpan(option1, "positive_int_value"));
+  EXPECT_TRUE(HasSpan(option2, "string_value"));
+}
+
+// ===================================================================
 
 }  // anonymous namespace
 
diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc
index a4aedaf..727f942 100644
--- a/src/google/protobuf/compiler/plugin.cc
+++ b/src/google/protobuf/compiler/plugin.cc
@@ -59,13 +59,15 @@
 namespace protobuf {
 namespace compiler {
 
-class GeneratorResponseOutputDirectory : public OutputDirectory {
+class GeneratorResponseContext : public GeneratorContext {
  public:
-  GeneratorResponseOutputDirectory(CodeGeneratorResponse* response)
-      : response_(response) {}
-  virtual ~GeneratorResponseOutputDirectory() {}
+  GeneratorResponseContext(CodeGeneratorResponse* response,
+                           const vector<const FileDescriptor*>& parsed_files)
+      : response_(response),
+        parsed_files_(parsed_files) {}
+  virtual ~GeneratorResponseContext() {}
 
-  // implements OutputDirectory --------------------------------------
+  // implements GeneratorContext --------------------------------------
 
   virtual io::ZeroCopyOutputStream* Open(const string& filename) {
     CodeGeneratorResponse::File* file = response_->add_file();
@@ -81,8 +83,13 @@
     return new io::StringOutputStream(file->mutable_content());
   }
 
+  void ListParsedFiles(vector<const FileDescriptor*>* output) {
+    *output = parsed_files_;
+  }
+
  private:
   CodeGeneratorResponse* response_;
+  const vector<const FileDescriptor*>& parsed_files_;
 };
 
 int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
@@ -112,22 +119,26 @@
     }
   }
 
-  CodeGeneratorResponse response;
-  GeneratorResponseOutputDirectory output_directory(&response);
-
+  vector<const FileDescriptor*> parsed_files;
   for (int i = 0; i < request.file_to_generate_size(); i++) {
-    const FileDescriptor* file =
-        pool.FindFileByName(request.file_to_generate(i));
-    if (file == NULL) {
+    parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i)));
+    if (parsed_files.back() == NULL) {
       cerr << argv[0] << ": protoc asked plugin to generate a file but "
               "did not provide a descriptor for the file: "
            << request.file_to_generate(i) << endl;
       return 1;
     }
+  }
+
+  CodeGeneratorResponse response;
+  GeneratorResponseContext context(&response, parsed_files);
+
+  for (int i = 0; i < parsed_files.size(); i++) {
+    const FileDescriptor* file = parsed_files[i];
 
     string error;
     bool succeeded = generator->Generate(
-        file, request.parameter(), &output_directory, &error);
+        file, request.parameter(), &context, &error);
 
     if (!succeeded && error.empty()) {
       error = "Code generator returned false but provided no error "
diff --git a/src/google/protobuf/compiler/plugin.h b/src/google/protobuf/compiler/plugin.h
index 7c40333..64dfb1d 100644
--- a/src/google/protobuf/compiler/plugin.h
+++ b/src/google/protobuf/compiler/plugin.h
@@ -64,7 +64,7 @@
 class CodeGenerator;    // code_generator.h
 
 // Implements main() for a protoc plugin exposing the given code generator.
-LIBPROTOC_EXPORT int PluginMain(int argc, char* argv[], const CodeGenerator* generator);
+int PluginMain(int argc, char* argv[], const CodeGenerator* generator);
 
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index 13d35c6..ad4b4de 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -158,7 +158,6 @@
 
 // ===================================================================
 
-const ::std::string CodeGeneratorRequest::_default_parameter_;
 #ifndef _MSC_VER
 const int CodeGeneratorRequest::kFileToGenerateFieldNumber;
 const int CodeGeneratorRequest::kParameterFieldNumber;
@@ -181,7 +180,7 @@
 
 void CodeGeneratorRequest::SharedCtor() {
   _cached_size_ = 0;
-  parameter_ = const_cast< ::std::string*>(&_default_parameter_);
+  parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -190,7 +189,7 @@
 }
 
 void CodeGeneratorRequest::SharedDtor() {
-  if (parameter_ != &_default_parameter_) {
+  if (parameter_ != &::google::protobuf::internal::kEmptyString) {
     delete parameter_;
   }
   if (this != default_instance_) {
@@ -219,8 +218,8 @@
 
 void CodeGeneratorRequest::Clear() {
   if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
-    if (_has_bit(1)) {
-      if (parameter_ != &_default_parameter_) {
+    if (has_parameter()) {
+      if (parameter_ != &::google::protobuf::internal::kEmptyString) {
         parameter_->clear();
       }
     }
@@ -315,7 +314,7 @@
   }
   
   // optional string parameter = 2;
-  if (_has_bit(1)) {
+  if (has_parameter()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->parameter().data(), this->parameter().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -347,7 +346,7 @@
   }
   
   // optional string parameter = 2;
-  if (_has_bit(1)) {
+  if (has_parameter()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->parameter().data(), this->parameter().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -425,7 +424,7 @@
   file_to_generate_.MergeFrom(from.file_to_generate_);
   proto_file_.MergeFrom(from.proto_file_);
   if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
-    if (from._has_bit(1)) {
+    if (from.has_parameter()) {
       set_parameter(from.parameter());
     }
   }
@@ -474,9 +473,6 @@
 
 // ===================================================================
 
-const ::std::string CodeGeneratorResponse_File::_default_name_;
-const ::std::string CodeGeneratorResponse_File::_default_insertion_point_;
-const ::std::string CodeGeneratorResponse_File::_default_content_;
 #ifndef _MSC_VER
 const int CodeGeneratorResponse_File::kNameFieldNumber;
 const int CodeGeneratorResponse_File::kInsertionPointFieldNumber;
@@ -499,9 +495,9 @@
 
 void CodeGeneratorResponse_File::SharedCtor() {
   _cached_size_ = 0;
-  name_ = const_cast< ::std::string*>(&_default_name_);
-  insertion_point_ = const_cast< ::std::string*>(&_default_insertion_point_);
-  content_ = const_cast< ::std::string*>(&_default_content_);
+  name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  content_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -510,13 +506,13 @@
 }
 
 void CodeGeneratorResponse_File::SharedDtor() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     delete name_;
   }
-  if (insertion_point_ != &_default_insertion_point_) {
+  if (insertion_point_ != &::google::protobuf::internal::kEmptyString) {
     delete insertion_point_;
   }
-  if (content_ != &_default_content_) {
+  if (content_ != &::google::protobuf::internal::kEmptyString) {
     delete content_;
   }
   if (this != default_instance_) {
@@ -545,18 +541,18 @@
 
 void CodeGeneratorResponse_File::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (name_ != &_default_name_) {
+    if (has_name()) {
+      if (name_ != &::google::protobuf::internal::kEmptyString) {
         name_->clear();
       }
     }
-    if (_has_bit(1)) {
-      if (insertion_point_ != &_default_insertion_point_) {
+    if (has_insertion_point()) {
+      if (insertion_point_ != &::google::protobuf::internal::kEmptyString) {
         insertion_point_->clear();
       }
     }
-    if (_has_bit(2)) {
-      if (content_ != &_default_content_) {
+    if (has_content()) {
+      if (content_ != &::google::protobuf::internal::kEmptyString) {
         content_->clear();
       }
     }
@@ -640,7 +636,7 @@
 void CodeGeneratorResponse_File::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -649,7 +645,7 @@
   }
   
   // optional string insertion_point = 2;
-  if (_has_bit(1)) {
+  if (has_insertion_point()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->insertion_point().data(), this->insertion_point().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -658,7 +654,7 @@
   }
   
   // optional string content = 15;
-  if (_has_bit(2)) {
+  if (has_content()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->content().data(), this->content().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -675,7 +671,7 @@
 ::google::protobuf::uint8* CodeGeneratorResponse_File::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -685,7 +681,7 @@
   }
   
   // optional string insertion_point = 2;
-  if (_has_bit(1)) {
+  if (has_insertion_point()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->insertion_point().data(), this->insertion_point().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -695,7 +691,7 @@
   }
   
   // optional string content = 15;
-  if (_has_bit(2)) {
+  if (has_content()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->content().data(), this->content().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -763,13 +759,13 @@
 void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) {
   GOOGLE_CHECK_NE(&from, this);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_name()) {
       set_name(from.name());
     }
-    if (from._has_bit(1)) {
+    if (from.has_insertion_point()) {
       set_insertion_point(from.insertion_point());
     }
-    if (from._has_bit(2)) {
+    if (from.has_content()) {
       set_content(from.content());
     }
   }
@@ -815,7 +811,6 @@
 
 // -------------------------------------------------------------------
 
-const ::std::string CodeGeneratorResponse::_default_error_;
 #ifndef _MSC_VER
 const int CodeGeneratorResponse::kErrorFieldNumber;
 const int CodeGeneratorResponse::kFileFieldNumber;
@@ -837,7 +832,7 @@
 
 void CodeGeneratorResponse::SharedCtor() {
   _cached_size_ = 0;
-  error_ = const_cast< ::std::string*>(&_default_error_);
+  error_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -846,7 +841,7 @@
 }
 
 void CodeGeneratorResponse::SharedDtor() {
-  if (error_ != &_default_error_) {
+  if (error_ != &::google::protobuf::internal::kEmptyString) {
     delete error_;
   }
   if (this != default_instance_) {
@@ -875,8 +870,8 @@
 
 void CodeGeneratorResponse::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (error_ != &_default_error_) {
+    if (has_error()) {
+      if (error_ != &::google::protobuf::internal::kEmptyString) {
         error_->clear();
       }
     }
@@ -942,7 +937,7 @@
 void CodeGeneratorResponse::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string error = 1;
-  if (_has_bit(0)) {
+  if (has_error()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->error().data(), this->error().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -965,7 +960,7 @@
 ::google::protobuf::uint8* CodeGeneratorResponse::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string error = 1;
-  if (_has_bit(0)) {
+  if (has_error()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->error().data(), this->error().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -1035,7 +1030,7 @@
   GOOGLE_CHECK_NE(&from, this);
   file_.MergeFrom(from.file_);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_error()) {
       set_error(from.error());
     }
   }
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index bd6bf63..c307bfd 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -120,6 +120,7 @@
   inline void set_parameter(const char* value);
   inline void set_parameter(const char* value, size_t size);
   inline ::std::string* mutable_parameter();
+  inline ::std::string* release_parameter();
   
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
   inline int proto_file_size() const;
@@ -135,30 +136,22 @@
   
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
  private:
+  inline void set_has_parameter();
+  inline void clear_has_parameter();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_;
   ::std::string* parameter_;
-  static const ::std::string _default_parameter_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+  
   friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static CodeGeneratorRequest* default_instance_;
 };
@@ -227,6 +220,7 @@
   inline void set_name(const char* value);
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
+  inline ::std::string* release_name();
   
   // optional string insertion_point = 2;
   inline bool has_insertion_point() const;
@@ -237,6 +231,7 @@
   inline void set_insertion_point(const char* value);
   inline void set_insertion_point(const char* value, size_t size);
   inline ::std::string* mutable_insertion_point();
+  inline ::std::string* release_insertion_point();
   
   // optional string content = 15;
   inline bool has_content() const;
@@ -247,35 +242,30 @@
   inline void set_content(const char* value);
   inline void set_content(const char* value, size_t size);
   inline ::std::string* mutable_content();
+  inline ::std::string* release_content();
   
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
  private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_insertion_point();
+  inline void clear_has_insertion_point();
+  inline void set_has_content();
+  inline void clear_has_content();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* name_;
-  static const ::std::string _default_name_;
   ::std::string* insertion_point_;
-  static const ::std::string _default_insertion_point_;
   ::std::string* content_;
-  static const ::std::string _default_content_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+  
   friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static CodeGeneratorResponse_File* default_instance_;
 };
@@ -346,6 +336,7 @@
   inline void set_error(const char* value);
   inline void set_error(const char* value, size_t size);
   inline ::std::string* mutable_error();
+  inline ::std::string* release_error();
   
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
   inline int file_size() const;
@@ -361,29 +352,21 @@
   
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
  private:
+  inline void set_has_error();
+  inline void clear_has_error();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* error_;
-  static const ::std::string _default_error_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
+  
   friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static CodeGeneratorResponse* default_instance_;
 };
@@ -440,45 +423,61 @@
 
 // optional string parameter = 2;
 inline bool CodeGeneratorRequest::has_parameter() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void CodeGeneratorRequest::set_has_parameter() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void CodeGeneratorRequest::clear_has_parameter() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void CodeGeneratorRequest::clear_parameter() {
-  if (parameter_ != &_default_parameter_) {
+  if (parameter_ != &::google::protobuf::internal::kEmptyString) {
     parameter_->clear();
   }
-  _clear_bit(1);
+  clear_has_parameter();
 }
 inline const ::std::string& CodeGeneratorRequest::parameter() const {
   return *parameter_;
 }
 inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
-  _set_bit(1);
-  if (parameter_ == &_default_parameter_) {
+  set_has_parameter();
+  if (parameter_ == &::google::protobuf::internal::kEmptyString) {
     parameter_ = new ::std::string;
   }
   parameter_->assign(value);
 }
 inline void CodeGeneratorRequest::set_parameter(const char* value) {
-  _set_bit(1);
-  if (parameter_ == &_default_parameter_) {
+  set_has_parameter();
+  if (parameter_ == &::google::protobuf::internal::kEmptyString) {
     parameter_ = new ::std::string;
   }
   parameter_->assign(value);
 }
 inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
-  _set_bit(1);
-  if (parameter_ == &_default_parameter_) {
+  set_has_parameter();
+  if (parameter_ == &::google::protobuf::internal::kEmptyString) {
     parameter_ = new ::std::string;
   }
   parameter_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* CodeGeneratorRequest::mutable_parameter() {
-  _set_bit(1);
-  if (parameter_ == &_default_parameter_) {
+  set_has_parameter();
+  if (parameter_ == &::google::protobuf::internal::kEmptyString) {
     parameter_ = new ::std::string;
   }
   return parameter_;
 }
+inline ::std::string* CodeGeneratorRequest::release_parameter() {
+  clear_has_parameter();
+  if (parameter_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = parameter_;
+    parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
 inline int CodeGeneratorRequest::proto_file_size() const {
@@ -511,129 +510,177 @@
 
 // optional string name = 1;
 inline bool CodeGeneratorResponse_File::has_name() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void CodeGeneratorResponse_File::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void CodeGeneratorResponse_File::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void CodeGeneratorResponse_File::clear_name() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     name_->clear();
   }
-  _clear_bit(0);
+  clear_has_name();
 }
 inline const ::std::string& CodeGeneratorResponse_File::name() const {
   return *name_;
 }
 inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void CodeGeneratorResponse_File::set_name(const char* value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* CodeGeneratorResponse_File::mutable_name() {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   return name_;
 }
+inline ::std::string* CodeGeneratorResponse_File::release_name() {
+  clear_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = name_;
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional string insertion_point = 2;
 inline bool CodeGeneratorResponse_File::has_insertion_point() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void CodeGeneratorResponse_File::set_has_insertion_point() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void CodeGeneratorResponse_File::clear_has_insertion_point() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void CodeGeneratorResponse_File::clear_insertion_point() {
-  if (insertion_point_ != &_default_insertion_point_) {
+  if (insertion_point_ != &::google::protobuf::internal::kEmptyString) {
     insertion_point_->clear();
   }
-  _clear_bit(1);
+  clear_has_insertion_point();
 }
 inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
   return *insertion_point_;
 }
 inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
-  _set_bit(1);
-  if (insertion_point_ == &_default_insertion_point_) {
+  set_has_insertion_point();
+  if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
     insertion_point_ = new ::std::string;
   }
   insertion_point_->assign(value);
 }
 inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
-  _set_bit(1);
-  if (insertion_point_ == &_default_insertion_point_) {
+  set_has_insertion_point();
+  if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
     insertion_point_ = new ::std::string;
   }
   insertion_point_->assign(value);
 }
 inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
-  _set_bit(1);
-  if (insertion_point_ == &_default_insertion_point_) {
+  set_has_insertion_point();
+  if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
     insertion_point_ = new ::std::string;
   }
   insertion_point_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
-  _set_bit(1);
-  if (insertion_point_ == &_default_insertion_point_) {
+  set_has_insertion_point();
+  if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
     insertion_point_ = new ::std::string;
   }
   return insertion_point_;
 }
+inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
+  clear_has_insertion_point();
+  if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = insertion_point_;
+    insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional string content = 15;
 inline bool CodeGeneratorResponse_File::has_content() const {
-  return _has_bit(2);
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void CodeGeneratorResponse_File::set_has_content() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void CodeGeneratorResponse_File::clear_has_content() {
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void CodeGeneratorResponse_File::clear_content() {
-  if (content_ != &_default_content_) {
+  if (content_ != &::google::protobuf::internal::kEmptyString) {
     content_->clear();
   }
-  _clear_bit(2);
+  clear_has_content();
 }
 inline const ::std::string& CodeGeneratorResponse_File::content() const {
   return *content_;
 }
 inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
-  _set_bit(2);
-  if (content_ == &_default_content_) {
+  set_has_content();
+  if (content_ == &::google::protobuf::internal::kEmptyString) {
     content_ = new ::std::string;
   }
   content_->assign(value);
 }
 inline void CodeGeneratorResponse_File::set_content(const char* value) {
-  _set_bit(2);
-  if (content_ == &_default_content_) {
+  set_has_content();
+  if (content_ == &::google::protobuf::internal::kEmptyString) {
     content_ = new ::std::string;
   }
   content_->assign(value);
 }
 inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
-  _set_bit(2);
-  if (content_ == &_default_content_) {
+  set_has_content();
+  if (content_ == &::google::protobuf::internal::kEmptyString) {
     content_ = new ::std::string;
   }
   content_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* CodeGeneratorResponse_File::mutable_content() {
-  _set_bit(2);
-  if (content_ == &_default_content_) {
+  set_has_content();
+  if (content_ == &::google::protobuf::internal::kEmptyString) {
     content_ = new ::std::string;
   }
   return content_;
 }
+inline ::std::string* CodeGeneratorResponse_File::release_content() {
+  clear_has_content();
+  if (content_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = content_;
+    content_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // -------------------------------------------------------------------
 
@@ -641,45 +688,61 @@
 
 // optional string error = 1;
 inline bool CodeGeneratorResponse::has_error() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void CodeGeneratorResponse::set_has_error() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void CodeGeneratorResponse::clear_has_error() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void CodeGeneratorResponse::clear_error() {
-  if (error_ != &_default_error_) {
+  if (error_ != &::google::protobuf::internal::kEmptyString) {
     error_->clear();
   }
-  _clear_bit(0);
+  clear_has_error();
 }
 inline const ::std::string& CodeGeneratorResponse::error() const {
   return *error_;
 }
 inline void CodeGeneratorResponse::set_error(const ::std::string& value) {
-  _set_bit(0);
-  if (error_ == &_default_error_) {
+  set_has_error();
+  if (error_ == &::google::protobuf::internal::kEmptyString) {
     error_ = new ::std::string;
   }
   error_->assign(value);
 }
 inline void CodeGeneratorResponse::set_error(const char* value) {
-  _set_bit(0);
-  if (error_ == &_default_error_) {
+  set_has_error();
+  if (error_ == &::google::protobuf::internal::kEmptyString) {
     error_ = new ::std::string;
   }
   error_->assign(value);
 }
 inline void CodeGeneratorResponse::set_error(const char* value, size_t size) {
-  _set_bit(0);
-  if (error_ == &_default_error_) {
+  set_has_error();
+  if (error_ == &::google::protobuf::internal::kEmptyString) {
     error_ = new ::std::string;
   }
   error_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* CodeGeneratorResponse::mutable_error() {
-  _set_bit(0);
-  if (error_ == &_default_error_) {
+  set_has_error();
+  if (error_ == &::google::protobuf::internal::kEmptyString) {
     error_ = new ::std::string;
   }
   return error_;
 }
+inline ::std::string* CodeGeneratorResponse::release_error() {
+  clear_has_error();
+  if (error_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = error_;
+    error_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
 inline int CodeGeneratorResponse::file_size() const {
diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto
index 4e928b0..651ed10 100644
--- a/src/google/protobuf/compiler/plugin.proto
+++ b/src/google/protobuf/compiler/plugin.proto
@@ -131,7 +131,7 @@
     // in order to work correctly in that context.
     //
     // The code generator that generates the initial file and the one which
-    // inserts into it must both run as part of a single invocatino of protoc.
+    // inserts into it must both run as part of a single invocation of protoc.
     // Code generators are executed in the order in which they appear on the
     // command line.
     //
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index fae83a3..9b10937 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -230,7 +230,7 @@
 
 bool Generator::Generate(const FileDescriptor* file,
                          const string& parameter,
-                         OutputDirectory* output_directory,
+                         GeneratorContext* context,
                          string* error) const {
 
   // Completely serialize all Generate() calls on this instance.  The
@@ -252,20 +252,18 @@
   fdp.SerializeToString(&file_descriptor_serialized_);
 
 
-  scoped_ptr<io::ZeroCopyOutputStream> output(output_directory->Open(filename));
+  scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
   GOOGLE_CHECK(output.get());
   io::Printer printer(output.get(), '$');
   printer_ = &printer;
 
   PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto());
+  PrintImports();
   PrintFileDescriptor();
   PrintTopLevelEnums();
   PrintTopLevelExtensions();
   PrintAllNestedEnumsInFile();
   PrintMessageDescriptors();
-  // We have to print the imports after the descriptors, so that mutually
-  // recursive protos in separate files can successfully reference each other.
-  PrintImports();
   FixForeignFieldsInDescriptors();
   PrintMessages();
   // We have to fix up the extensions after the message classes themselves,
@@ -377,7 +375,7 @@
   printer_->Print("containing_type=None,\n");
   printer_->Print("options=$options_value$,\n",
                   "options_value",
-                  OptionsValue("EnumOptions", CEscape(options_string)));
+                  OptionsValue("EnumOptions", options_string));
   EnumDescriptorProto edp;
   PrintSerializedPbInterval(enum_descriptor, edp);
   printer_->Outdent();
@@ -674,6 +672,17 @@
   }
 }
 
+void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const {
+  map<string, string> m;
+  m["descriptor_name"] = kDescriptorKey;
+  m["message_name"] = descriptor.name();
+  m["message_descriptor_name"] = ModuleLevelDescriptorName(descriptor);
+  const char file_descriptor_template[] =
+      "$descriptor_name$.message_types_by_name['$message_name$'] = "
+      "$message_descriptor_name$\n";
+  printer_->Print(m, file_descriptor_template);
+}
+
 // Sets any necessary message_type and enum_type attributes
 // for the Python version of |field|.
 //
@@ -752,6 +761,9 @@
   for (int i = 0; i < file_->message_type_count(); ++i) {
     FixForeignFieldsInDescriptor(*file_->message_type(i), NULL);
   }
+  for (int i = 0; i < file_->message_type_count(); ++i) {
+    AddMessageToFileDescriptor(*file_->message_type(i));
+  }
   printer_->Print("\n");
 }
 
@@ -823,6 +835,8 @@
       "  type=None)");
 }
 
+// Returns a Python expression that calls descriptor._ParseOptions using
+// the given descriptor class name and serialized options protobuf string.
 string Generator::OptionsValue(
     const string& class_name, const string& serialized_options) const {
   if (serialized_options.length() == 0 || GeneratingDescriptorProto()) {
diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h
index 43c2087..84eaf8a 100644
--- a/src/google/protobuf/compiler/python/python_generator.h
+++ b/src/google/protobuf/compiler/python/python_generator.h
@@ -66,7 +66,7 @@
   // CodeGenerator methods.
   virtual bool Generate(const FileDescriptor* file,
                         const string& parameter,
-                        OutputDirectory* output_directory,
+                        GeneratorContext* generator_context,
                         string* error) const;
 
  private:
@@ -104,6 +104,7 @@
   void FixForeignFieldsInField(const Descriptor* containing_type,
                                const FieldDescriptor& field,
                                const string& python_dict_name) const;
+  void AddMessageToFileDescriptor(const Descriptor& descriptor) const;
   string FieldReferencingExpression(const Descriptor* containing_type,
                                     const FieldDescriptor& field,
                                     const string& python_dict_name) const;
diff --git a/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
index fde8876..da619ad 100644
--- a/src/google/protobuf/compiler/python/python_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
@@ -56,19 +56,19 @@
 
   virtual bool Generate(const FileDescriptor* file,
                         const string& parameter,
-                        OutputDirectory* output_directory,
+                        GeneratorContext* context,
                         string* error) const {
-    TryInsert("test_pb2.py", "imports", output_directory);
-    TryInsert("test_pb2.py", "module_scope", output_directory);
-    TryInsert("test_pb2.py", "class_scope:foo.Bar", output_directory);
-    TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", output_directory);
+    TryInsert("test_pb2.py", "imports", context);
+    TryInsert("test_pb2.py", "module_scope", context);
+    TryInsert("test_pb2.py", "class_scope:foo.Bar", context);
+    TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", context);
     return true;
   }
 
   void TryInsert(const string& filename, const string& insertion_point,
-                 OutputDirectory* output_directory) const {
+                 GeneratorContext* context) const {
     scoped_ptr<io::ZeroCopyOutputStream> output(
-      output_directory->OpenForInsert(filename, insertion_point));
+      context->OpenForInsert(filename, insertion_point));
     io::Printer printer(output.get(), '$');
     printer.Print("// inserted $name$\n", "name", insertion_point);
   }
diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc
index dbd813e..5fb5d5c 100644
--- a/src/google/protobuf/compiler/subprocess.cc
+++ b/src/google/protobuf/compiler/subprocess.cc
@@ -32,6 +32,8 @@
 
 #include <google/protobuf/compiler/subprocess.h>
 
+#include <algorithm>
+
 #ifndef _WIN32
 #include <errno.h>
 #include <sys/select.h>
@@ -39,7 +41,6 @@
 #include <signal.h>
 #endif
 
-#include <algorithm>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/message.h>
 #include <google/protobuf/stubs/substitute.h>
diff --git a/src/google/protobuf/compiler/subprocess.h b/src/google/protobuf/compiler/subprocess.h
index 7a6fa70..de9fce9 100644
--- a/src/google/protobuf/compiler/subprocess.h
+++ b/src/google/protobuf/compiler/subprocess.h
@@ -40,9 +40,10 @@
 #include <sys/types.h>
 #include <unistd.h>
 #endif  // !_WIN32
+#include <google/protobuf/stubs/common.h>
 
 #include <string>
-#include <google/protobuf/stubs/common.h>
+
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/zip_output_unittest.sh b/src/google/protobuf/compiler/zip_output_unittest.sh
index 259d5d2..3a02436 100755
--- a/src/google/protobuf/compiler/zip_output_unittest.sh
+++ b/src/google/protobuf/compiler/zip_output_unittest.sh
@@ -39,45 +39,51 @@
   exit 1
 }
 
+TEST_TMPDIR=.
+PROTOC=./protoc
+
 echo '
+  syntax = "proto2";
   option java_multiple_files = true;
   option java_package = "test.jar";
   option java_outer_classname = "Outer";
   message Foo {}
   message Bar {}
-' > testzip.proto
+' > $TEST_TMPDIR/testzip.proto
 
-./protoc --cpp_out=testzip.zip --python_out=testzip.zip --java_out=testzip.jar \
-    testzip.proto || fail 'protoc failed.'
+$PROTOC \
+    --cpp_out=$TEST_TMPDIR/testzip.zip --python_out=$TEST_TMPDIR/testzip.zip \
+    --java_out=$TEST_TMPDIR/testzip.jar -I$TEST_TMPDIR testzip.proto \
+    || fail 'protoc failed.'
 
 echo "Testing output to zip..."
 if unzip -h > /dev/null; then
-  unzip -t testzip.zip > testzip.list || fail 'unzip failed.'
+  unzip -t $TEST_TMPDIR/testzip.zip > $TEST_TMPDIR/testzip.list || fail 'unzip failed.'
 
-  grep 'testing: testzip\.pb\.cc *OK$' testzip.list > /dev/null \
+  grep 'testing: testzip\.pb\.cc *OK$' $TEST_TMPDIR/testzip.list > /dev/null \
     || fail 'testzip.pb.cc not found in output zip.'
-  grep 'testing: testzip\.pb\.h *OK$' testzip.list > /dev/null \
+  grep 'testing: testzip\.pb\.h *OK$' $TEST_TMPDIR/testzip.list > /dev/null \
     || fail 'testzip.pb.h not found in output zip.'
-  grep 'testing: testzip_pb2\.py *OK$' testzip.list > /dev/null \
+  grep 'testing: testzip_pb2\.py *OK$' $TEST_TMPDIR/testzip.list > /dev/null \
     || fail 'testzip_pb2.py not found in output zip.'
-  grep -i 'manifest' testzip.list > /dev/null \
+  grep -i 'manifest' $TEST_TMPDIR/testzip.list > /dev/null \
     && fail 'Zip file contained manifest.'
 else
   echo "Warning:  'unzip' command not available.  Skipping test."
 fi
 
 echo "Testing output to jar..."
-if jar c testzip.proto > /dev/null; then
-  jar tf testzip.jar > testzip.list || fail 'jar failed.'
+if jar c $TEST_TMPDIR/testzip.proto > /dev/null; then
+  jar tf $TEST_TMPDIR/testzip.jar > $TEST_TMPDIR/testzip.list || fail 'jar failed.'
 
-  grep '^test/jar/Foo\.java$' testzip.list > /dev/null \
+  grep '^test/jar/Foo\.java$' $TEST_TMPDIR/testzip.list > /dev/null \
     || fail 'Foo.java not found in output jar.'
-  grep '^test/jar/Bar\.java$' testzip.list > /dev/null \
+  grep '^test/jar/Bar\.java$' $TEST_TMPDIR/testzip.list > /dev/null \
     || fail 'Bar.java not found in output jar.'
-  grep '^test/jar/Outer\.java$' testzip.list > /dev/null \
+  grep '^test/jar/Outer\.java$' $TEST_TMPDIR/testzip.list > /dev/null \
     || fail 'Outer.java not found in output jar.'
-  grep '^META-INF/MANIFEST\.MF$' testzip.list > /dev/null \
-    || fail 'Manifest not ofund in output jar.'
+  grep '^META-INF/MANIFEST\.MF$' $TEST_TMPDIR/testzip.list > /dev/null \
+    || fail 'Manifest not found in output jar.'
 else
   echo "Warning:  'jar' command not available.  Skipping test."
 fi
diff --git a/src/google/protobuf/compiler/zip_writer.cc b/src/google/protobuf/compiler/zip_writer.cc
index 53c1877..65d7352 100644
--- a/src/google/protobuf/compiler/zip_writer.cc
+++ b/src/google/protobuf/compiler/zip_writer.cc
@@ -28,6 +28,36 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
 // Author: ambrose@google.com (Ambrose Feinstein),
 //         kenton@google.com (Kenton Varda)
 //
@@ -183,6 +213,6 @@
   return output.HadError();
 }
 
-}  // namespace google
-}  // namespace protobuf
 }  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/zip_writer.h b/src/google/protobuf/compiler/zip_writer.h
index 4289553..be73972 100644
--- a/src/google/protobuf/compiler/zip_writer.h
+++ b/src/google/protobuf/compiler/zip_writer.h
@@ -28,6 +28,36 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
 // Author: kenton@google.com (Kenton Varda)
 
 #include <vector>
@@ -58,6 +88,6 @@
   vector<FileInfo> files_;
 };
 
-}  // namespace google
-}  // namespace protobuf
 }  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index 9226dfb..76b7219 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -42,10 +42,12 @@
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/descriptor_database.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/text_format.h>
 #include <google/protobuf/unknown_field_set.h>
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/tokenizer.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/once.h>
@@ -2056,6 +2058,8 @@
     // Otherwise returns true.
     bool InterpretOptions(OptionsToInterpret* options_to_interpret);
 
+    class AggregateOptionFinder;
+
    private:
     // Interprets uninterpreted_option_ on the specified message, which
     // must be the mutable copy of the original options message to which
@@ -2082,6 +2086,11 @@
     bool SetOptionValue(const FieldDescriptor* option_field,
                         UnknownFieldSet* unknown_fields);
 
+    // Parses an aggregate value for a CPPTYPE_MESSAGE option and
+    // saves it into *unknown_fields.
+    bool SetAggregateOption(const FieldDescriptor* option_field,
+                            UnknownFieldSet* unknown_fields);
+
     // Convenience functions to set an int field the right way, depending on
     // its wire type (a single int CppType can represent multiple wire types).
     void SetInt32(int number, int32 value, FieldDescriptor::Type type,
@@ -2128,6 +2137,10 @@
     // can use it to find locations recorded by the parser.
     const UninterpretedOption* uninterpreted_option_;
 
+    // Factory used to create the dynamic messages we need to parse
+    // any aggregate option values we encounter.
+    DynamicMessageFactory dynamic_factory_;
+
     GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OptionInterpreter);
   };
 
@@ -2139,6 +2152,8 @@
   // redundantly declare OptionInterpreter a friend just to make things extra
   // clear for these bad compilers.
   friend class OptionInterpreter;
+  friend class OptionInterpreter::AggregateOptionFinder;
+
   static inline bool get_allow_unknown(const DescriptorPool* pool) {
     return pool->allow_unknown_;
   }
@@ -3973,9 +3988,6 @@
         intermediate_fields.push_back(field);
         descriptor = field->message_type();
       }
-    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
-      return AddNameError("Option field \"" + debug_msg_name +
-                          "\" cannot be of message type.");
     }
   }
 
@@ -4310,18 +4322,95 @@
       break;
 
     case FieldDescriptor::CPPTYPE_MESSAGE:
-      // We don't currently support defining a message-typed option, so we
-      // should never actually get here.
-      return AddValueError("Option \"" + option_field->full_name() +
-                           "\" is a message.  To set fields within it, use "
-                           "syntax like \"" + option_field->name() +
-                           ".foo = value\".");
+      if (!SetAggregateOption(option_field, unknown_fields)) {
+        return false;
+      }
       break;
   }
 
   return true;
 }
 
+class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder
+    : public TextFormat::Finder {
+ public:
+  DescriptorBuilder* builder_;
+
+  virtual const FieldDescriptor* FindExtension(
+      Message* message, const string& name) const {
+    if (builder_->pool_->mutex_ != NULL) {
+      builder_->pool_->mutex_->AssertHeld();
+    }
+    Symbol result = builder_->LookupSymbolNoPlaceholder(
+        name, message->GetDescriptor()->full_name());
+    if (result.type == Symbol::FIELD &&
+        result.field_descriptor->is_extension()) {
+      return result.field_descriptor;
+    } else {
+      return NULL;
+    }
+  }
+};
+
+// A custom error collector to record any text-format parsing errors
+namespace {
+class AggregateErrorCollector : public io::ErrorCollector {
+ public:
+  string error_;
+
+  virtual void AddError(int line, int column, const string& message) {
+    if (!error_.empty()) {
+      error_ += "; ";
+    }
+    error_ += message;
+  }
+
+  virtual void AddWarning(int line, int column, const string& message) {
+    // Ignore warnings
+  }
+};
+}
+
+// We construct a dynamic message of the type corresponding to
+// option_field, parse the supplied text-format string into this
+// message, and serialize the resulting message to produce the value.
+bool DescriptorBuilder::OptionInterpreter::SetAggregateOption(
+    const FieldDescriptor* option_field,
+    UnknownFieldSet* unknown_fields) {
+  if (!uninterpreted_option_->has_aggregate_value()) {
+    return AddValueError("Option \"" + option_field->full_name() +
+                         "\" is a message. To set the entire message, use "
+                         "syntax like \"" + option_field->name() +
+                         " = { <proto text format> }\". "
+                         "To set fields within it, use "
+                         "syntax like \"" + option_field->name() +
+                         ".foo = value\".");
+  }
+
+  const Descriptor* type = option_field->message_type();
+  scoped_ptr<Message> dynamic(dynamic_factory_.GetPrototype(type)->New());
+  GOOGLE_CHECK(dynamic.get() != NULL)
+      << "Could not create an instance of " << option_field->DebugString();
+
+  AggregateErrorCollector collector;
+  AggregateOptionFinder finder;
+  finder.builder_ = builder_;
+  TextFormat::Parser parser;
+  parser.RecordErrorsTo(&collector);
+  parser.SetFinder(&finder);
+  if (!parser.ParseFromString(uninterpreted_option_->aggregate_value(),
+                              dynamic.get())) {
+    AddValueError("Error while parsing option value for \"" +
+                  option_field->name() + "\": " + collector.error_);
+    return false;
+  } else {
+    string serial;
+    dynamic->SerializeToString(&serial);  // Never fails
+    unknown_fields->AddLengthDelimited(option_field->number(), serial);
+    return true;
+  }
+}
+
 void DescriptorBuilder::OptionInterpreter::SetInt32(int number, int32 value,
     FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
   switch (type) {
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index 922237f..87303ef 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -76,6 +76,12 @@
 const ::google::protobuf::Descriptor* UninterpretedOption_NamePart_descriptor_ = NULL;
 const ::google::protobuf::internal::GeneratedMessageReflection*
   UninterpretedOption_NamePart_reflection_ = NULL;
+const ::google::protobuf::Descriptor* SourceCodeInfo_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  SourceCodeInfo_reflection_ = NULL;
+const ::google::protobuf::Descriptor* SourceCodeInfo_Location_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  SourceCodeInfo_Location_reflection_ = NULL;
 
 }  // namespace
 
@@ -102,7 +108,7 @@
       ::google::protobuf::MessageFactory::generated_factory(),
       sizeof(FileDescriptorSet));
   FileDescriptorProto_descriptor_ = file->message_type(1);
-  static const int FileDescriptorProto_offsets_[8] = {
+  static const int FileDescriptorProto_offsets_[9] = {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, name_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, package_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, dependency_),
@@ -111,6 +117,7 @@
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, service_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, extension_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, options_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, source_code_info_),
   };
   FileDescriptorProto_reflection_ =
     new ::google::protobuf::internal::GeneratedMessageReflection(
@@ -254,10 +261,11 @@
       ::google::protobuf::MessageFactory::generated_factory(),
       sizeof(MethodDescriptorProto));
   FileOptions_descriptor_ = file->message_type(8);
-  static const int FileOptions_offsets_[8] = {
+  static const int FileOptions_offsets_[9] = {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generate_equals_and_hash_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, optimize_for_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_generic_services_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generic_services_),
@@ -374,13 +382,14 @@
       ::google::protobuf::MessageFactory::generated_factory(),
       sizeof(MethodOptions));
   UninterpretedOption_descriptor_ = file->message_type(15);
-  static const int UninterpretedOption_offsets_[6] = {
+  static const int UninterpretedOption_offsets_[7] = {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, name_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, identifier_value_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, positive_int_value_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, negative_int_value_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, double_value_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, string_value_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, aggregate_value_),
   };
   UninterpretedOption_reflection_ =
     new ::google::protobuf::internal::GeneratedMessageReflection(
@@ -409,6 +418,37 @@
       ::google::protobuf::DescriptorPool::generated_pool(),
       ::google::protobuf::MessageFactory::generated_factory(),
       sizeof(UninterpretedOption_NamePart));
+  SourceCodeInfo_descriptor_ = file->message_type(16);
+  static const int SourceCodeInfo_offsets_[1] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, location_),
+  };
+  SourceCodeInfo_reflection_ =
+    new ::google::protobuf::internal::GeneratedMessageReflection(
+      SourceCodeInfo_descriptor_,
+      SourceCodeInfo::default_instance_,
+      SourceCodeInfo_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _has_bits_[0]),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _unknown_fields_),
+      -1,
+      ::google::protobuf::DescriptorPool::generated_pool(),
+      ::google::protobuf::MessageFactory::generated_factory(),
+      sizeof(SourceCodeInfo));
+  SourceCodeInfo_Location_descriptor_ = SourceCodeInfo_descriptor_->nested_type(0);
+  static const int SourceCodeInfo_Location_offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, path_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, span_),
+  };
+  SourceCodeInfo_Location_reflection_ =
+    new ::google::protobuf::internal::GeneratedMessageReflection(
+      SourceCodeInfo_Location_descriptor_,
+      SourceCodeInfo_Location::default_instance_,
+      SourceCodeInfo_Location_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _has_bits_[0]),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _unknown_fields_),
+      -1,
+      ::google::protobuf::DescriptorPool::generated_pool(),
+      ::google::protobuf::MessageFactory::generated_factory(),
+      sizeof(SourceCodeInfo_Location));
 }
 
 namespace {
@@ -457,6 +497,10 @@
     UninterpretedOption_descriptor_, &UninterpretedOption::default_instance());
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
     UninterpretedOption_NamePart_descriptor_, &UninterpretedOption_NamePart::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+    SourceCodeInfo_descriptor_, &SourceCodeInfo::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+    SourceCodeInfo_Location_descriptor_, &SourceCodeInfo_Location::default_instance());
 }
 
 }  // namespace
@@ -498,6 +542,10 @@
   delete UninterpretedOption_reflection_;
   delete UninterpretedOption_NamePart::default_instance_;
   delete UninterpretedOption_NamePart_reflection_;
+  delete SourceCodeInfo::default_instance_;
+  delete SourceCodeInfo_reflection_;
+  delete SourceCodeInfo_Location::default_instance_;
+  delete SourceCodeInfo_Location_reflection_;
 }
 
 void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
@@ -510,7 +558,7 @@
     "\n google/protobuf/descriptor.proto\022\017goog"
     "le.protobuf\"G\n\021FileDescriptorSet\0222\n\004file"
     "\030\001 \003(\0132$.google.protobuf.FileDescriptorP"
-    "roto\"\334\002\n\023FileDescriptorProto\022\014\n\004name\030\001 \001"
+    "roto\"\227\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001"
     "(\t\022\017\n\007package\030\002 \001(\t\022\022\n\ndependency\030\003 \003(\t\022"
     "6\n\014message_type\030\004 \003(\0132 .google.protobuf."
     "DescriptorProto\0227\n\tenum_type\030\005 \003(\0132$.goo"
@@ -518,88 +566,94 @@
     "ice\030\006 \003(\0132\'.google.protobuf.ServiceDescr"
     "iptorProto\0228\n\textension\030\007 \003(\0132%.google.p"
     "rotobuf.FieldDescriptorProto\022-\n\007options\030"
-    "\010 \001(\0132\034.google.protobuf.FileOptions\"\251\003\n\017"
-    "DescriptorProto\022\014\n\004name\030\001 \001(\t\0224\n\005field\030\002"
-    " \003(\0132%.google.protobuf.FieldDescriptorPr"
-    "oto\0228\n\textension\030\006 \003(\0132%.google.protobuf"
-    ".FieldDescriptorProto\0225\n\013nested_type\030\003 \003"
-    "(\0132 .google.protobuf.DescriptorProto\0227\n\t"
-    "enum_type\030\004 \003(\0132$.google.protobuf.EnumDe"
-    "scriptorProto\022H\n\017extension_range\030\005 \003(\0132/"
-    ".google.protobuf.DescriptorProto.Extensi"
-    "onRange\0220\n\007options\030\007 \001(\0132\037.google.protob"
-    "uf.MessageOptions\032,\n\016ExtensionRange\022\r\n\005s"
-    "tart\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"\224\005\n\024FieldDescrip"
-    "torProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\003 \001(\005\022:"
-    "\n\005label\030\004 \001(\0162+.google.protobuf.FieldDes"
-    "criptorProto.Label\0228\n\004type\030\005 \001(\0162*.googl"
-    "e.protobuf.FieldDescriptorProto.Type\022\021\n\t"
-    "type_name\030\006 \001(\t\022\020\n\010extendee\030\002 \001(\t\022\025\n\rdef"
-    "ault_value\030\007 \001(\t\022.\n\007options\030\010 \001(\0132\035.goog"
-    "le.protobuf.FieldOptions\"\266\002\n\004Type\022\017\n\013TYP"
-    "E_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64"
-    "\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014T"
-    "YPE_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_"
-    "BOOL\020\010\022\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_GROUP\020\n\022"
-    "\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TYP"
-    "E_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXED"
-    "32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_SINT32\020\021"
-    "\022\017\n\013TYPE_SINT64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTI"
-    "ONAL\020\001\022\022\n\016LABEL_REQUIRED\020\002\022\022\n\016LABEL_REPE"
-    "ATED\020\003\"\214\001\n\023EnumDescriptorProto\022\014\n\004name\030\001"
-    " \001(\t\0228\n\005value\030\002 \003(\0132).google.protobuf.En"
-    "umValueDescriptorProto\022-\n\007options\030\003 \001(\0132"
-    "\034.google.protobuf.EnumOptions\"l\n\030EnumVal"
-    "ueDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006numbe"
-    "r\030\002 \001(\005\0222\n\007options\030\003 \001(\0132!.google.protob"
-    "uf.EnumValueOptions\"\220\001\n\026ServiceDescripto"
-    "rProto\022\014\n\004name\030\001 \001(\t\0226\n\006method\030\002 \003(\0132&.g"
-    "oogle.protobuf.MethodDescriptorProto\0220\n\007"
-    "options\030\003 \001(\0132\037.google.protobuf.ServiceO"
-    "ptions\"\177\n\025MethodDescriptorProto\022\014\n\004name\030"
-    "\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t\022\023\n\013output_type"
-    "\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.protobu"
-    "f.MethodOptions\"\244\003\n\013FileOptions\022\024\n\014java_"
-    "package\030\001 \001(\t\022\034\n\024java_outer_classname\030\010 "
-    "\001(\t\022\"\n\023java_multiple_files\030\n \001(\010:\005false\022"
-    "F\n\014optimize_for\030\t \001(\0162).google.protobuf."
-    "FileOptions.OptimizeMode:\005SPEED\022!\n\023cc_ge"
-    "neric_services\030\020 \001(\010:\004true\022#\n\025java_gener"
-    "ic_services\030\021 \001(\010:\004true\022!\n\023py_generic_se"
-    "rvices\030\022 \001(\010:\004true\022C\n\024uninterpreted_opti"
-    "on\030\347\007 \003(\0132$.google.protobuf.Uninterprete"
-    "dOption\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCO"
-    "DE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\270"
-    "\001\n\016MessageOptions\022&\n\027message_set_wire_fo"
-    "rmat\030\001 \001(\010:\005false\022.\n\037no_standard_descrip"
-    "tor_accessor\030\002 \001(\010:\005false\022C\n\024uninterpret"
+    "\010 \001(\0132\034.google.protobuf.FileOptions\0229\n\020s"
+    "ource_code_info\030\t \001(\0132\037.google.protobuf."
+    "SourceCodeInfo\"\251\003\n\017DescriptorProto\022\014\n\004na"
+    "me\030\001 \001(\t\0224\n\005field\030\002 \003(\0132%.google.protobu"
+    "f.FieldDescriptorProto\0228\n\textension\030\006 \003("
+    "\0132%.google.protobuf.FieldDescriptorProto"
+    "\0225\n\013nested_type\030\003 \003(\0132 .google.protobuf."
+    "DescriptorProto\0227\n\tenum_type\030\004 \003(\0132$.goo"
+    "gle.protobuf.EnumDescriptorProto\022H\n\017exte"
+    "nsion_range\030\005 \003(\0132/.google.protobuf.Desc"
+    "riptorProto.ExtensionRange\0220\n\007options\030\007 "
+    "\001(\0132\037.google.protobuf.MessageOptions\032,\n\016"
+    "ExtensionRange\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001"
+    "(\005\"\224\005\n\024FieldDescriptorProto\022\014\n\004name\030\001 \001("
+    "\t\022\016\n\006number\030\003 \001(\005\022:\n\005label\030\004 \001(\0162+.googl"
+    "e.protobuf.FieldDescriptorProto.Label\0228\n"
+    "\004type\030\005 \001(\0162*.google.protobuf.FieldDescr"
+    "iptorProto.Type\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010ex"
+    "tendee\030\002 \001(\t\022\025\n\rdefault_value\030\007 \001(\t\022.\n\007o"
+    "ptions\030\010 \001(\0132\035.google.protobuf.FieldOpti"
+    "ons\"\266\002\n\004Type\022\017\n\013TYPE_DOUBLE\020\001\022\016\n\nTYPE_FL"
+    "OAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013TYPE_UINT64\020\004\022\016"
+    "\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIXED64\020\006\022\020\n\014TYPE"
+    "_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022\017\n\013TYPE_STRING"
+    "\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\n"
+    "TYPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE_EN"
+    "UM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rTYPE_SFIXED64"
+    "\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_SINT64\020\022\"C\n\005"
+    "Label\022\022\n\016LABEL_OPTIONAL\020\001\022\022\n\016LABEL_REQUI"
+    "RED\020\002\022\022\n\016LABEL_REPEATED\020\003\"\214\001\n\023EnumDescri"
+    "ptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005value\030\002 \003(\0132)"
+    ".google.protobuf.EnumValueDescriptorProt"
+    "o\022-\n\007options\030\003 \001(\0132\034.google.protobuf.Enu"
+    "mOptions\"l\n\030EnumValueDescriptorProto\022\014\n\004"
+    "name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222\n\007options\030\003 "
+    "\001(\0132!.google.protobuf.EnumValueOptions\"\220"
+    "\001\n\026ServiceDescriptorProto\022\014\n\004name\030\001 \001(\t\022"
+    "6\n\006method\030\002 \003(\0132&.google.protobuf.Method"
+    "DescriptorProto\0220\n\007options\030\003 \001(\0132\037.googl"
+    "e.protobuf.ServiceOptions\"\177\n\025MethodDescr"
+    "iptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\ninput_type\030\002"
+    " \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n\007options\030\004 \001"
+    "(\0132\036.google.protobuf.MethodOptions\"\325\003\n\013F"
+    "ileOptions\022\024\n\014java_package\030\001 \001(\t\022\034\n\024java"
+    "_outer_classname\030\010 \001(\t\022\"\n\023java_multiple_"
+    "files\030\n \001(\010:\005false\022,\n\035java_generate_equa"
+    "ls_and_hash\030\024 \001(\010:\005false\022F\n\014optimize_for"
+    "\030\t \001(\0162).google.protobuf.FileOptions.Opt"
+    "imizeMode:\005SPEED\022\"\n\023cc_generic_services\030"
+    "\020 \001(\010:\005false\022$\n\025java_generic_services\030\021 "
+    "\001(\010:\005false\022\"\n\023py_generic_services\030\022 \001(\010:"
+    "\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$."
+    "google.protobuf.UninterpretedOption\":\n\014O"
+    "ptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n"
+    "\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\270\001\n\016MessageOp"
+    "tions\022&\n\027message_set_wire_format\030\001 \001(\010:\005"
+    "false\022.\n\037no_standard_descriptor_accessor"
+    "\030\002 \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007"
+    " \003(\0132$.google.protobuf.UninterpretedOpti"
+    "on*\t\010\350\007\020\200\200\200\200\002\"\224\002\n\014FieldOptions\022:\n\005ctype\030"
+    "\001 \001(\0162#.google.protobuf.FieldOptions.CTy"
+    "pe:\006STRING\022\016\n\006packed\030\002 \001(\010\022\031\n\ndeprecated"
+    "\030\003 \001(\010:\005false\022\034\n\024experimental_map_key\030\t "
+    "\001(\t\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goo"
+    "gle.protobuf.UninterpretedOption\"/\n\005CTyp"
+    "e\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020"
+    "\002*\t\010\350\007\020\200\200\200\200\002\"]\n\013EnumOptions\022C\n\024uninterpr"
+    "eted_option\030\347\007 \003(\0132$.google.protobuf.Uni"
+    "nterpretedOption*\t\010\350\007\020\200\200\200\200\002\"b\n\020EnumValue"
+    "Options\022C\n\024uninterpreted_option\030\347\007 \003(\0132$"
+    ".google.protobuf.UninterpretedOption*\t\010\350"
+    "\007\020\200\200\200\200\002\"`\n\016ServiceOptions\022C\n\024uninterpret"
     "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint"
-    "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"\224\002\n\014FieldOptio"
-    "ns\022:\n\005ctype\030\001 \001(\0162#.google.protobuf.Fiel"
-    "dOptions.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\031"
-    "\n\ndeprecated\030\003 \001(\010:\005false\022\034\n\024experimenta"
-    "l_map_key\030\t \001(\t\022C\n\024uninterpreted_option\030"
-    "\347\007 \003(\0132$.google.protobuf.UninterpretedOp"
-    "tion\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014S"
-    "TRING_PIECE\020\002*\t\010\350\007\020\200\200\200\200\002\"]\n\013EnumOptions\022"
-    "C\n\024uninterpreted_option\030\347\007 \003(\0132$.google."
-    "protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\""
-    "b\n\020EnumValueOptions\022C\n\024uninterpreted_opt"
-    "ion\030\347\007 \003(\0132$.google.protobuf.Uninterpret"
-    "edOption*\t\010\350\007\020\200\200\200\200\002\"`\n\016ServiceOptions\022C\n"
-    "\024uninterpreted_option\030\347\007 \003(\0132$.google.pr"
-    "otobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"_\n"
-    "\rMethodOptions\022C\n\024uninterpreted_option\030\347"
-    "\007 \003(\0132$.google.protobuf.UninterpretedOpt"
-    "ion*\t\010\350\007\020\200\200\200\200\002\"\205\002\n\023UninterpretedOption\022;"
-    "\n\004name\030\002 \003(\0132-.google.protobuf.Uninterpr"
-    "etedOption.NamePart\022\030\n\020identifier_value\030"
-    "\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022neg"
-    "ative_int_value\030\005 \001(\003\022\024\n\014double_value\030\006 "
-    "\001(\001\022\024\n\014string_value\030\007 \001(\014\0323\n\010NamePart\022\021\n"
-    "\tname_part\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010B)"
-    "\n\023com.google.protobufB\020DescriptorProtosH"
-    "\001", 3681);
+    "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"_\n\rMethodOptio"
+    "ns\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goog"
+    "le.protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200"
+    "\200\002\"\236\002\n\023UninterpretedOption\022;\n\004name\030\002 \003(\013"
+    "2-.google.protobuf.UninterpretedOption.N"
+    "amePart\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022pos"
+    "itive_int_value\030\004 \001(\004\022\032\n\022negative_int_va"
+    "lue\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014strin"
+    "g_value\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323"
+    "\n\010NamePart\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_exte"
+    "nsion\030\002 \002(\010\"|\n\016SourceCodeInfo\022:\n\010locatio"
+    "n\030\001 \003(\0132(.google.protobuf.SourceCodeInfo"
+    ".Location\032.\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022"
+    "\020\n\004span\030\002 \003(\005B\002\020\001B)\n\023com.google.protobuf"
+    "B\020DescriptorProtosH\001", 3940);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
   FileDescriptorSet::default_instance_ = new FileDescriptorSet();
@@ -620,6 +674,8 @@
   MethodOptions::default_instance_ = new MethodOptions();
   UninterpretedOption::default_instance_ = new UninterpretedOption();
   UninterpretedOption_NamePart::default_instance_ = new UninterpretedOption_NamePart();
+  SourceCodeInfo::default_instance_ = new SourceCodeInfo();
+  SourceCodeInfo_Location::default_instance_ = new SourceCodeInfo_Location();
   FileDescriptorSet::default_instance_->InitAsDefaultInstance();
   FileDescriptorProto::default_instance_->InitAsDefaultInstance();
   DescriptorProto::default_instance_->InitAsDefaultInstance();
@@ -638,6 +694,8 @@
   MethodOptions::default_instance_->InitAsDefaultInstance();
   UninterpretedOption::default_instance_->InitAsDefaultInstance();
   UninterpretedOption_NamePart::default_instance_->InitAsDefaultInstance();
+  SourceCodeInfo::default_instance_->InitAsDefaultInstance();
+  SourceCodeInfo_Location::default_instance_->InitAsDefaultInstance();
   ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto);
 }
 
@@ -856,8 +914,6 @@
 
 // ===================================================================
 
-const ::std::string FileDescriptorProto::_default_name_;
-const ::std::string FileDescriptorProto::_default_package_;
 #ifndef _MSC_VER
 const int FileDescriptorProto::kNameFieldNumber;
 const int FileDescriptorProto::kPackageFieldNumber;
@@ -867,6 +923,7 @@
 const int FileDescriptorProto::kServiceFieldNumber;
 const int FileDescriptorProto::kExtensionFieldNumber;
 const int FileDescriptorProto::kOptionsFieldNumber;
+const int FileDescriptorProto::kSourceCodeInfoFieldNumber;
 #endif  // !_MSC_VER
 
 FileDescriptorProto::FileDescriptorProto()
@@ -876,6 +933,7 @@
 
 void FileDescriptorProto::InitAsDefaultInstance() {
   options_ = const_cast< ::google::protobuf::FileOptions*>(&::google::protobuf::FileOptions::default_instance());
+  source_code_info_ = const_cast< ::google::protobuf::SourceCodeInfo*>(&::google::protobuf::SourceCodeInfo::default_instance());
 }
 
 FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from)
@@ -886,9 +944,10 @@
 
 void FileDescriptorProto::SharedCtor() {
   _cached_size_ = 0;
-  name_ = const_cast< ::std::string*>(&_default_name_);
-  package_ = const_cast< ::std::string*>(&_default_package_);
+  name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   options_ = NULL;
+  source_code_info_ = NULL;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -897,14 +956,15 @@
 }
 
 void FileDescriptorProto::SharedDtor() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     delete name_;
   }
-  if (package_ != &_default_package_) {
+  if (package_ != &::google::protobuf::internal::kEmptyString) {
     delete package_;
   }
   if (this != default_instance_) {
     delete options_;
+    delete source_code_info_;
   }
 }
 
@@ -930,20 +990,25 @@
 
 void FileDescriptorProto::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (name_ != &_default_name_) {
+    if (has_name()) {
+      if (name_ != &::google::protobuf::internal::kEmptyString) {
         name_->clear();
       }
     }
-    if (_has_bit(1)) {
-      if (package_ != &_default_package_) {
+    if (has_package()) {
+      if (package_ != &::google::protobuf::internal::kEmptyString) {
         package_->clear();
       }
     }
-    if (_has_bit(7)) {
+    if (has_options()) {
       if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
     }
   }
+  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    if (has_source_code_info()) {
+      if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear();
+    }
+  }
   dependency_.Clear();
   message_type_.Clear();
   enum_type_.Clear();
@@ -1080,6 +1145,20 @@
         } else {
           goto handle_uninterpreted;
         }
+        if (input->ExpectTag(74)) goto parse_source_code_info;
+        break;
+      }
+      
+      // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+      case 9: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_source_code_info:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_source_code_info()));
+        } else {
+          goto handle_uninterpreted;
+        }
         if (input->ExpectAtEnd()) return true;
         break;
       }
@@ -1103,7 +1182,7 @@
 void FileDescriptorProto::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -1112,7 +1191,7 @@
   }
   
   // optional string package = 2;
-  if (_has_bit(1)) {
+  if (has_package()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->package().data(), this->package().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -1154,11 +1233,17 @@
   }
   
   // optional .google.protobuf.FileOptions options = 8;
-  if (_has_bit(7)) {
+  if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       8, this->options(), output);
   }
   
+  // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+  if (has_source_code_info()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      9, this->source_code_info(), output);
+  }
+  
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
         unknown_fields(), output);
@@ -1168,7 +1253,7 @@
 ::google::protobuf::uint8* FileDescriptorProto::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -1178,7 +1263,7 @@
   }
   
   // optional string package = 2;
-  if (_has_bit(1)) {
+  if (has_package()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->package().data(), this->package().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -1225,12 +1310,19 @@
   }
   
   // optional .google.protobuf.FileOptions options = 8;
-  if (_has_bit(7)) {
+  if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         8, this->options(), target);
   }
   
+  // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+  if (has_source_code_info()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        9, this->source_code_info(), target);
+  }
+  
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -1264,6 +1356,15 @@
     }
     
   }
+  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+    if (has_source_code_info()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          this->source_code_info());
+    }
+    
+  }
   // repeated string dependency = 3;
   total_size += 1 * this->dependency_size();
   for (int i = 0; i < this->dependency_size(); i++) {
@@ -1334,16 +1435,21 @@
   service_.MergeFrom(from.service_);
   extension_.MergeFrom(from.extension_);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_name()) {
       set_name(from.name());
     }
-    if (from._has_bit(1)) {
+    if (from.has_package()) {
       set_package(from.package());
     }
-    if (from._has_bit(7)) {
+    if (from.has_options()) {
       mutable_options()->::google::protobuf::FileOptions::MergeFrom(from.options());
     }
   }
+  if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    if (from.has_source_code_info()) {
+      mutable_source_code_info()->::google::protobuf::SourceCodeInfo::MergeFrom(from.source_code_info());
+    }
+  }
   mutable_unknown_fields()->MergeFrom(from.unknown_fields());
 }
 
@@ -1389,6 +1495,7 @@
     service_.Swap(&other->service_);
     extension_.Swap(&other->extension_);
     std::swap(options_, other->options_);
+    std::swap(source_code_info_, other->source_code_info_);
     std::swap(_has_bits_[0], other->_has_bits_[0]);
     _unknown_fields_.Swap(&other->_unknown_fields_);
     std::swap(_cached_size_, other->_cached_size_);
@@ -1483,7 +1590,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                  input, &start_)));
-          _set_bit(0);
+          set_has_start();
         } else {
           goto handle_uninterpreted;
         }
@@ -1499,7 +1606,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                  input, &end_)));
-          _set_bit(1);
+          set_has_end();
         } else {
           goto handle_uninterpreted;
         }
@@ -1526,12 +1633,12 @@
 void DescriptorProto_ExtensionRange::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional int32 start = 1;
-  if (_has_bit(0)) {
+  if (has_start()) {
     ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output);
   }
   
   // optional int32 end = 2;
-  if (_has_bit(1)) {
+  if (has_end()) {
     ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->end(), output);
   }
   
@@ -1544,12 +1651,12 @@
 ::google::protobuf::uint8* DescriptorProto_ExtensionRange::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional int32 start = 1;
-  if (_has_bit(0)) {
+  if (has_start()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target);
   }
   
   // optional int32 end = 2;
-  if (_has_bit(1)) {
+  if (has_end()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->end(), target);
   }
   
@@ -1605,10 +1712,10 @@
 void DescriptorProto_ExtensionRange::MergeFrom(const DescriptorProto_ExtensionRange& from) {
   GOOGLE_CHECK_NE(&from, this);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_start()) {
       set_start(from.start());
     }
-    if (from._has_bit(1)) {
+    if (from.has_end()) {
       set_end(from.end());
     }
   }
@@ -1653,7 +1760,6 @@
 
 // -------------------------------------------------------------------
 
-const ::std::string DescriptorProto::_default_name_;
 #ifndef _MSC_VER
 const int DescriptorProto::kNameFieldNumber;
 const int DescriptorProto::kFieldFieldNumber;
@@ -1681,7 +1787,7 @@
 
 void DescriptorProto::SharedCtor() {
   _cached_size_ = 0;
-  name_ = const_cast< ::std::string*>(&_default_name_);
+  name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   options_ = NULL;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
@@ -1691,7 +1797,7 @@
 }
 
 void DescriptorProto::SharedDtor() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     delete name_;
   }
   if (this != default_instance_) {
@@ -1721,12 +1827,12 @@
 
 void DescriptorProto::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (name_ != &_default_name_) {
+    if (has_name()) {
+      if (name_ != &::google::protobuf::internal::kEmptyString) {
         name_->clear();
       }
     }
-    if (_has_bit(6)) {
+    if (has_options()) {
       if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear();
     }
   }
@@ -1869,7 +1975,7 @@
 void DescriptorProto::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -1908,7 +2014,7 @@
   }
   
   // optional .google.protobuf.MessageOptions options = 7;
-  if (_has_bit(6)) {
+  if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       7, this->options(), output);
   }
@@ -1922,7 +2028,7 @@
 ::google::protobuf::uint8* DescriptorProto::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -1967,7 +2073,7 @@
   }
   
   // optional .google.protobuf.MessageOptions options = 7;
-  if (_has_bit(6)) {
+  if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         7, this->options(), target);
@@ -2070,10 +2176,10 @@
   enum_type_.MergeFrom(from.enum_type_);
   extension_range_.MergeFrom(from.extension_range_);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_name()) {
       set_name(from.name());
     }
-    if (from._has_bit(6)) {
+    if (from.has_options()) {
       mutable_options()->::google::protobuf::MessageOptions::MergeFrom(from.options());
     }
   }
@@ -2214,10 +2320,6 @@
 const FieldDescriptorProto_Label FieldDescriptorProto::Label_MAX;
 const int FieldDescriptorProto::Label_ARRAYSIZE;
 #endif  // _MSC_VER
-const ::std::string FieldDescriptorProto::_default_name_;
-const ::std::string FieldDescriptorProto::_default_type_name_;
-const ::std::string FieldDescriptorProto::_default_extendee_;
-const ::std::string FieldDescriptorProto::_default_default_value_;
 #ifndef _MSC_VER
 const int FieldDescriptorProto::kNameFieldNumber;
 const int FieldDescriptorProto::kNumberFieldNumber;
@@ -2246,13 +2348,13 @@
 
 void FieldDescriptorProto::SharedCtor() {
   _cached_size_ = 0;
-  name_ = const_cast< ::std::string*>(&_default_name_);
+  name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   number_ = 0;
   label_ = 1;
   type_ = 1;
-  type_name_ = const_cast< ::std::string*>(&_default_type_name_);
-  extendee_ = const_cast< ::std::string*>(&_default_extendee_);
-  default_value_ = const_cast< ::std::string*>(&_default_default_value_);
+  type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   options_ = NULL;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
@@ -2262,16 +2364,16 @@
 }
 
 void FieldDescriptorProto::SharedDtor() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     delete name_;
   }
-  if (type_name_ != &_default_type_name_) {
+  if (type_name_ != &::google::protobuf::internal::kEmptyString) {
     delete type_name_;
   }
-  if (extendee_ != &_default_extendee_) {
+  if (extendee_ != &::google::protobuf::internal::kEmptyString) {
     delete extendee_;
   }
-  if (default_value_ != &_default_default_value_) {
+  if (default_value_ != &::google::protobuf::internal::kEmptyString) {
     delete default_value_;
   }
   if (this != default_instance_) {
@@ -2301,30 +2403,30 @@
 
 void FieldDescriptorProto::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (name_ != &_default_name_) {
+    if (has_name()) {
+      if (name_ != &::google::protobuf::internal::kEmptyString) {
         name_->clear();
       }
     }
     number_ = 0;
     label_ = 1;
     type_ = 1;
-    if (_has_bit(4)) {
-      if (type_name_ != &_default_type_name_) {
+    if (has_type_name()) {
+      if (type_name_ != &::google::protobuf::internal::kEmptyString) {
         type_name_->clear();
       }
     }
-    if (_has_bit(5)) {
-      if (extendee_ != &_default_extendee_) {
+    if (has_extendee()) {
+      if (extendee_ != &::google::protobuf::internal::kEmptyString) {
         extendee_->clear();
       }
     }
-    if (_has_bit(6)) {
-      if (default_value_ != &_default_default_value_) {
+    if (has_default_value()) {
+      if (default_value_ != &::google::protobuf::internal::kEmptyString) {
         default_value_->clear();
       }
     }
-    if (_has_bit(7)) {
+    if (has_options()) {
       if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
     }
   }
@@ -2379,7 +2481,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                  input, &number_)));
-          _set_bit(1);
+          set_has_number();
         } else {
           goto handle_uninterpreted;
         }
@@ -2496,7 +2598,7 @@
 void FieldDescriptorProto::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2505,7 +2607,7 @@
   }
   
   // optional string extendee = 2;
-  if (_has_bit(5)) {
+  if (has_extendee()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->extendee().data(), this->extendee().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2514,24 +2616,24 @@
   }
   
   // optional int32 number = 3;
-  if (_has_bit(1)) {
+  if (has_number()) {
     ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->number(), output);
   }
   
   // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
-  if (_has_bit(2)) {
+  if (has_label()) {
     ::google::protobuf::internal::WireFormatLite::WriteEnum(
       4, this->label(), output);
   }
   
   // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
-  if (_has_bit(3)) {
+  if (has_type()) {
     ::google::protobuf::internal::WireFormatLite::WriteEnum(
       5, this->type(), output);
   }
   
   // optional string type_name = 6;
-  if (_has_bit(4)) {
+  if (has_type_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->type_name().data(), this->type_name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2540,7 +2642,7 @@
   }
   
   // optional string default_value = 7;
-  if (_has_bit(6)) {
+  if (has_default_value()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->default_value().data(), this->default_value().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2549,7 +2651,7 @@
   }
   
   // optional .google.protobuf.FieldOptions options = 8;
-  if (_has_bit(7)) {
+  if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       8, this->options(), output);
   }
@@ -2563,7 +2665,7 @@
 ::google::protobuf::uint8* FieldDescriptorProto::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2573,7 +2675,7 @@
   }
   
   // optional string extendee = 2;
-  if (_has_bit(5)) {
+  if (has_extendee()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->extendee().data(), this->extendee().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2583,24 +2685,24 @@
   }
   
   // optional int32 number = 3;
-  if (_has_bit(1)) {
+  if (has_number()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->number(), target);
   }
   
   // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
-  if (_has_bit(2)) {
+  if (has_label()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
       4, this->label(), target);
   }
   
   // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
-  if (_has_bit(3)) {
+  if (has_type()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
       5, this->type(), target);
   }
   
   // optional string type_name = 6;
-  if (_has_bit(4)) {
+  if (has_type_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->type_name().data(), this->type_name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2610,7 +2712,7 @@
   }
   
   // optional string default_value = 7;
-  if (_has_bit(6)) {
+  if (has_default_value()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->default_value().data(), this->default_value().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2620,7 +2722,7 @@
   }
   
   // optional .google.protobuf.FieldOptions options = 8;
-  if (_has_bit(7)) {
+  if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         8, this->options(), target);
@@ -2718,28 +2820,28 @@
 void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) {
   GOOGLE_CHECK_NE(&from, this);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_name()) {
       set_name(from.name());
     }
-    if (from._has_bit(1)) {
+    if (from.has_number()) {
       set_number(from.number());
     }
-    if (from._has_bit(2)) {
+    if (from.has_label()) {
       set_label(from.label());
     }
-    if (from._has_bit(3)) {
+    if (from.has_type()) {
       set_type(from.type());
     }
-    if (from._has_bit(4)) {
+    if (from.has_type_name()) {
       set_type_name(from.type_name());
     }
-    if (from._has_bit(5)) {
+    if (from.has_extendee()) {
       set_extendee(from.extendee());
     }
-    if (from._has_bit(6)) {
+    if (from.has_default_value()) {
       set_default_value(from.default_value());
     }
-    if (from._has_bit(7)) {
+    if (from.has_options()) {
       mutable_options()->::google::protobuf::FieldOptions::MergeFrom(from.options());
     }
   }
@@ -2793,7 +2895,6 @@
 
 // ===================================================================
 
-const ::std::string EnumDescriptorProto::_default_name_;
 #ifndef _MSC_VER
 const int EnumDescriptorProto::kNameFieldNumber;
 const int EnumDescriptorProto::kValueFieldNumber;
@@ -2817,7 +2918,7 @@
 
 void EnumDescriptorProto::SharedCtor() {
   _cached_size_ = 0;
-  name_ = const_cast< ::std::string*>(&_default_name_);
+  name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   options_ = NULL;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
@@ -2827,7 +2928,7 @@
 }
 
 void EnumDescriptorProto::SharedDtor() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     delete name_;
   }
   if (this != default_instance_) {
@@ -2857,12 +2958,12 @@
 
 void EnumDescriptorProto::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (name_ != &_default_name_) {
+    if (has_name()) {
+      if (name_ != &::google::protobuf::internal::kEmptyString) {
         name_->clear();
       }
     }
-    if (_has_bit(2)) {
+    if (has_options()) {
       if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear();
     }
   }
@@ -2941,7 +3042,7 @@
 void EnumDescriptorProto::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2956,7 +3057,7 @@
   }
   
   // optional .google.protobuf.EnumOptions options = 3;
-  if (_has_bit(2)) {
+  if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       3, this->options(), output);
   }
@@ -2970,7 +3071,7 @@
 ::google::protobuf::uint8* EnumDescriptorProto::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -2987,7 +3088,7 @@
   }
   
   // optional .google.protobuf.EnumOptions options = 3;
-  if (_has_bit(2)) {
+  if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         3, this->options(), target);
@@ -3054,10 +3155,10 @@
   GOOGLE_CHECK_NE(&from, this);
   value_.MergeFrom(from.value_);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_name()) {
       set_name(from.name());
     }
-    if (from._has_bit(2)) {
+    if (from.has_options()) {
       mutable_options()->::google::protobuf::EnumOptions::MergeFrom(from.options());
     }
   }
@@ -3109,7 +3210,6 @@
 
 // ===================================================================
 
-const ::std::string EnumValueDescriptorProto::_default_name_;
 #ifndef _MSC_VER
 const int EnumValueDescriptorProto::kNameFieldNumber;
 const int EnumValueDescriptorProto::kNumberFieldNumber;
@@ -3133,7 +3233,7 @@
 
 void EnumValueDescriptorProto::SharedCtor() {
   _cached_size_ = 0;
-  name_ = const_cast< ::std::string*>(&_default_name_);
+  name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   number_ = 0;
   options_ = NULL;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -3144,7 +3244,7 @@
 }
 
 void EnumValueDescriptorProto::SharedDtor() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     delete name_;
   }
   if (this != default_instance_) {
@@ -3174,13 +3274,13 @@
 
 void EnumValueDescriptorProto::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (name_ != &_default_name_) {
+    if (has_name()) {
+      if (name_ != &::google::protobuf::internal::kEmptyString) {
         name_->clear();
       }
     }
     number_ = 0;
-    if (_has_bit(2)) {
+    if (has_options()) {
       if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear();
     }
   }
@@ -3218,7 +3318,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                  input, &number_)));
-          _set_bit(1);
+          set_has_number();
         } else {
           goto handle_uninterpreted;
         }
@@ -3259,7 +3359,7 @@
 void EnumValueDescriptorProto::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3268,12 +3368,12 @@
   }
   
   // optional int32 number = 2;
-  if (_has_bit(1)) {
+  if (has_number()) {
     ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->number(), output);
   }
   
   // optional .google.protobuf.EnumValueOptions options = 3;
-  if (_has_bit(2)) {
+  if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       3, this->options(), output);
   }
@@ -3287,7 +3387,7 @@
 ::google::protobuf::uint8* EnumValueDescriptorProto::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3297,12 +3397,12 @@
   }
   
   // optional int32 number = 2;
-  if (_has_bit(1)) {
+  if (has_number()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->number(), target);
   }
   
   // optional .google.protobuf.EnumValueOptions options = 3;
-  if (_has_bit(2)) {
+  if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         3, this->options(), target);
@@ -3367,13 +3467,13 @@
 void EnumValueDescriptorProto::MergeFrom(const EnumValueDescriptorProto& from) {
   GOOGLE_CHECK_NE(&from, this);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_name()) {
       set_name(from.name());
     }
-    if (from._has_bit(1)) {
+    if (from.has_number()) {
       set_number(from.number());
     }
-    if (from._has_bit(2)) {
+    if (from.has_options()) {
       mutable_options()->::google::protobuf::EnumValueOptions::MergeFrom(from.options());
     }
   }
@@ -3422,7 +3522,6 @@
 
 // ===================================================================
 
-const ::std::string ServiceDescriptorProto::_default_name_;
 #ifndef _MSC_VER
 const int ServiceDescriptorProto::kNameFieldNumber;
 const int ServiceDescriptorProto::kMethodFieldNumber;
@@ -3446,7 +3545,7 @@
 
 void ServiceDescriptorProto::SharedCtor() {
   _cached_size_ = 0;
-  name_ = const_cast< ::std::string*>(&_default_name_);
+  name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   options_ = NULL;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
@@ -3456,7 +3555,7 @@
 }
 
 void ServiceDescriptorProto::SharedDtor() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     delete name_;
   }
   if (this != default_instance_) {
@@ -3486,12 +3585,12 @@
 
 void ServiceDescriptorProto::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (name_ != &_default_name_) {
+    if (has_name()) {
+      if (name_ != &::google::protobuf::internal::kEmptyString) {
         name_->clear();
       }
     }
-    if (_has_bit(2)) {
+    if (has_options()) {
       if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear();
     }
   }
@@ -3570,7 +3669,7 @@
 void ServiceDescriptorProto::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3585,7 +3684,7 @@
   }
   
   // optional .google.protobuf.ServiceOptions options = 3;
-  if (_has_bit(2)) {
+  if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       3, this->options(), output);
   }
@@ -3599,7 +3698,7 @@
 ::google::protobuf::uint8* ServiceDescriptorProto::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3616,7 +3715,7 @@
   }
   
   // optional .google.protobuf.ServiceOptions options = 3;
-  if (_has_bit(2)) {
+  if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         3, this->options(), target);
@@ -3683,10 +3782,10 @@
   GOOGLE_CHECK_NE(&from, this);
   method_.MergeFrom(from.method_);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_name()) {
       set_name(from.name());
     }
-    if (from._has_bit(2)) {
+    if (from.has_options()) {
       mutable_options()->::google::protobuf::ServiceOptions::MergeFrom(from.options());
     }
   }
@@ -3738,9 +3837,6 @@
 
 // ===================================================================
 
-const ::std::string MethodDescriptorProto::_default_name_;
-const ::std::string MethodDescriptorProto::_default_input_type_;
-const ::std::string MethodDescriptorProto::_default_output_type_;
 #ifndef _MSC_VER
 const int MethodDescriptorProto::kNameFieldNumber;
 const int MethodDescriptorProto::kInputTypeFieldNumber;
@@ -3765,9 +3861,9 @@
 
 void MethodDescriptorProto::SharedCtor() {
   _cached_size_ = 0;
-  name_ = const_cast< ::std::string*>(&_default_name_);
-  input_type_ = const_cast< ::std::string*>(&_default_input_type_);
-  output_type_ = const_cast< ::std::string*>(&_default_output_type_);
+  name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   options_ = NULL;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
@@ -3777,13 +3873,13 @@
 }
 
 void MethodDescriptorProto::SharedDtor() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     delete name_;
   }
-  if (input_type_ != &_default_input_type_) {
+  if (input_type_ != &::google::protobuf::internal::kEmptyString) {
     delete input_type_;
   }
-  if (output_type_ != &_default_output_type_) {
+  if (output_type_ != &::google::protobuf::internal::kEmptyString) {
     delete output_type_;
   }
   if (this != default_instance_) {
@@ -3813,22 +3909,22 @@
 
 void MethodDescriptorProto::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (name_ != &_default_name_) {
+    if (has_name()) {
+      if (name_ != &::google::protobuf::internal::kEmptyString) {
         name_->clear();
       }
     }
-    if (_has_bit(1)) {
-      if (input_type_ != &_default_input_type_) {
+    if (has_input_type()) {
+      if (input_type_ != &::google::protobuf::internal::kEmptyString) {
         input_type_->clear();
       }
     }
-    if (_has_bit(2)) {
-      if (output_type_ != &_default_output_type_) {
+    if (has_output_type()) {
+      if (output_type_ != &::google::protobuf::internal::kEmptyString) {
         output_type_->clear();
       }
     }
-    if (_has_bit(3)) {
+    if (has_options()) {
       if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear();
     }
   }
@@ -3925,7 +4021,7 @@
 void MethodDescriptorProto::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3934,7 +4030,7 @@
   }
   
   // optional string input_type = 2;
-  if (_has_bit(1)) {
+  if (has_input_type()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->input_type().data(), this->input_type().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3943,7 +4039,7 @@
   }
   
   // optional string output_type = 3;
-  if (_has_bit(2)) {
+  if (has_output_type()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->output_type().data(), this->output_type().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3952,7 +4048,7 @@
   }
   
   // optional .google.protobuf.MethodOptions options = 4;
-  if (_has_bit(3)) {
+  if (has_options()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
       4, this->options(), output);
   }
@@ -3966,7 +4062,7 @@
 ::google::protobuf::uint8* MethodDescriptorProto::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string name = 1;
-  if (_has_bit(0)) {
+  if (has_name()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name().data(), this->name().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3976,7 +4072,7 @@
   }
   
   // optional string input_type = 2;
-  if (_has_bit(1)) {
+  if (has_input_type()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->input_type().data(), this->input_type().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3986,7 +4082,7 @@
   }
   
   // optional string output_type = 3;
-  if (_has_bit(2)) {
+  if (has_output_type()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->output_type().data(), this->output_type().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -3996,7 +4092,7 @@
   }
   
   // optional .google.protobuf.MethodOptions options = 4;
-  if (_has_bit(3)) {
+  if (has_options()) {
     target = ::google::protobuf::internal::WireFormatLite::
       WriteMessageNoVirtualToArray(
         4, this->options(), target);
@@ -4068,16 +4164,16 @@
 void MethodDescriptorProto::MergeFrom(const MethodDescriptorProto& from) {
   GOOGLE_CHECK_NE(&from, this);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_name()) {
       set_name(from.name());
     }
-    if (from._has_bit(1)) {
+    if (from.has_input_type()) {
       set_input_type(from.input_type());
     }
-    if (from._has_bit(2)) {
+    if (from.has_output_type()) {
       set_output_type(from.output_type());
     }
-    if (from._has_bit(3)) {
+    if (from.has_options()) {
       mutable_options()->::google::protobuf::MethodOptions::MergeFrom(from.options());
     }
   }
@@ -4150,12 +4246,11 @@
 const FileOptions_OptimizeMode FileOptions::OptimizeMode_MAX;
 const int FileOptions::OptimizeMode_ARRAYSIZE;
 #endif  // _MSC_VER
-const ::std::string FileOptions::_default_java_package_;
-const ::std::string FileOptions::_default_java_outer_classname_;
 #ifndef _MSC_VER
 const int FileOptions::kJavaPackageFieldNumber;
 const int FileOptions::kJavaOuterClassnameFieldNumber;
 const int FileOptions::kJavaMultipleFilesFieldNumber;
+const int FileOptions::kJavaGenerateEqualsAndHashFieldNumber;
 const int FileOptions::kOptimizeForFieldNumber;
 const int FileOptions::kCcGenericServicesFieldNumber;
 const int FileOptions::kJavaGenericServicesFieldNumber;
@@ -4179,13 +4274,14 @@
 
 void FileOptions::SharedCtor() {
   _cached_size_ = 0;
-  java_package_ = const_cast< ::std::string*>(&_default_java_package_);
-  java_outer_classname_ = const_cast< ::std::string*>(&_default_java_outer_classname_);
+  java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   java_multiple_files_ = false;
+  java_generate_equals_and_hash_ = false;
   optimize_for_ = 1;
-  cc_generic_services_ = true;
-  java_generic_services_ = true;
-  py_generic_services_ = true;
+  cc_generic_services_ = false;
+  java_generic_services_ = false;
+  py_generic_services_ = false;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -4194,10 +4290,10 @@
 }
 
 void FileOptions::SharedDtor() {
-  if (java_package_ != &_default_java_package_) {
+  if (java_package_ != &::google::protobuf::internal::kEmptyString) {
     delete java_package_;
   }
-  if (java_outer_classname_ != &_default_java_outer_classname_) {
+  if (java_outer_classname_ != &::google::protobuf::internal::kEmptyString) {
     delete java_outer_classname_;
   }
   if (this != default_instance_) {
@@ -4227,21 +4323,22 @@
 void FileOptions::Clear() {
   _extensions_.Clear();
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (java_package_ != &_default_java_package_) {
+    if (has_java_package()) {
+      if (java_package_ != &::google::protobuf::internal::kEmptyString) {
         java_package_->clear();
       }
     }
-    if (_has_bit(1)) {
-      if (java_outer_classname_ != &_default_java_outer_classname_) {
+    if (has_java_outer_classname()) {
+      if (java_outer_classname_ != &::google::protobuf::internal::kEmptyString) {
         java_outer_classname_->clear();
       }
     }
     java_multiple_files_ = false;
+    java_generate_equals_and_hash_ = false;
     optimize_for_ = 1;
-    cc_generic_services_ = true;
-    java_generic_services_ = true;
-    py_generic_services_ = true;
+    cc_generic_services_ = false;
+    java_generic_services_ = false;
+    py_generic_services_ = false;
   }
   uninterpreted_option_.Clear();
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -4316,7 +4413,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &java_multiple_files_)));
-          _set_bit(2);
+          set_has_java_multiple_files();
         } else {
           goto handle_uninterpreted;
         }
@@ -4324,7 +4421,7 @@
         break;
       }
       
-      // optional bool cc_generic_services = 16 [default = true];
+      // optional bool cc_generic_services = 16 [default = false];
       case 16: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
@@ -4332,7 +4429,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &cc_generic_services_)));
-          _set_bit(4);
+          set_has_cc_generic_services();
         } else {
           goto handle_uninterpreted;
         }
@@ -4340,7 +4437,7 @@
         break;
       }
       
-      // optional bool java_generic_services = 17 [default = true];
+      // optional bool java_generic_services = 17 [default = false];
       case 17: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
@@ -4348,7 +4445,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &java_generic_services_)));
-          _set_bit(5);
+          set_has_java_generic_services();
         } else {
           goto handle_uninterpreted;
         }
@@ -4356,7 +4453,7 @@
         break;
       }
       
-      // optional bool py_generic_services = 18 [default = true];
+      // optional bool py_generic_services = 18 [default = false];
       case 18: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
@@ -4364,7 +4461,23 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &py_generic_services_)));
-          _set_bit(6);
+          set_has_py_generic_services();
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(160)) goto parse_java_generate_equals_and_hash;
+        break;
+      }
+      
+      // optional bool java_generate_equals_and_hash = 20 [default = false];
+      case 20: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_java_generate_equals_and_hash:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &java_generate_equals_and_hash_)));
+          set_has_java_generate_equals_and_hash();
         } else {
           goto handle_uninterpreted;
         }
@@ -4411,7 +4524,7 @@
 void FileOptions::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional string java_package = 1;
-  if (_has_bit(0)) {
+  if (has_java_package()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->java_package().data(), this->java_package().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -4420,7 +4533,7 @@
   }
   
   // optional string java_outer_classname = 8;
-  if (_has_bit(1)) {
+  if (has_java_outer_classname()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->java_outer_classname().data(), this->java_outer_classname().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -4429,31 +4542,36 @@
   }
   
   // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
-  if (_has_bit(3)) {
+  if (has_optimize_for()) {
     ::google::protobuf::internal::WireFormatLite::WriteEnum(
       9, this->optimize_for(), output);
   }
   
   // optional bool java_multiple_files = 10 [default = false];
-  if (_has_bit(2)) {
+  if (has_java_multiple_files()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->java_multiple_files(), output);
   }
   
-  // optional bool cc_generic_services = 16 [default = true];
-  if (_has_bit(4)) {
+  // optional bool cc_generic_services = 16 [default = false];
+  if (has_cc_generic_services()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(16, this->cc_generic_services(), output);
   }
   
-  // optional bool java_generic_services = 17 [default = true];
-  if (_has_bit(5)) {
+  // optional bool java_generic_services = 17 [default = false];
+  if (has_java_generic_services()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(17, this->java_generic_services(), output);
   }
   
-  // optional bool py_generic_services = 18 [default = true];
-  if (_has_bit(6)) {
+  // optional bool py_generic_services = 18 [default = false];
+  if (has_py_generic_services()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(18, this->py_generic_services(), output);
   }
   
+  // optional bool java_generate_equals_and_hash = 20 [default = false];
+  if (has_java_generate_equals_and_hash()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(20, this->java_generate_equals_and_hash(), output);
+  }
+  
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
@@ -4473,7 +4591,7 @@
 ::google::protobuf::uint8* FileOptions::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional string java_package = 1;
-  if (_has_bit(0)) {
+  if (has_java_package()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->java_package().data(), this->java_package().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -4483,7 +4601,7 @@
   }
   
   // optional string java_outer_classname = 8;
-  if (_has_bit(1)) {
+  if (has_java_outer_classname()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->java_outer_classname().data(), this->java_outer_classname().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -4493,31 +4611,36 @@
   }
   
   // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
-  if (_has_bit(3)) {
+  if (has_optimize_for()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
       9, this->optimize_for(), target);
   }
   
   // optional bool java_multiple_files = 10 [default = false];
-  if (_has_bit(2)) {
+  if (has_java_multiple_files()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->java_multiple_files(), target);
   }
   
-  // optional bool cc_generic_services = 16 [default = true];
-  if (_has_bit(4)) {
+  // optional bool cc_generic_services = 16 [default = false];
+  if (has_cc_generic_services()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(16, this->cc_generic_services(), target);
   }
   
-  // optional bool java_generic_services = 17 [default = true];
-  if (_has_bit(5)) {
+  // optional bool java_generic_services = 17 [default = false];
+  if (has_java_generic_services()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(17, this->java_generic_services(), target);
   }
   
-  // optional bool py_generic_services = 18 [default = true];
-  if (_has_bit(6)) {
+  // optional bool py_generic_services = 18 [default = false];
+  if (has_py_generic_services()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(18, this->py_generic_services(), target);
   }
   
+  // optional bool java_generate_equals_and_hash = 20 [default = false];
+  if (has_java_generate_equals_and_hash()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(20, this->java_generate_equals_and_hash(), target);
+  }
+  
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   for (int i = 0; i < this->uninterpreted_option_size(); i++) {
     target = ::google::protobuf::internal::WireFormatLite::
@@ -4559,23 +4682,28 @@
       total_size += 1 + 1;
     }
     
+    // optional bool java_generate_equals_and_hash = 20 [default = false];
+    if (has_java_generate_equals_and_hash()) {
+      total_size += 2 + 1;
+    }
+    
     // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
     if (has_optimize_for()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::EnumSize(this->optimize_for());
     }
     
-    // optional bool cc_generic_services = 16 [default = true];
+    // optional bool cc_generic_services = 16 [default = false];
     if (has_cc_generic_services()) {
       total_size += 2 + 1;
     }
     
-    // optional bool java_generic_services = 17 [default = true];
+    // optional bool java_generic_services = 17 [default = false];
     if (has_java_generic_services()) {
       total_size += 2 + 1;
     }
     
-    // optional bool py_generic_services = 18 [default = true];
+    // optional bool py_generic_services = 18 [default = false];
     if (has_py_generic_services()) {
       total_size += 2 + 1;
     }
@@ -4618,25 +4746,28 @@
   GOOGLE_CHECK_NE(&from, this);
   uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_java_package()) {
       set_java_package(from.java_package());
     }
-    if (from._has_bit(1)) {
+    if (from.has_java_outer_classname()) {
       set_java_outer_classname(from.java_outer_classname());
     }
-    if (from._has_bit(2)) {
+    if (from.has_java_multiple_files()) {
       set_java_multiple_files(from.java_multiple_files());
     }
-    if (from._has_bit(3)) {
+    if (from.has_java_generate_equals_and_hash()) {
+      set_java_generate_equals_and_hash(from.java_generate_equals_and_hash());
+    }
+    if (from.has_optimize_for()) {
       set_optimize_for(from.optimize_for());
     }
-    if (from._has_bit(4)) {
+    if (from.has_cc_generic_services()) {
       set_cc_generic_services(from.cc_generic_services());
     }
-    if (from._has_bit(5)) {
+    if (from.has_java_generic_services()) {
       set_java_generic_services(from.java_generic_services());
     }
-    if (from._has_bit(6)) {
+    if (from.has_py_generic_services()) {
       set_py_generic_services(from.py_generic_services());
     }
   }
@@ -4670,6 +4801,7 @@
     std::swap(java_package_, other->java_package_);
     std::swap(java_outer_classname_, other->java_outer_classname_);
     std::swap(java_multiple_files_, other->java_multiple_files_);
+    std::swap(java_generate_equals_and_hash_, other->java_generate_equals_and_hash_);
     std::swap(optimize_for_, other->optimize_for_);
     std::swap(cc_generic_services_, other->cc_generic_services_);
     std::swap(java_generic_services_, other->java_generic_services_);
@@ -4773,7 +4905,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &message_set_wire_format_)));
-          _set_bit(0);
+          set_has_message_set_wire_format();
         } else {
           goto handle_uninterpreted;
         }
@@ -4789,7 +4921,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &no_standard_descriptor_accessor_)));
-          _set_bit(1);
+          set_has_no_standard_descriptor_accessor();
         } else {
           goto handle_uninterpreted;
         }
@@ -4836,12 +4968,12 @@
 void MessageOptions::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional bool message_set_wire_format = 1 [default = false];
-  if (_has_bit(0)) {
+  if (has_message_set_wire_format()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->message_set_wire_format(), output);
   }
   
   // optional bool no_standard_descriptor_accessor = 2 [default = false];
-  if (_has_bit(1)) {
+  if (has_no_standard_descriptor_accessor()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->no_standard_descriptor_accessor(), output);
   }
   
@@ -4864,12 +4996,12 @@
 ::google::protobuf::uint8* MessageOptions::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional bool message_set_wire_format = 1 [default = false];
-  if (_has_bit(0)) {
+  if (has_message_set_wire_format()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->message_set_wire_format(), target);
   }
   
   // optional bool no_standard_descriptor_accessor = 2 [default = false];
-  if (_has_bit(1)) {
+  if (has_no_standard_descriptor_accessor()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->no_standard_descriptor_accessor(), target);
   }
   
@@ -4943,10 +5075,10 @@
   GOOGLE_CHECK_NE(&from, this);
   uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_message_set_wire_format()) {
       set_message_set_wire_format(from.message_set_wire_format());
     }
-    if (from._has_bit(1)) {
+    if (from.has_no_standard_descriptor_accessor()) {
       set_no_standard_descriptor_accessor(from.no_standard_descriptor_accessor());
     }
   }
@@ -5021,7 +5153,6 @@
 const FieldOptions_CType FieldOptions::CType_MAX;
 const int FieldOptions::CType_ARRAYSIZE;
 #endif  // _MSC_VER
-const ::std::string FieldOptions::_default_experimental_map_key_;
 #ifndef _MSC_VER
 const int FieldOptions::kCtypeFieldNumber;
 const int FieldOptions::kPackedFieldNumber;
@@ -5049,7 +5180,7 @@
   ctype_ = 0;
   packed_ = false;
   deprecated_ = false;
-  experimental_map_key_ = const_cast< ::std::string*>(&_default_experimental_map_key_);
+  experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -5058,7 +5189,7 @@
 }
 
 void FieldOptions::SharedDtor() {
-  if (experimental_map_key_ != &_default_experimental_map_key_) {
+  if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) {
     delete experimental_map_key_;
   }
   if (this != default_instance_) {
@@ -5091,8 +5222,8 @@
     ctype_ = 0;
     packed_ = false;
     deprecated_ = false;
-    if (_has_bit(3)) {
-      if (experimental_map_key_ != &_default_experimental_map_key_) {
+    if (has_experimental_map_key()) {
+      if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) {
         experimental_map_key_->clear();
       }
     }
@@ -5136,7 +5267,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &packed_)));
-          _set_bit(1);
+          set_has_packed();
         } else {
           goto handle_uninterpreted;
         }
@@ -5152,7 +5283,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &deprecated_)));
-          _set_bit(2);
+          set_has_deprecated();
         } else {
           goto handle_uninterpreted;
         }
@@ -5216,23 +5347,23 @@
 void FieldOptions::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
-  if (_has_bit(0)) {
+  if (has_ctype()) {
     ::google::protobuf::internal::WireFormatLite::WriteEnum(
       1, this->ctype(), output);
   }
   
   // optional bool packed = 2;
-  if (_has_bit(1)) {
+  if (has_packed()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->packed(), output);
   }
   
   // optional bool deprecated = 3 [default = false];
-  if (_has_bit(2)) {
+  if (has_deprecated()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output);
   }
   
   // optional string experimental_map_key = 9;
-  if (_has_bit(3)) {
+  if (has_experimental_map_key()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->experimental_map_key().data(), this->experimental_map_key().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -5259,23 +5390,23 @@
 ::google::protobuf::uint8* FieldOptions::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
-  if (_has_bit(0)) {
+  if (has_ctype()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
       1, this->ctype(), target);
   }
   
   // optional bool packed = 2;
-  if (_has_bit(1)) {
+  if (has_packed()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->packed(), target);
   }
   
   // optional bool deprecated = 3 [default = false];
-  if (_has_bit(2)) {
+  if (has_deprecated()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target);
   }
   
   // optional string experimental_map_key = 9;
-  if (_has_bit(3)) {
+  if (has_experimental_map_key()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->experimental_map_key().data(), this->experimental_map_key().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -5367,16 +5498,16 @@
   GOOGLE_CHECK_NE(&from, this);
   uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_ctype()) {
       set_ctype(from.ctype());
     }
-    if (from._has_bit(1)) {
+    if (from.has_packed()) {
       set_packed(from.packed());
     }
-    if (from._has_bit(2)) {
+    if (from.has_deprecated()) {
       set_deprecated(from.deprecated());
     }
-    if (from._has_bit(3)) {
+    if (from.has_experimental_map_key()) {
       set_experimental_map_key(from.experimental_map_key());
     }
   }
@@ -6326,7 +6457,6 @@
 
 // ===================================================================
 
-const ::std::string UninterpretedOption_NamePart::_default_name_part_;
 #ifndef _MSC_VER
 const int UninterpretedOption_NamePart::kNamePartFieldNumber;
 const int UninterpretedOption_NamePart::kIsExtensionFieldNumber;
@@ -6348,7 +6478,7 @@
 
 void UninterpretedOption_NamePart::SharedCtor() {
   _cached_size_ = 0;
-  name_part_ = const_cast< ::std::string*>(&_default_name_part_);
+  name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   is_extension_ = false;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
@@ -6358,7 +6488,7 @@
 }
 
 void UninterpretedOption_NamePart::SharedDtor() {
-  if (name_part_ != &_default_name_part_) {
+  if (name_part_ != &::google::protobuf::internal::kEmptyString) {
     delete name_part_;
   }
   if (this != default_instance_) {
@@ -6387,8 +6517,8 @@
 
 void UninterpretedOption_NamePart::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (_has_bit(0)) {
-      if (name_part_ != &_default_name_part_) {
+    if (has_name_part()) {
+      if (name_part_ != &::google::protobuf::internal::kEmptyString) {
         name_part_->clear();
       }
     }
@@ -6428,7 +6558,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                  input, &is_extension_)));
-          _set_bit(1);
+          set_has_is_extension();
         } else {
           goto handle_uninterpreted;
         }
@@ -6455,7 +6585,7 @@
 void UninterpretedOption_NamePart::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // required string name_part = 1;
-  if (_has_bit(0)) {
+  if (has_name_part()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name_part().data(), this->name_part().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -6464,7 +6594,7 @@
   }
   
   // required bool is_extension = 2;
-  if (_has_bit(1)) {
+  if (has_is_extension()) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->is_extension(), output);
   }
   
@@ -6477,7 +6607,7 @@
 ::google::protobuf::uint8* UninterpretedOption_NamePart::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
   // required string name_part = 1;
-  if (_has_bit(0)) {
+  if (has_name_part()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->name_part().data(), this->name_part().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -6487,7 +6617,7 @@
   }
   
   // required bool is_extension = 2;
-  if (_has_bit(1)) {
+  if (has_is_extension()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->is_extension(), target);
   }
   
@@ -6541,10 +6671,10 @@
 void UninterpretedOption_NamePart::MergeFrom(const UninterpretedOption_NamePart& from) {
   GOOGLE_CHECK_NE(&from, this);
   if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from._has_bit(0)) {
+    if (from.has_name_part()) {
       set_name_part(from.name_part());
     }
-    if (from._has_bit(1)) {
+    if (from.has_is_extension()) {
       set_is_extension(from.is_extension());
     }
   }
@@ -6590,8 +6720,6 @@
 
 // -------------------------------------------------------------------
 
-const ::std::string UninterpretedOption::_default_identifier_value_;
-const ::std::string UninterpretedOption::_default_string_value_;
 #ifndef _MSC_VER
 const int UninterpretedOption::kNameFieldNumber;
 const int UninterpretedOption::kIdentifierValueFieldNumber;
@@ -6599,6 +6727,7 @@
 const int UninterpretedOption::kNegativeIntValueFieldNumber;
 const int UninterpretedOption::kDoubleValueFieldNumber;
 const int UninterpretedOption::kStringValueFieldNumber;
+const int UninterpretedOption::kAggregateValueFieldNumber;
 #endif  // !_MSC_VER
 
 UninterpretedOption::UninterpretedOption()
@@ -6617,11 +6746,12 @@
 
 void UninterpretedOption::SharedCtor() {
   _cached_size_ = 0;
-  identifier_value_ = const_cast< ::std::string*>(&_default_identifier_value_);
+  identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   positive_int_value_ = GOOGLE_ULONGLONG(0);
   negative_int_value_ = GOOGLE_LONGLONG(0);
   double_value_ = 0;
-  string_value_ = const_cast< ::std::string*>(&_default_string_value_);
+  string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+  aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -6630,12 +6760,15 @@
 }
 
 void UninterpretedOption::SharedDtor() {
-  if (identifier_value_ != &_default_identifier_value_) {
+  if (identifier_value_ != &::google::protobuf::internal::kEmptyString) {
     delete identifier_value_;
   }
-  if (string_value_ != &_default_string_value_) {
+  if (string_value_ != &::google::protobuf::internal::kEmptyString) {
     delete string_value_;
   }
+  if (aggregate_value_ != &::google::protobuf::internal::kEmptyString) {
+    delete aggregate_value_;
+  }
   if (this != default_instance_) {
   }
 }
@@ -6662,19 +6795,24 @@
 
 void UninterpretedOption::Clear() {
   if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
-    if (_has_bit(1)) {
-      if (identifier_value_ != &_default_identifier_value_) {
+    if (has_identifier_value()) {
+      if (identifier_value_ != &::google::protobuf::internal::kEmptyString) {
         identifier_value_->clear();
       }
     }
     positive_int_value_ = GOOGLE_ULONGLONG(0);
     negative_int_value_ = GOOGLE_LONGLONG(0);
     double_value_ = 0;
-    if (_has_bit(5)) {
-      if (string_value_ != &_default_string_value_) {
+    if (has_string_value()) {
+      if (string_value_ != &::google::protobuf::internal::kEmptyString) {
         string_value_->clear();
       }
     }
+    if (has_aggregate_value()) {
+      if (aggregate_value_ != &::google::protobuf::internal::kEmptyString) {
+        aggregate_value_->clear();
+      }
+    }
   }
   name_.Clear();
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -6727,7 +6865,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
                  input, &positive_int_value_)));
-          _set_bit(2);
+          set_has_positive_int_value();
         } else {
           goto handle_uninterpreted;
         }
@@ -6743,7 +6881,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
                  input, &negative_int_value_)));
-          _set_bit(3);
+          set_has_negative_int_value();
         } else {
           goto handle_uninterpreted;
         }
@@ -6759,7 +6897,7 @@
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>(
                  input, &double_value_)));
-          _set_bit(4);
+          set_has_double_value();
         } else {
           goto handle_uninterpreted;
         }
@@ -6777,6 +6915,23 @@
         } else {
           goto handle_uninterpreted;
         }
+        if (input->ExpectTag(66)) goto parse_aggregate_value;
+        break;
+      }
+      
+      // optional string aggregate_value = 8;
+      case 8: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_aggregate_value:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_aggregate_value()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+            this->aggregate_value().data(), this->aggregate_value().length(),
+            ::google::protobuf::internal::WireFormat::PARSE);
+        } else {
+          goto handle_uninterpreted;
+        }
         if (input->ExpectAtEnd()) return true;
         break;
       }
@@ -6806,7 +6961,7 @@
   }
   
   // optional string identifier_value = 3;
-  if (_has_bit(1)) {
+  if (has_identifier_value()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->identifier_value().data(), this->identifier_value().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -6815,26 +6970,35 @@
   }
   
   // optional uint64 positive_int_value = 4;
-  if (_has_bit(2)) {
+  if (has_positive_int_value()) {
     ::google::protobuf::internal::WireFormatLite::WriteUInt64(4, this->positive_int_value(), output);
   }
   
   // optional int64 negative_int_value = 5;
-  if (_has_bit(3)) {
+  if (has_negative_int_value()) {
     ::google::protobuf::internal::WireFormatLite::WriteInt64(5, this->negative_int_value(), output);
   }
   
   // optional double double_value = 6;
-  if (_has_bit(4)) {
+  if (has_double_value()) {
     ::google::protobuf::internal::WireFormatLite::WriteDouble(6, this->double_value(), output);
   }
   
   // optional bytes string_value = 7;
-  if (_has_bit(5)) {
+  if (has_string_value()) {
     ::google::protobuf::internal::WireFormatLite::WriteBytes(
       7, this->string_value(), output);
   }
   
+  // optional string aggregate_value = 8;
+  if (has_aggregate_value()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->aggregate_value().data(), this->aggregate_value().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      8, this->aggregate_value(), output);
+  }
+  
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
         unknown_fields(), output);
@@ -6851,7 +7015,7 @@
   }
   
   // optional string identifier_value = 3;
-  if (_has_bit(1)) {
+  if (has_identifier_value()) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8String(
       this->identifier_value().data(), this->identifier_value().length(),
       ::google::protobuf::internal::WireFormat::SERIALIZE);
@@ -6861,27 +7025,37 @@
   }
   
   // optional uint64 positive_int_value = 4;
-  if (_has_bit(2)) {
+  if (has_positive_int_value()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(4, this->positive_int_value(), target);
   }
   
   // optional int64 negative_int_value = 5;
-  if (_has_bit(3)) {
+  if (has_negative_int_value()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(5, this->negative_int_value(), target);
   }
   
   // optional double double_value = 6;
-  if (_has_bit(4)) {
+  if (has_double_value()) {
     target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(6, this->double_value(), target);
   }
   
   // optional bytes string_value = 7;
-  if (_has_bit(5)) {
+  if (has_string_value()) {
     target =
       ::google::protobuf::internal::WireFormatLite::WriteBytesToArray(
         7, this->string_value(), target);
   }
   
+  // optional string aggregate_value = 8;
+  if (has_aggregate_value()) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->aggregate_value().data(), this->aggregate_value().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        8, this->aggregate_value(), target);
+  }
+  
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -6926,6 +7100,13 @@
           this->string_value());
     }
     
+    // optional string aggregate_value = 8;
+    if (has_aggregate_value()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->aggregate_value());
+    }
+    
   }
   // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
   total_size += 1 * this->name_size();
@@ -6962,21 +7143,24 @@
   GOOGLE_CHECK_NE(&from, this);
   name_.MergeFrom(from.name_);
   if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
-    if (from._has_bit(1)) {
+    if (from.has_identifier_value()) {
       set_identifier_value(from.identifier_value());
     }
-    if (from._has_bit(2)) {
+    if (from.has_positive_int_value()) {
       set_positive_int_value(from.positive_int_value());
     }
-    if (from._has_bit(3)) {
+    if (from.has_negative_int_value()) {
       set_negative_int_value(from.negative_int_value());
     }
-    if (from._has_bit(4)) {
+    if (from.has_double_value()) {
       set_double_value(from.double_value());
     }
-    if (from._has_bit(5)) {
+    if (from.has_string_value()) {
       set_string_value(from.string_value());
     }
+    if (from.has_aggregate_value()) {
+      set_aggregate_value(from.aggregate_value());
+    }
   }
   mutable_unknown_fields()->MergeFrom(from.unknown_fields());
 }
@@ -7009,6 +7193,7 @@
     std::swap(negative_int_value_, other->negative_int_value_);
     std::swap(double_value_, other->double_value_);
     std::swap(string_value_, other->string_value_);
+    std::swap(aggregate_value_, other->aggregate_value_);
     std::swap(_has_bits_[0], other->_has_bits_[0]);
     _unknown_fields_.Swap(&other->_unknown_fields_);
     std::swap(_cached_size_, other->_cached_size_);
@@ -7024,6 +7209,497 @@
 }
 
 
+// ===================================================================
+
+#ifndef _MSC_VER
+const int SourceCodeInfo_Location::kPathFieldNumber;
+const int SourceCodeInfo_Location::kSpanFieldNumber;
+#endif  // !_MSC_VER
+
+SourceCodeInfo_Location::SourceCodeInfo_Location()
+  : ::google::protobuf::Message() {
+  SharedCtor();
+}
+
+void SourceCodeInfo_Location::InitAsDefaultInstance() {
+}
+
+SourceCodeInfo_Location::SourceCodeInfo_Location(const SourceCodeInfo_Location& from)
+  : ::google::protobuf::Message() {
+  SharedCtor();
+  MergeFrom(from);
+}
+
+void SourceCodeInfo_Location::SharedCtor() {
+  _cached_size_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+SourceCodeInfo_Location::~SourceCodeInfo_Location() {
+  SharedDtor();
+}
+
+void SourceCodeInfo_Location::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void SourceCodeInfo_Location::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* SourceCodeInfo_Location::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return SourceCodeInfo_Location_descriptor_;
+}
+
+const SourceCodeInfo_Location& SourceCodeInfo_Location::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();  return *default_instance_;
+}
+
+SourceCodeInfo_Location* SourceCodeInfo_Location::default_instance_ = NULL;
+
+SourceCodeInfo_Location* SourceCodeInfo_Location::New() const {
+  return new SourceCodeInfo_Location;
+}
+
+void SourceCodeInfo_Location::Clear() {
+  path_.Clear();
+  span_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->Clear();
+}
+
+bool SourceCodeInfo_Location::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+  ::google::protobuf::uint32 tag;
+  while ((tag = input->ReadTag()) != 0) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated int32 path = 1 [packed = true];
+      case 1: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, this->mutable_path())));
+        } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)
+                   == ::google::protobuf::internal::WireFormatLite::
+                      WIRETYPE_VARINT) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 1, 10, input, this->mutable_path())));
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(18)) goto parse_span;
+        break;
+      }
+      
+      // repeated int32 span = 2 [packed = true];
+      case 2: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_span:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, this->mutable_span())));
+        } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)
+                   == ::google::protobuf::internal::WireFormatLite::
+                      WIRETYPE_VARINT) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 1, 18, input, this->mutable_span())));
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectAtEnd()) return true;
+        break;
+      }
+      
+      default: {
+      handle_uninterpreted:
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          return true;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+  return true;
+#undef DO_
+}
+
+void SourceCodeInfo_Location::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // repeated int32 path = 1 [packed = true];
+  if (this->path_size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteTag(1, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
+    output->WriteVarint32(_path_cached_byte_size_);
+  }
+  for (int i = 0; i < this->path_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag(
+      this->path(i), output);
+  }
+  
+  // repeated int32 span = 2 [packed = true];
+  if (this->span_size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteTag(2, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
+    output->WriteVarint32(_span_cached_byte_size_);
+  }
+  for (int i = 0; i < this->span_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag(
+      this->span(i), output);
+  }
+  
+  if (!unknown_fields().empty()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+}
+
+::google::protobuf::uint8* SourceCodeInfo_Location::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // repeated int32 path = 1 [packed = true];
+  if (this->path_size() > 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(
+      1,
+      ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
+      target);
+    target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(
+      _path_cached_byte_size_, target);
+  }
+  for (int i = 0; i < this->path_size(); i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteInt32NoTagToArray(this->path(i), target);
+  }
+  
+  // repeated int32 span = 2 [packed = true];
+  if (this->span_size() > 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(
+      2,
+      ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
+      target);
+    target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(
+      _span_cached_byte_size_, target);
+  }
+  for (int i = 0; i < this->span_size(); i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteInt32NoTagToArray(this->span(i), target);
+  }
+  
+  if (!unknown_fields().empty()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  return target;
+}
+
+int SourceCodeInfo_Location::ByteSize() const {
+  int total_size = 0;
+  
+  // repeated int32 path = 1 [packed = true];
+  {
+    int data_size = 0;
+    for (int i = 0; i < this->path_size(); i++) {
+      data_size += ::google::protobuf::internal::WireFormatLite::
+        Int32Size(this->path(i));
+    }
+    if (data_size > 0) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);
+    }
+    _path_cached_byte_size_ = data_size;
+    total_size += data_size;
+  }
+  
+  // repeated int32 span = 2 [packed = true];
+  {
+    int data_size = 0;
+    for (int i = 0; i < this->span_size(); i++) {
+      data_size += ::google::protobuf::internal::WireFormatLite::
+        Int32Size(this->span(i));
+    }
+    if (data_size > 0) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);
+    }
+    _span_cached_byte_size_ = data_size;
+    total_size += data_size;
+  }
+  
+  if (!unknown_fields().empty()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void SourceCodeInfo_Location::MergeFrom(const ::google::protobuf::Message& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  const SourceCodeInfo_Location* source =
+    ::google::protobuf::internal::dynamic_cast_if_available<const SourceCodeInfo_Location*>(
+      &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  path_.MergeFrom(from.path_);
+  span_.MergeFrom(from.span_);
+  mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+}
+
+void SourceCodeInfo_Location::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void SourceCodeInfo_Location::CopyFrom(const SourceCodeInfo_Location& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool SourceCodeInfo_Location::IsInitialized() const {
+  
+  return true;
+}
+
+void SourceCodeInfo_Location::Swap(SourceCodeInfo_Location* other) {
+  if (other != this) {
+    path_.Swap(&other->path_);
+    span_.Swap(&other->span_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.Swap(&other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::google::protobuf::Metadata SourceCodeInfo_Location::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = SourceCodeInfo_Location_descriptor_;
+  metadata.reflection = SourceCodeInfo_Location_reflection_;
+  return metadata;
+}
+
+
+// -------------------------------------------------------------------
+
+#ifndef _MSC_VER
+const int SourceCodeInfo::kLocationFieldNumber;
+#endif  // !_MSC_VER
+
+SourceCodeInfo::SourceCodeInfo()
+  : ::google::protobuf::Message() {
+  SharedCtor();
+}
+
+void SourceCodeInfo::InitAsDefaultInstance() {
+}
+
+SourceCodeInfo::SourceCodeInfo(const SourceCodeInfo& from)
+  : ::google::protobuf::Message() {
+  SharedCtor();
+  MergeFrom(from);
+}
+
+void SourceCodeInfo::SharedCtor() {
+  _cached_size_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+SourceCodeInfo::~SourceCodeInfo() {
+  SharedDtor();
+}
+
+void SourceCodeInfo::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void SourceCodeInfo::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* SourceCodeInfo::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return SourceCodeInfo_descriptor_;
+}
+
+const SourceCodeInfo& SourceCodeInfo::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();  return *default_instance_;
+}
+
+SourceCodeInfo* SourceCodeInfo::default_instance_ = NULL;
+
+SourceCodeInfo* SourceCodeInfo::New() const {
+  return new SourceCodeInfo;
+}
+
+void SourceCodeInfo::Clear() {
+  location_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->Clear();
+}
+
+bool SourceCodeInfo::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+  ::google::protobuf::uint32 tag;
+  while ((tag = input->ReadTag()) != 0) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+      case 1: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_location:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+                input, add_location()));
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(10)) goto parse_location;
+        if (input->ExpectAtEnd()) return true;
+        break;
+      }
+      
+      default: {
+      handle_uninterpreted:
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          return true;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+  return true;
+#undef DO_
+}
+
+void SourceCodeInfo::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+  for (int i = 0; i < this->location_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, this->location(i), output);
+  }
+  
+  if (!unknown_fields().empty()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+}
+
+::google::protobuf::uint8* SourceCodeInfo::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+  for (int i = 0; i < this->location_size(); i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        1, this->location(i), target);
+  }
+  
+  if (!unknown_fields().empty()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  return target;
+}
+
+int SourceCodeInfo::ByteSize() const {
+  int total_size = 0;
+  
+  // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+  total_size += 1 * this->location_size();
+  for (int i = 0; i < this->location_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->location(i));
+  }
+  
+  if (!unknown_fields().empty()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void SourceCodeInfo::MergeFrom(const ::google::protobuf::Message& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  const SourceCodeInfo* source =
+    ::google::protobuf::internal::dynamic_cast_if_available<const SourceCodeInfo*>(
+      &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void SourceCodeInfo::MergeFrom(const SourceCodeInfo& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  location_.MergeFrom(from.location_);
+  mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+}
+
+void SourceCodeInfo::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void SourceCodeInfo::CopyFrom(const SourceCodeInfo& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool SourceCodeInfo::IsInitialized() const {
+  
+  return true;
+}
+
+void SourceCodeInfo::Swap(SourceCodeInfo* other) {
+  if (other != this) {
+    location_.Swap(&other->location_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.Swap(&other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::google::protobuf::Metadata SourceCodeInfo::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = SourceCodeInfo_descriptor_;
+  metadata.reflection = SourceCodeInfo_reflection_;
+  return metadata;
+}
+
+
 // @@protoc_insertion_point(namespace_scope)
 
 }  // namespace protobuf
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 205c547..e85a933 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -51,6 +51,8 @@
 class MethodOptions;
 class UninterpretedOption;
 class UninterpretedOption_NamePart;
+class SourceCodeInfo;
+class SourceCodeInfo_Location;
 
 enum FieldDescriptorProto_Type {
   FieldDescriptorProto_Type_TYPE_DOUBLE = 1,
@@ -217,27 +219,18 @@
   
   // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet)
  private:
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > file_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static FileDescriptorSet* default_instance_;
 };
@@ -306,6 +299,7 @@
   inline void set_name(const char* value);
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
+  inline ::std::string* release_name();
   
   // optional string package = 2;
   inline bool has_package() const;
@@ -316,6 +310,7 @@
   inline void set_package(const char* value);
   inline void set_package(const char* value, size_t size);
   inline ::std::string* mutable_package();
+  inline ::std::string* release_package();
   
   // repeated string dependency = 3;
   inline int dependency_size() const;
@@ -387,39 +382,46 @@
   static const int kOptionsFieldNumber = 8;
   inline const ::google::protobuf::FileOptions& options() const;
   inline ::google::protobuf::FileOptions* mutable_options();
+  inline ::google::protobuf::FileOptions* release_options();
+  
+  // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+  inline bool has_source_code_info() const;
+  inline void clear_source_code_info();
+  static const int kSourceCodeInfoFieldNumber = 9;
+  inline const ::google::protobuf::SourceCodeInfo& source_code_info() const;
+  inline ::google::protobuf::SourceCodeInfo* mutable_source_code_info();
+  inline ::google::protobuf::SourceCodeInfo* release_source_code_info();
   
   // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto)
  private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_package();
+  inline void clear_has_package();
+  inline void set_has_options();
+  inline void clear_has_options();
+  inline void set_has_source_code_info();
+  inline void clear_has_source_code_info();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* name_;
-  static const ::std::string _default_name_;
   ::std::string* package_;
-  static const ::std::string _default_package_;
   ::google::protobuf::RepeatedPtrField< ::std::string> dependency_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > message_type_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto > service_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_;
   ::google::protobuf::FileOptions* options_;
+  ::google::protobuf::SourceCodeInfo* source_code_info_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(9 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static FileDescriptorProto* default_instance_;
 };
@@ -495,28 +497,23 @@
   
   // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange)
  private:
+  inline void set_has_start();
+  inline void clear_has_start();
+  inline void set_has_end();
+  inline void clear_has_end();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::google::protobuf::int32 start_;
   ::google::protobuf::int32 end_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static DescriptorProto_ExtensionRange* default_instance_;
 };
@@ -587,6 +584,7 @@
   inline void set_name(const char* value);
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
+  inline ::std::string* release_name();
   
   // repeated .google.protobuf.FieldDescriptorProto field = 2;
   inline int field_size() const;
@@ -654,37 +652,32 @@
   static const int kOptionsFieldNumber = 7;
   inline const ::google::protobuf::MessageOptions& options() const;
   inline ::google::protobuf::MessageOptions* mutable_options();
+  inline ::google::protobuf::MessageOptions* release_options();
   
   // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto)
  private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_options();
+  inline void clear_has_options();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* name_;
-  static const ::std::string _default_name_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > field_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > nested_type_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange > extension_range_;
   ::google::protobuf::MessageOptions* options_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static DescriptorProto* default_instance_;
 };
@@ -818,6 +811,7 @@
   inline void set_name(const char* value);
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
+  inline ::std::string* release_name();
   
   // optional int32 number = 3;
   inline bool has_number() const;
@@ -849,6 +843,7 @@
   inline void set_type_name(const char* value);
   inline void set_type_name(const char* value, size_t size);
   inline ::std::string* mutable_type_name();
+  inline ::std::string* release_type_name();
   
   // optional string extendee = 2;
   inline bool has_extendee() const;
@@ -859,6 +854,7 @@
   inline void set_extendee(const char* value);
   inline void set_extendee(const char* value, size_t size);
   inline ::std::string* mutable_extendee();
+  inline ::std::string* release_extendee();
   
   // optional string default_value = 7;
   inline bool has_default_value() const;
@@ -869,6 +865,7 @@
   inline void set_default_value(const char* value);
   inline void set_default_value(const char* value, size_t size);
   inline ::std::string* mutable_default_value();
+  inline ::std::string* release_default_value();
   
   // optional .google.protobuf.FieldOptions options = 8;
   inline bool has_options() const;
@@ -876,41 +873,45 @@
   static const int kOptionsFieldNumber = 8;
   inline const ::google::protobuf::FieldOptions& options() const;
   inline ::google::protobuf::FieldOptions* mutable_options();
+  inline ::google::protobuf::FieldOptions* release_options();
   
   // @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto)
  private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_number();
+  inline void clear_has_number();
+  inline void set_has_label();
+  inline void clear_has_label();
+  inline void set_has_type();
+  inline void clear_has_type();
+  inline void set_has_type_name();
+  inline void clear_has_type_name();
+  inline void set_has_extendee();
+  inline void clear_has_extendee();
+  inline void set_has_default_value();
+  inline void clear_has_default_value();
+  inline void set_has_options();
+  inline void clear_has_options();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* name_;
-  static const ::std::string _default_name_;
   ::google::protobuf::int32 number_;
   int label_;
-  int type_;
   ::std::string* type_name_;
-  static const ::std::string _default_type_name_;
   ::std::string* extendee_;
-  static const ::std::string _default_extendee_;
   ::std::string* default_value_;
-  static const ::std::string _default_default_value_;
   ::google::protobuf::FieldOptions* options_;
+  int type_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static FieldDescriptorProto* default_instance_;
 };
@@ -979,6 +980,7 @@
   inline void set_name(const char* value);
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
+  inline ::std::string* release_name();
   
   // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
   inline int value_size() const;
@@ -998,33 +1000,28 @@
   static const int kOptionsFieldNumber = 3;
   inline const ::google::protobuf::EnumOptions& options() const;
   inline ::google::protobuf::EnumOptions* mutable_options();
+  inline ::google::protobuf::EnumOptions* release_options();
   
   // @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto)
  private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_options();
+  inline void clear_has_options();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* name_;
-  static const ::std::string _default_name_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto > value_;
   ::google::protobuf::EnumOptions* options_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static EnumDescriptorProto* default_instance_;
 };
@@ -1093,6 +1090,7 @@
   inline void set_name(const char* value);
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
+  inline ::std::string* release_name();
   
   // optional int32 number = 2;
   inline bool has_number() const;
@@ -1107,33 +1105,30 @@
   static const int kOptionsFieldNumber = 3;
   inline const ::google::protobuf::EnumValueOptions& options() const;
   inline ::google::protobuf::EnumValueOptions* mutable_options();
+  inline ::google::protobuf::EnumValueOptions* release_options();
   
   // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto)
  private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_number();
+  inline void clear_has_number();
+  inline void set_has_options();
+  inline void clear_has_options();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* name_;
-  static const ::std::string _default_name_;
-  ::google::protobuf::int32 number_;
   ::google::protobuf::EnumValueOptions* options_;
+  ::google::protobuf::int32 number_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static EnumValueDescriptorProto* default_instance_;
 };
@@ -1202,6 +1197,7 @@
   inline void set_name(const char* value);
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
+  inline ::std::string* release_name();
   
   // repeated .google.protobuf.MethodDescriptorProto method = 2;
   inline int method_size() const;
@@ -1221,33 +1217,28 @@
   static const int kOptionsFieldNumber = 3;
   inline const ::google::protobuf::ServiceOptions& options() const;
   inline ::google::protobuf::ServiceOptions* mutable_options();
+  inline ::google::protobuf::ServiceOptions* release_options();
   
   // @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto)
  private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_options();
+  inline void clear_has_options();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* name_;
-  static const ::std::string _default_name_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto > method_;
   ::google::protobuf::ServiceOptions* options_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static ServiceDescriptorProto* default_instance_;
 };
@@ -1316,6 +1307,7 @@
   inline void set_name(const char* value);
   inline void set_name(const char* value, size_t size);
   inline ::std::string* mutable_name();
+  inline ::std::string* release_name();
   
   // optional string input_type = 2;
   inline bool has_input_type() const;
@@ -1326,6 +1318,7 @@
   inline void set_input_type(const char* value);
   inline void set_input_type(const char* value, size_t size);
   inline ::std::string* mutable_input_type();
+  inline ::std::string* release_input_type();
   
   // optional string output_type = 3;
   inline bool has_output_type() const;
@@ -1336,6 +1329,7 @@
   inline void set_output_type(const char* value);
   inline void set_output_type(const char* value, size_t size);
   inline ::std::string* mutable_output_type();
+  inline ::std::string* release_output_type();
   
   // optional .google.protobuf.MethodOptions options = 4;
   inline bool has_options() const;
@@ -1343,36 +1337,33 @@
   static const int kOptionsFieldNumber = 4;
   inline const ::google::protobuf::MethodOptions& options() const;
   inline ::google::protobuf::MethodOptions* mutable_options();
+  inline ::google::protobuf::MethodOptions* release_options();
   
   // @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto)
  private:
+  inline void set_has_name();
+  inline void clear_has_name();
+  inline void set_has_input_type();
+  inline void clear_has_input_type();
+  inline void set_has_output_type();
+  inline void clear_has_output_type();
+  inline void set_has_options();
+  inline void clear_has_options();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* name_;
-  static const ::std::string _default_name_;
   ::std::string* input_type_;
-  static const ::std::string _default_input_type_;
   ::std::string* output_type_;
-  static const ::std::string _default_output_type_;
   ::google::protobuf::MethodOptions* options_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static MethodDescriptorProto* default_instance_;
 };
@@ -1466,6 +1457,7 @@
   inline void set_java_package(const char* value);
   inline void set_java_package(const char* value, size_t size);
   inline ::std::string* mutable_java_package();
+  inline ::std::string* release_java_package();
   
   // optional string java_outer_classname = 8;
   inline bool has_java_outer_classname() const;
@@ -1476,6 +1468,7 @@
   inline void set_java_outer_classname(const char* value);
   inline void set_java_outer_classname(const char* value, size_t size);
   inline ::std::string* mutable_java_outer_classname();
+  inline ::std::string* release_java_outer_classname();
   
   // optional bool java_multiple_files = 10 [default = false];
   inline bool has_java_multiple_files() const;
@@ -1484,6 +1477,13 @@
   inline bool java_multiple_files() const;
   inline void set_java_multiple_files(bool value);
   
+  // optional bool java_generate_equals_and_hash = 20 [default = false];
+  inline bool has_java_generate_equals_and_hash() const;
+  inline void clear_java_generate_equals_and_hash();
+  static const int kJavaGenerateEqualsAndHashFieldNumber = 20;
+  inline bool java_generate_equals_and_hash() const;
+  inline void set_java_generate_equals_and_hash(bool value);
+  
   // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
   inline bool has_optimize_for() const;
   inline void clear_optimize_for();
@@ -1491,21 +1491,21 @@
   inline ::google::protobuf::FileOptions_OptimizeMode optimize_for() const;
   inline void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value);
   
-  // optional bool cc_generic_services = 16 [default = true];
+  // optional bool cc_generic_services = 16 [default = false];
   inline bool has_cc_generic_services() const;
   inline void clear_cc_generic_services();
   static const int kCcGenericServicesFieldNumber = 16;
   inline bool cc_generic_services() const;
   inline void set_cc_generic_services(bool value);
   
-  // optional bool java_generic_services = 17 [default = true];
+  // optional bool java_generic_services = 17 [default = false];
   inline bool has_java_generic_services() const;
   inline void clear_java_generic_services();
   static const int kJavaGenericServicesFieldNumber = 17;
   inline bool java_generic_services() const;
   inline void set_java_generic_services(bool value);
   
-  // optional bool py_generic_services = 18 [default = true];
+  // optional bool py_generic_services = 18 [default = false];
   inline bool has_py_generic_services() const;
   inline void clear_py_generic_services();
   static const int kPyGenericServicesFieldNumber = 18;
@@ -1527,37 +1527,44 @@
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.FileOptions)
  private:
+  inline void set_has_java_package();
+  inline void clear_has_java_package();
+  inline void set_has_java_outer_classname();
+  inline void clear_has_java_outer_classname();
+  inline void set_has_java_multiple_files();
+  inline void clear_has_java_multiple_files();
+  inline void set_has_java_generate_equals_and_hash();
+  inline void clear_has_java_generate_equals_and_hash();
+  inline void set_has_optimize_for();
+  inline void clear_has_optimize_for();
+  inline void set_has_cc_generic_services();
+  inline void clear_has_cc_generic_services();
+  inline void set_has_java_generic_services();
+  inline void clear_has_java_generic_services();
+  inline void set_has_py_generic_services();
+  inline void clear_has_py_generic_services();
+  
   ::google::protobuf::internal::ExtensionSet _extensions_;
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* java_package_;
-  static const ::std::string _default_java_package_;
   ::std::string* java_outer_classname_;
-  static const ::std::string _default_java_outer_classname_;
-  bool java_multiple_files_;
   int optimize_for_;
+  bool java_multiple_files_;
+  bool java_generate_equals_and_hash_;
   bool cc_generic_services_;
   bool java_generic_services_;
-  bool py_generic_services_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  bool py_generic_services_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(9 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static FileOptions* default_instance_;
 };
@@ -1646,30 +1653,26 @@
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions)
  private:
-  ::google::protobuf::internal::ExtensionSet _extensions_;
-  ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
+  inline void set_has_message_set_wire_format();
+  inline void clear_has_message_set_wire_format();
+  inline void set_has_no_standard_descriptor_accessor();
+  inline void clear_has_no_standard_descriptor_accessor();
   
+  ::google::protobuf::internal::ExtensionSet _extensions_;
+  
+  ::google::protobuf::UnknownFieldSet _unknown_fields_;
+  
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
   bool message_set_wire_format_;
   bool no_standard_descriptor_accessor_;
-  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static MessageOptions* default_instance_;
 };
@@ -1784,6 +1787,7 @@
   inline void set_experimental_map_key(const char* value);
   inline void set_experimental_map_key(const char* value, size_t size);
   inline ::std::string* mutable_experimental_map_key();
+  inline ::std::string* release_experimental_map_key();
   
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   inline int uninterpreted_option_size() const;
@@ -1800,33 +1804,32 @@
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions)
  private:
+  inline void set_has_ctype();
+  inline void clear_has_ctype();
+  inline void set_has_packed();
+  inline void clear_has_packed();
+  inline void set_has_deprecated();
+  inline void clear_has_deprecated();
+  inline void set_has_experimental_map_key();
+  inline void clear_has_experimental_map_key();
+  
   ::google::protobuf::internal::ExtensionSet _extensions_;
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   int ctype_;
   bool packed_;
   bool deprecated_;
   ::std::string* experimental_map_key_;
-  static const ::std::string _default_experimental_map_key_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static FieldOptions* default_instance_;
 };
@@ -1901,28 +1904,20 @@
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions)
  private:
+  
   ::google::protobuf::internal::ExtensionSet _extensions_;
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static EnumOptions* default_instance_;
 };
@@ -1997,28 +1992,20 @@
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions)
  private:
+  
   ::google::protobuf::internal::ExtensionSet _extensions_;
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static EnumValueOptions* default_instance_;
 };
@@ -2093,28 +2080,20 @@
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions)
  private:
+  
   ::google::protobuf::internal::ExtensionSet _extensions_;
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static ServiceOptions* default_instance_;
 };
@@ -2189,28 +2168,20 @@
   GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions)
   // @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions)
  private:
+  
   ::google::protobuf::internal::ExtensionSet _extensions_;
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static MethodOptions* default_instance_;
 };
@@ -2279,6 +2250,7 @@
   inline void set_name_part(const char* value);
   inline void set_name_part(const char* value, size_t size);
   inline ::std::string* mutable_name_part();
+  inline ::std::string* release_name_part();
   
   // required bool is_extension = 2;
   inline bool has_is_extension() const;
@@ -2289,29 +2261,23 @@
   
   // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart)
  private:
+  inline void set_has_name_part();
+  inline void clear_has_name_part();
+  inline void set_has_is_extension();
+  inline void clear_has_is_extension();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::std::string* name_part_;
-  static const ::std::string _default_name_part_;
   bool is_extension_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static UninterpretedOption_NamePart* default_instance_;
 };
@@ -2394,6 +2360,7 @@
   inline void set_identifier_value(const char* value);
   inline void set_identifier_value(const char* value, size_t size);
   inline ::std::string* mutable_identifier_value();
+  inline ::std::string* release_identifier_value();
   
   // optional uint64 positive_int_value = 4;
   inline bool has_positive_int_value() const;
@@ -2425,40 +2392,241 @@
   inline void set_string_value(const char* value);
   inline void set_string_value(const void* value, size_t size);
   inline ::std::string* mutable_string_value();
+  inline ::std::string* release_string_value();
+  
+  // optional string aggregate_value = 8;
+  inline bool has_aggregate_value() const;
+  inline void clear_aggregate_value();
+  static const int kAggregateValueFieldNumber = 8;
+  inline const ::std::string& aggregate_value() const;
+  inline void set_aggregate_value(const ::std::string& value);
+  inline void set_aggregate_value(const char* value);
+  inline void set_aggregate_value(const char* value, size_t size);
+  inline ::std::string* mutable_aggregate_value();
+  inline ::std::string* release_aggregate_value();
   
   // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption)
  private:
+  inline void set_has_identifier_value();
+  inline void clear_has_identifier_value();
+  inline void set_has_positive_int_value();
+  inline void clear_has_positive_int_value();
+  inline void set_has_negative_int_value();
+  inline void clear_has_negative_int_value();
+  inline void set_has_double_value();
+  inline void clear_has_double_value();
+  inline void set_has_string_value();
+  inline void clear_has_string_value();
+  inline void set_has_aggregate_value();
+  inline void clear_has_aggregate_value();
+  
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
-  mutable int _cached_size_;
   
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart > name_;
   ::std::string* identifier_value_;
-  static const ::std::string _default_identifier_value_;
   ::google::protobuf::uint64 positive_int_value_;
   ::google::protobuf::int64 negative_int_value_;
   double double_value_;
   ::std::string* string_value_;
-  static const ::std::string _default_string_value_;
+  ::std::string* aggregate_value_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
+  
   friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
   friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
   
-  ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32];
-  
-  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
-  inline bool _has_bit(int index) const {
-    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
-  }
-  inline void _set_bit(int index) {
-    _has_bits_[index / 32] |= (1u << (index % 32));
-  }
-  inline void _clear_bit(int index) {
-    _has_bits_[index / 32] &= ~(1u << (index % 32));
-  }
-  
   void InitAsDefaultInstance();
   static UninterpretedOption* default_instance_;
 };
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Message {
+ public:
+  SourceCodeInfo_Location();
+  virtual ~SourceCodeInfo_Location();
+  
+  SourceCodeInfo_Location(const SourceCodeInfo_Location& from);
+  
+  inline SourceCodeInfo_Location& operator=(const SourceCodeInfo_Location& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _unknown_fields_;
+  }
+  
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+  
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const SourceCodeInfo_Location& default_instance();
+  
+  void Swap(SourceCodeInfo_Location* other);
+  
+  // implements Message ----------------------------------------------
+  
+  SourceCodeInfo_Location* New() const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const SourceCodeInfo_Location& from);
+  void MergeFrom(const SourceCodeInfo_Location& from);
+  void Clear();
+  bool IsInitialized() const;
+  
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  
+  ::google::protobuf::Metadata GetMetadata() const;
+  
+  // nested types ----------------------------------------------------
+  
+  // accessors -------------------------------------------------------
+  
+  // repeated int32 path = 1 [packed = true];
+  inline int path_size() const;
+  inline void clear_path();
+  static const int kPathFieldNumber = 1;
+  inline ::google::protobuf::int32 path(int index) const;
+  inline void set_path(int index, ::google::protobuf::int32 value);
+  inline void add_path(::google::protobuf::int32 value);
+  inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+      path() const;
+  inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+      mutable_path();
+  
+  // repeated int32 span = 2 [packed = true];
+  inline int span_size() const;
+  inline void clear_span();
+  static const int kSpanFieldNumber = 2;
+  inline ::google::protobuf::int32 span(int index) const;
+  inline void set_span(int index, ::google::protobuf::int32 value);
+  inline void add_span(::google::protobuf::int32 value);
+  inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+      span() const;
+  inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+      mutable_span();
+  
+  // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location)
+ private:
+  
+  ::google::protobuf::UnknownFieldSet _unknown_fields_;
+  
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 > path_;
+  mutable int _path_cached_byte_size_;
+  ::google::protobuf::RepeatedField< ::google::protobuf::int32 > span_;
+  mutable int _span_cached_byte_size_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
+  
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
+  void InitAsDefaultInstance();
+  static SourceCodeInfo_Location* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message {
+ public:
+  SourceCodeInfo();
+  virtual ~SourceCodeInfo();
+  
+  SourceCodeInfo(const SourceCodeInfo& from);
+  
+  inline SourceCodeInfo& operator=(const SourceCodeInfo& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _unknown_fields_;
+  }
+  
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+  
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const SourceCodeInfo& default_instance();
+  
+  void Swap(SourceCodeInfo* other);
+  
+  // implements Message ----------------------------------------------
+  
+  SourceCodeInfo* New() const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const SourceCodeInfo& from);
+  void MergeFrom(const SourceCodeInfo& from);
+  void Clear();
+  bool IsInitialized() const;
+  
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  
+  ::google::protobuf::Metadata GetMetadata() const;
+  
+  // nested types ----------------------------------------------------
+  
+  typedef SourceCodeInfo_Location Location;
+  
+  // accessors -------------------------------------------------------
+  
+  // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+  inline int location_size() const;
+  inline void clear_location();
+  static const int kLocationFieldNumber = 1;
+  inline const ::google::protobuf::SourceCodeInfo_Location& location(int index) const;
+  inline ::google::protobuf::SourceCodeInfo_Location* mutable_location(int index);
+  inline ::google::protobuf::SourceCodeInfo_Location* add_location();
+  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+      location() const;
+  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
+      mutable_location();
+  
+  // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo)
+ private:
+  
+  ::google::protobuf::UnknownFieldSet _unknown_fields_;
+  
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location > location_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
+  
+  friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+  
+  void InitAsDefaultInstance();
+  static SourceCodeInfo* default_instance_;
+};
 // ===================================================================
 
 
@@ -2497,87 +2665,119 @@
 
 // optional string name = 1;
 inline bool FileDescriptorProto::has_name() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void FileDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void FileDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void FileDescriptorProto::clear_name() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     name_->clear();
   }
-  _clear_bit(0);
+  clear_has_name();
 }
 inline const ::std::string& FileDescriptorProto::name() const {
   return *name_;
 }
 inline void FileDescriptorProto::set_name(const ::std::string& value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void FileDescriptorProto::set_name(const char* value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void FileDescriptorProto::set_name(const char* value, size_t size) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* FileDescriptorProto::mutable_name() {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   return name_;
 }
+inline ::std::string* FileDescriptorProto::release_name() {
+  clear_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = name_;
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional string package = 2;
 inline bool FileDescriptorProto::has_package() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void FileDescriptorProto::set_has_package() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void FileDescriptorProto::clear_has_package() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void FileDescriptorProto::clear_package() {
-  if (package_ != &_default_package_) {
+  if (package_ != &::google::protobuf::internal::kEmptyString) {
     package_->clear();
   }
-  _clear_bit(1);
+  clear_has_package();
 }
 inline const ::std::string& FileDescriptorProto::package() const {
   return *package_;
 }
 inline void FileDescriptorProto::set_package(const ::std::string& value) {
-  _set_bit(1);
-  if (package_ == &_default_package_) {
+  set_has_package();
+  if (package_ == &::google::protobuf::internal::kEmptyString) {
     package_ = new ::std::string;
   }
   package_->assign(value);
 }
 inline void FileDescriptorProto::set_package(const char* value) {
-  _set_bit(1);
-  if (package_ == &_default_package_) {
+  set_has_package();
+  if (package_ == &::google::protobuf::internal::kEmptyString) {
     package_ = new ::std::string;
   }
   package_->assign(value);
 }
 inline void FileDescriptorProto::set_package(const char* value, size_t size) {
-  _set_bit(1);
-  if (package_ == &_default_package_) {
+  set_has_package();
+  if (package_ == &::google::protobuf::internal::kEmptyString) {
     package_ = new ::std::string;
   }
   package_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* FileDescriptorProto::mutable_package() {
-  _set_bit(1);
-  if (package_ == &_default_package_) {
+  set_has_package();
+  if (package_ == &::google::protobuf::internal::kEmptyString) {
     package_ = new ::std::string;
   }
   return package_;
 }
+inline ::std::string* FileDescriptorProto::release_package() {
+  clear_has_package();
+  if (package_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = package_;
+    package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // repeated string dependency = 3;
 inline int FileDescriptorProto::dependency_size() const {
@@ -2725,20 +2925,61 @@
 
 // optional .google.protobuf.FileOptions options = 8;
 inline bool FileDescriptorProto::has_options() const {
-  return _has_bit(7);
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+inline void FileDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000080u;
+}
+inline void FileDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000080u;
 }
 inline void FileDescriptorProto::clear_options() {
   if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
-  _clear_bit(7);
+  clear_has_options();
 }
 inline const ::google::protobuf::FileOptions& FileDescriptorProto::options() const {
   return options_ != NULL ? *options_ : *default_instance_->options_;
 }
 inline ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() {
-  _set_bit(7);
+  set_has_options();
   if (options_ == NULL) options_ = new ::google::protobuf::FileOptions;
   return options_;
 }
+inline ::google::protobuf::FileOptions* FileDescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::FileOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+
+// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+inline bool FileDescriptorProto::has_source_code_info() const {
+  return (_has_bits_[0] & 0x00000100u) != 0;
+}
+inline void FileDescriptorProto::set_has_source_code_info() {
+  _has_bits_[0] |= 0x00000100u;
+}
+inline void FileDescriptorProto::clear_has_source_code_info() {
+  _has_bits_[0] &= ~0x00000100u;
+}
+inline void FileDescriptorProto::clear_source_code_info() {
+  if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear();
+  clear_has_source_code_info();
+}
+inline const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const {
+  return source_code_info_ != NULL ? *source_code_info_ : *default_instance_->source_code_info_;
+}
+inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() {
+  set_has_source_code_info();
+  if (source_code_info_ == NULL) source_code_info_ = new ::google::protobuf::SourceCodeInfo;
+  return source_code_info_;
+}
+inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() {
+  clear_has_source_code_info();
+  ::google::protobuf::SourceCodeInfo* temp = source_code_info_;
+  source_code_info_ = NULL;
+  return temp;
+}
 
 // -------------------------------------------------------------------
 
@@ -2746,33 +2987,45 @@
 
 // optional int32 start = 1;
 inline bool DescriptorProto_ExtensionRange::has_start() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void DescriptorProto_ExtensionRange::set_has_start() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void DescriptorProto_ExtensionRange::clear_has_start() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void DescriptorProto_ExtensionRange::clear_start() {
   start_ = 0;
-  _clear_bit(0);
+  clear_has_start();
 }
 inline ::google::protobuf::int32 DescriptorProto_ExtensionRange::start() const {
   return start_;
 }
 inline void DescriptorProto_ExtensionRange::set_start(::google::protobuf::int32 value) {
-  _set_bit(0);
+  set_has_start();
   start_ = value;
 }
 
 // optional int32 end = 2;
 inline bool DescriptorProto_ExtensionRange::has_end() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void DescriptorProto_ExtensionRange::set_has_end() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void DescriptorProto_ExtensionRange::clear_has_end() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void DescriptorProto_ExtensionRange::clear_end() {
   end_ = 0;
-  _clear_bit(1);
+  clear_has_end();
 }
 inline ::google::protobuf::int32 DescriptorProto_ExtensionRange::end() const {
   return end_;
 }
 inline void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 value) {
-  _set_bit(1);
+  set_has_end();
   end_ = value;
 }
 
@@ -2782,45 +3035,61 @@
 
 // optional string name = 1;
 inline bool DescriptorProto::has_name() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void DescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void DescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void DescriptorProto::clear_name() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     name_->clear();
   }
-  _clear_bit(0);
+  clear_has_name();
 }
 inline const ::std::string& DescriptorProto::name() const {
   return *name_;
 }
 inline void DescriptorProto::set_name(const ::std::string& value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void DescriptorProto::set_name(const char* value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void DescriptorProto::set_name(const char* value, size_t size) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* DescriptorProto::mutable_name() {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   return name_;
 }
+inline ::std::string* DescriptorProto::release_name() {
+  clear_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = name_;
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // repeated .google.protobuf.FieldDescriptorProto field = 2;
 inline int DescriptorProto::field_size() const {
@@ -2949,20 +3218,32 @@
 
 // optional .google.protobuf.MessageOptions options = 7;
 inline bool DescriptorProto::has_options() const {
-  return _has_bit(6);
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+inline void DescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000040u;
+}
+inline void DescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000040u;
 }
 inline void DescriptorProto::clear_options() {
   if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear();
-  _clear_bit(6);
+  clear_has_options();
 }
 inline const ::google::protobuf::MessageOptions& DescriptorProto::options() const {
   return options_ != NULL ? *options_ : *default_instance_->options_;
 }
 inline ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() {
-  _set_bit(6);
+  set_has_options();
   if (options_ == NULL) options_ = new ::google::protobuf::MessageOptions;
   return options_;
 }
+inline ::google::protobuf::MessageOptions* DescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::MessageOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
 
 // -------------------------------------------------------------------
 
@@ -2970,238 +3251,332 @@
 
 // optional string name = 1;
 inline bool FieldDescriptorProto::has_name() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void FieldDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void FieldDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void FieldDescriptorProto::clear_name() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     name_->clear();
   }
-  _clear_bit(0);
+  clear_has_name();
 }
 inline const ::std::string& FieldDescriptorProto::name() const {
   return *name_;
 }
 inline void FieldDescriptorProto::set_name(const ::std::string& value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void FieldDescriptorProto::set_name(const char* value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void FieldDescriptorProto::set_name(const char* value, size_t size) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* FieldDescriptorProto::mutable_name() {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   return name_;
 }
+inline ::std::string* FieldDescriptorProto::release_name() {
+  clear_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = name_;
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional int32 number = 3;
 inline bool FieldDescriptorProto::has_number() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void FieldDescriptorProto::set_has_number() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void FieldDescriptorProto::clear_has_number() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void FieldDescriptorProto::clear_number() {
   number_ = 0;
-  _clear_bit(1);
+  clear_has_number();
 }
 inline ::google::protobuf::int32 FieldDescriptorProto::number() const {
   return number_;
 }
 inline void FieldDescriptorProto::set_number(::google::protobuf::int32 value) {
-  _set_bit(1);
+  set_has_number();
   number_ = value;
 }
 
 // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
 inline bool FieldDescriptorProto::has_label() const {
-  return _has_bit(2);
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void FieldDescriptorProto::set_has_label() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void FieldDescriptorProto::clear_has_label() {
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void FieldDescriptorProto::clear_label() {
   label_ = 1;
-  _clear_bit(2);
+  clear_has_label();
 }
 inline ::google::protobuf::FieldDescriptorProto_Label FieldDescriptorProto::label() const {
   return static_cast< ::google::protobuf::FieldDescriptorProto_Label >(label_);
 }
 inline void FieldDescriptorProto::set_label(::google::protobuf::FieldDescriptorProto_Label value) {
   GOOGLE_DCHECK(::google::protobuf::FieldDescriptorProto_Label_IsValid(value));
-  _set_bit(2);
+  set_has_label();
   label_ = value;
 }
 
 // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
 inline bool FieldDescriptorProto::has_type() const {
-  return _has_bit(3);
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void FieldDescriptorProto::set_has_type() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void FieldDescriptorProto::clear_has_type() {
+  _has_bits_[0] &= ~0x00000008u;
 }
 inline void FieldDescriptorProto::clear_type() {
   type_ = 1;
-  _clear_bit(3);
+  clear_has_type();
 }
 inline ::google::protobuf::FieldDescriptorProto_Type FieldDescriptorProto::type() const {
   return static_cast< ::google::protobuf::FieldDescriptorProto_Type >(type_);
 }
 inline void FieldDescriptorProto::set_type(::google::protobuf::FieldDescriptorProto_Type value) {
   GOOGLE_DCHECK(::google::protobuf::FieldDescriptorProto_Type_IsValid(value));
-  _set_bit(3);
+  set_has_type();
   type_ = value;
 }
 
 // optional string type_name = 6;
 inline bool FieldDescriptorProto::has_type_name() const {
-  return _has_bit(4);
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+inline void FieldDescriptorProto::set_has_type_name() {
+  _has_bits_[0] |= 0x00000010u;
+}
+inline void FieldDescriptorProto::clear_has_type_name() {
+  _has_bits_[0] &= ~0x00000010u;
 }
 inline void FieldDescriptorProto::clear_type_name() {
-  if (type_name_ != &_default_type_name_) {
+  if (type_name_ != &::google::protobuf::internal::kEmptyString) {
     type_name_->clear();
   }
-  _clear_bit(4);
+  clear_has_type_name();
 }
 inline const ::std::string& FieldDescriptorProto::type_name() const {
   return *type_name_;
 }
 inline void FieldDescriptorProto::set_type_name(const ::std::string& value) {
-  _set_bit(4);
-  if (type_name_ == &_default_type_name_) {
+  set_has_type_name();
+  if (type_name_ == &::google::protobuf::internal::kEmptyString) {
     type_name_ = new ::std::string;
   }
   type_name_->assign(value);
 }
 inline void FieldDescriptorProto::set_type_name(const char* value) {
-  _set_bit(4);
-  if (type_name_ == &_default_type_name_) {
+  set_has_type_name();
+  if (type_name_ == &::google::protobuf::internal::kEmptyString) {
     type_name_ = new ::std::string;
   }
   type_name_->assign(value);
 }
 inline void FieldDescriptorProto::set_type_name(const char* value, size_t size) {
-  _set_bit(4);
-  if (type_name_ == &_default_type_name_) {
+  set_has_type_name();
+  if (type_name_ == &::google::protobuf::internal::kEmptyString) {
     type_name_ = new ::std::string;
   }
   type_name_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* FieldDescriptorProto::mutable_type_name() {
-  _set_bit(4);
-  if (type_name_ == &_default_type_name_) {
+  set_has_type_name();
+  if (type_name_ == &::google::protobuf::internal::kEmptyString) {
     type_name_ = new ::std::string;
   }
   return type_name_;
 }
+inline ::std::string* FieldDescriptorProto::release_type_name() {
+  clear_has_type_name();
+  if (type_name_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = type_name_;
+    type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional string extendee = 2;
 inline bool FieldDescriptorProto::has_extendee() const {
-  return _has_bit(5);
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+inline void FieldDescriptorProto::set_has_extendee() {
+  _has_bits_[0] |= 0x00000020u;
+}
+inline void FieldDescriptorProto::clear_has_extendee() {
+  _has_bits_[0] &= ~0x00000020u;
 }
 inline void FieldDescriptorProto::clear_extendee() {
-  if (extendee_ != &_default_extendee_) {
+  if (extendee_ != &::google::protobuf::internal::kEmptyString) {
     extendee_->clear();
   }
-  _clear_bit(5);
+  clear_has_extendee();
 }
 inline const ::std::string& FieldDescriptorProto::extendee() const {
   return *extendee_;
 }
 inline void FieldDescriptorProto::set_extendee(const ::std::string& value) {
-  _set_bit(5);
-  if (extendee_ == &_default_extendee_) {
+  set_has_extendee();
+  if (extendee_ == &::google::protobuf::internal::kEmptyString) {
     extendee_ = new ::std::string;
   }
   extendee_->assign(value);
 }
 inline void FieldDescriptorProto::set_extendee(const char* value) {
-  _set_bit(5);
-  if (extendee_ == &_default_extendee_) {
+  set_has_extendee();
+  if (extendee_ == &::google::protobuf::internal::kEmptyString) {
     extendee_ = new ::std::string;
   }
   extendee_->assign(value);
 }
 inline void FieldDescriptorProto::set_extendee(const char* value, size_t size) {
-  _set_bit(5);
-  if (extendee_ == &_default_extendee_) {
+  set_has_extendee();
+  if (extendee_ == &::google::protobuf::internal::kEmptyString) {
     extendee_ = new ::std::string;
   }
   extendee_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* FieldDescriptorProto::mutable_extendee() {
-  _set_bit(5);
-  if (extendee_ == &_default_extendee_) {
+  set_has_extendee();
+  if (extendee_ == &::google::protobuf::internal::kEmptyString) {
     extendee_ = new ::std::string;
   }
   return extendee_;
 }
+inline ::std::string* FieldDescriptorProto::release_extendee() {
+  clear_has_extendee();
+  if (extendee_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = extendee_;
+    extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional string default_value = 7;
 inline bool FieldDescriptorProto::has_default_value() const {
-  return _has_bit(6);
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+inline void FieldDescriptorProto::set_has_default_value() {
+  _has_bits_[0] |= 0x00000040u;
+}
+inline void FieldDescriptorProto::clear_has_default_value() {
+  _has_bits_[0] &= ~0x00000040u;
 }
 inline void FieldDescriptorProto::clear_default_value() {
-  if (default_value_ != &_default_default_value_) {
+  if (default_value_ != &::google::protobuf::internal::kEmptyString) {
     default_value_->clear();
   }
-  _clear_bit(6);
+  clear_has_default_value();
 }
 inline const ::std::string& FieldDescriptorProto::default_value() const {
   return *default_value_;
 }
 inline void FieldDescriptorProto::set_default_value(const ::std::string& value) {
-  _set_bit(6);
-  if (default_value_ == &_default_default_value_) {
+  set_has_default_value();
+  if (default_value_ == &::google::protobuf::internal::kEmptyString) {
     default_value_ = new ::std::string;
   }
   default_value_->assign(value);
 }
 inline void FieldDescriptorProto::set_default_value(const char* value) {
-  _set_bit(6);
-  if (default_value_ == &_default_default_value_) {
+  set_has_default_value();
+  if (default_value_ == &::google::protobuf::internal::kEmptyString) {
     default_value_ = new ::std::string;
   }
   default_value_->assign(value);
 }
 inline void FieldDescriptorProto::set_default_value(const char* value, size_t size) {
-  _set_bit(6);
-  if (default_value_ == &_default_default_value_) {
+  set_has_default_value();
+  if (default_value_ == &::google::protobuf::internal::kEmptyString) {
     default_value_ = new ::std::string;
   }
   default_value_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* FieldDescriptorProto::mutable_default_value() {
-  _set_bit(6);
-  if (default_value_ == &_default_default_value_) {
+  set_has_default_value();
+  if (default_value_ == &::google::protobuf::internal::kEmptyString) {
     default_value_ = new ::std::string;
   }
   return default_value_;
 }
+inline ::std::string* FieldDescriptorProto::release_default_value() {
+  clear_has_default_value();
+  if (default_value_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = default_value_;
+    default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional .google.protobuf.FieldOptions options = 8;
 inline bool FieldDescriptorProto::has_options() const {
-  return _has_bit(7);
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+inline void FieldDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000080u;
+}
+inline void FieldDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000080u;
 }
 inline void FieldDescriptorProto::clear_options() {
   if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
-  _clear_bit(7);
+  clear_has_options();
 }
 inline const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const {
   return options_ != NULL ? *options_ : *default_instance_->options_;
 }
 inline ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() {
-  _set_bit(7);
+  set_has_options();
   if (options_ == NULL) options_ = new ::google::protobuf::FieldOptions;
   return options_;
 }
+inline ::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::FieldOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
 
 // -------------------------------------------------------------------
 
@@ -3209,45 +3584,61 @@
 
 // optional string name = 1;
 inline bool EnumDescriptorProto::has_name() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void EnumDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void EnumDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void EnumDescriptorProto::clear_name() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     name_->clear();
   }
-  _clear_bit(0);
+  clear_has_name();
 }
 inline const ::std::string& EnumDescriptorProto::name() const {
   return *name_;
 }
 inline void EnumDescriptorProto::set_name(const ::std::string& value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void EnumDescriptorProto::set_name(const char* value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void EnumDescriptorProto::set_name(const char* value, size_t size) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* EnumDescriptorProto::mutable_name() {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   return name_;
 }
+inline ::std::string* EnumDescriptorProto::release_name() {
+  clear_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = name_;
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
 inline int EnumDescriptorProto::value_size() const {
@@ -3276,20 +3667,32 @@
 
 // optional .google.protobuf.EnumOptions options = 3;
 inline bool EnumDescriptorProto::has_options() const {
-  return _has_bit(2);
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void EnumDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void EnumDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void EnumDescriptorProto::clear_options() {
   if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear();
-  _clear_bit(2);
+  clear_has_options();
 }
 inline const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const {
   return options_ != NULL ? *options_ : *default_instance_->options_;
 }
 inline ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() {
-  _set_bit(2);
+  set_has_options();
   if (options_ == NULL) options_ = new ::google::protobuf::EnumOptions;
   return options_;
 }
+inline ::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::EnumOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
 
 // -------------------------------------------------------------------
 
@@ -3297,78 +3700,112 @@
 
 // optional string name = 1;
 inline bool EnumValueDescriptorProto::has_name() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void EnumValueDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void EnumValueDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void EnumValueDescriptorProto::clear_name() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     name_->clear();
   }
-  _clear_bit(0);
+  clear_has_name();
 }
 inline const ::std::string& EnumValueDescriptorProto::name() const {
   return *name_;
 }
 inline void EnumValueDescriptorProto::set_name(const ::std::string& value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void EnumValueDescriptorProto::set_name(const char* value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void EnumValueDescriptorProto::set_name(const char* value, size_t size) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* EnumValueDescriptorProto::mutable_name() {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   return name_;
 }
+inline ::std::string* EnumValueDescriptorProto::release_name() {
+  clear_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = name_;
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional int32 number = 2;
 inline bool EnumValueDescriptorProto::has_number() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void EnumValueDescriptorProto::set_has_number() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void EnumValueDescriptorProto::clear_has_number() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void EnumValueDescriptorProto::clear_number() {
   number_ = 0;
-  _clear_bit(1);
+  clear_has_number();
 }
 inline ::google::protobuf::int32 EnumValueDescriptorProto::number() const {
   return number_;
 }
 inline void EnumValueDescriptorProto::set_number(::google::protobuf::int32 value) {
-  _set_bit(1);
+  set_has_number();
   number_ = value;
 }
 
 // optional .google.protobuf.EnumValueOptions options = 3;
 inline bool EnumValueDescriptorProto::has_options() const {
-  return _has_bit(2);
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void EnumValueDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void EnumValueDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void EnumValueDescriptorProto::clear_options() {
   if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear();
-  _clear_bit(2);
+  clear_has_options();
 }
 inline const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const {
   return options_ != NULL ? *options_ : *default_instance_->options_;
 }
 inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() {
-  _set_bit(2);
+  set_has_options();
   if (options_ == NULL) options_ = new ::google::protobuf::EnumValueOptions;
   return options_;
 }
+inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::EnumValueOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
 
 // -------------------------------------------------------------------
 
@@ -3376,45 +3813,61 @@
 
 // optional string name = 1;
 inline bool ServiceDescriptorProto::has_name() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void ServiceDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void ServiceDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void ServiceDescriptorProto::clear_name() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     name_->clear();
   }
-  _clear_bit(0);
+  clear_has_name();
 }
 inline const ::std::string& ServiceDescriptorProto::name() const {
   return *name_;
 }
 inline void ServiceDescriptorProto::set_name(const ::std::string& value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void ServiceDescriptorProto::set_name(const char* value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void ServiceDescriptorProto::set_name(const char* value, size_t size) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* ServiceDescriptorProto::mutable_name() {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   return name_;
 }
+inline ::std::string* ServiceDescriptorProto::release_name() {
+  clear_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = name_;
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // repeated .google.protobuf.MethodDescriptorProto method = 2;
 inline int ServiceDescriptorProto::method_size() const {
@@ -3443,20 +3896,32 @@
 
 // optional .google.protobuf.ServiceOptions options = 3;
 inline bool ServiceDescriptorProto::has_options() const {
-  return _has_bit(2);
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void ServiceDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void ServiceDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void ServiceDescriptorProto::clear_options() {
   if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear();
-  _clear_bit(2);
+  clear_has_options();
 }
 inline const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const {
   return options_ != NULL ? *options_ : *default_instance_->options_;
 }
 inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() {
-  _set_bit(2);
+  set_has_options();
   if (options_ == NULL) options_ = new ::google::protobuf::ServiceOptions;
   return options_;
 }
+inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::ServiceOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
 
 // -------------------------------------------------------------------
 
@@ -3464,146 +3929,206 @@
 
 // optional string name = 1;
 inline bool MethodDescriptorProto::has_name() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void MethodDescriptorProto::set_has_name() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void MethodDescriptorProto::clear_has_name() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void MethodDescriptorProto::clear_name() {
-  if (name_ != &_default_name_) {
+  if (name_ != &::google::protobuf::internal::kEmptyString) {
     name_->clear();
   }
-  _clear_bit(0);
+  clear_has_name();
 }
 inline const ::std::string& MethodDescriptorProto::name() const {
   return *name_;
 }
 inline void MethodDescriptorProto::set_name(const ::std::string& value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void MethodDescriptorProto::set_name(const char* value) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(value);
 }
 inline void MethodDescriptorProto::set_name(const char* value, size_t size) {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   name_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* MethodDescriptorProto::mutable_name() {
-  _set_bit(0);
-  if (name_ == &_default_name_) {
+  set_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
     name_ = new ::std::string;
   }
   return name_;
 }
+inline ::std::string* MethodDescriptorProto::release_name() {
+  clear_has_name();
+  if (name_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = name_;
+    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional string input_type = 2;
 inline bool MethodDescriptorProto::has_input_type() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void MethodDescriptorProto::set_has_input_type() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void MethodDescriptorProto::clear_has_input_type() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void MethodDescriptorProto::clear_input_type() {
-  if (input_type_ != &_default_input_type_) {
+  if (input_type_ != &::google::protobuf::internal::kEmptyString) {
     input_type_->clear();
   }
-  _clear_bit(1);
+  clear_has_input_type();
 }
 inline const ::std::string& MethodDescriptorProto::input_type() const {
   return *input_type_;
 }
 inline void MethodDescriptorProto::set_input_type(const ::std::string& value) {
-  _set_bit(1);
-  if (input_type_ == &_default_input_type_) {
+  set_has_input_type();
+  if (input_type_ == &::google::protobuf::internal::kEmptyString) {
     input_type_ = new ::std::string;
   }
   input_type_->assign(value);
 }
 inline void MethodDescriptorProto::set_input_type(const char* value) {
-  _set_bit(1);
-  if (input_type_ == &_default_input_type_) {
+  set_has_input_type();
+  if (input_type_ == &::google::protobuf::internal::kEmptyString) {
     input_type_ = new ::std::string;
   }
   input_type_->assign(value);
 }
 inline void MethodDescriptorProto::set_input_type(const char* value, size_t size) {
-  _set_bit(1);
-  if (input_type_ == &_default_input_type_) {
+  set_has_input_type();
+  if (input_type_ == &::google::protobuf::internal::kEmptyString) {
     input_type_ = new ::std::string;
   }
   input_type_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* MethodDescriptorProto::mutable_input_type() {
-  _set_bit(1);
-  if (input_type_ == &_default_input_type_) {
+  set_has_input_type();
+  if (input_type_ == &::google::protobuf::internal::kEmptyString) {
     input_type_ = new ::std::string;
   }
   return input_type_;
 }
+inline ::std::string* MethodDescriptorProto::release_input_type() {
+  clear_has_input_type();
+  if (input_type_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = input_type_;
+    input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional string output_type = 3;
 inline bool MethodDescriptorProto::has_output_type() const {
-  return _has_bit(2);
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void MethodDescriptorProto::set_has_output_type() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void MethodDescriptorProto::clear_has_output_type() {
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void MethodDescriptorProto::clear_output_type() {
-  if (output_type_ != &_default_output_type_) {
+  if (output_type_ != &::google::protobuf::internal::kEmptyString) {
     output_type_->clear();
   }
-  _clear_bit(2);
+  clear_has_output_type();
 }
 inline const ::std::string& MethodDescriptorProto::output_type() const {
   return *output_type_;
 }
 inline void MethodDescriptorProto::set_output_type(const ::std::string& value) {
-  _set_bit(2);
-  if (output_type_ == &_default_output_type_) {
+  set_has_output_type();
+  if (output_type_ == &::google::protobuf::internal::kEmptyString) {
     output_type_ = new ::std::string;
   }
   output_type_->assign(value);
 }
 inline void MethodDescriptorProto::set_output_type(const char* value) {
-  _set_bit(2);
-  if (output_type_ == &_default_output_type_) {
+  set_has_output_type();
+  if (output_type_ == &::google::protobuf::internal::kEmptyString) {
     output_type_ = new ::std::string;
   }
   output_type_->assign(value);
 }
 inline void MethodDescriptorProto::set_output_type(const char* value, size_t size) {
-  _set_bit(2);
-  if (output_type_ == &_default_output_type_) {
+  set_has_output_type();
+  if (output_type_ == &::google::protobuf::internal::kEmptyString) {
     output_type_ = new ::std::string;
   }
   output_type_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* MethodDescriptorProto::mutable_output_type() {
-  _set_bit(2);
-  if (output_type_ == &_default_output_type_) {
+  set_has_output_type();
+  if (output_type_ == &::google::protobuf::internal::kEmptyString) {
     output_type_ = new ::std::string;
   }
   return output_type_;
 }
+inline ::std::string* MethodDescriptorProto::release_output_type() {
+  clear_has_output_type();
+  if (output_type_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = output_type_;
+    output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional .google.protobuf.MethodOptions options = 4;
 inline bool MethodDescriptorProto::has_options() const {
-  return _has_bit(3);
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void MethodDescriptorProto::set_has_options() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void MethodDescriptorProto::clear_has_options() {
+  _has_bits_[0] &= ~0x00000008u;
 }
 inline void MethodDescriptorProto::clear_options() {
   if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear();
-  _clear_bit(3);
+  clear_has_options();
 }
 inline const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const {
   return options_ != NULL ? *options_ : *default_instance_->options_;
 }
 inline ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() {
-  _set_bit(3);
+  set_has_options();
   if (options_ == NULL) options_ = new ::google::protobuf::MethodOptions;
   return options_;
 }
+inline ::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() {
+  clear_has_options();
+  ::google::protobuf::MethodOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
 
 // -------------------------------------------------------------------
 
@@ -3611,166 +4136,250 @@
 
 // optional string java_package = 1;
 inline bool FileOptions::has_java_package() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void FileOptions::set_has_java_package() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void FileOptions::clear_has_java_package() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void FileOptions::clear_java_package() {
-  if (java_package_ != &_default_java_package_) {
+  if (java_package_ != &::google::protobuf::internal::kEmptyString) {
     java_package_->clear();
   }
-  _clear_bit(0);
+  clear_has_java_package();
 }
 inline const ::std::string& FileOptions::java_package() const {
   return *java_package_;
 }
 inline void FileOptions::set_java_package(const ::std::string& value) {
-  _set_bit(0);
-  if (java_package_ == &_default_java_package_) {
+  set_has_java_package();
+  if (java_package_ == &::google::protobuf::internal::kEmptyString) {
     java_package_ = new ::std::string;
   }
   java_package_->assign(value);
 }
 inline void FileOptions::set_java_package(const char* value) {
-  _set_bit(0);
-  if (java_package_ == &_default_java_package_) {
+  set_has_java_package();
+  if (java_package_ == &::google::protobuf::internal::kEmptyString) {
     java_package_ = new ::std::string;
   }
   java_package_->assign(value);
 }
 inline void FileOptions::set_java_package(const char* value, size_t size) {
-  _set_bit(0);
-  if (java_package_ == &_default_java_package_) {
+  set_has_java_package();
+  if (java_package_ == &::google::protobuf::internal::kEmptyString) {
     java_package_ = new ::std::string;
   }
   java_package_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* FileOptions::mutable_java_package() {
-  _set_bit(0);
-  if (java_package_ == &_default_java_package_) {
+  set_has_java_package();
+  if (java_package_ == &::google::protobuf::internal::kEmptyString) {
     java_package_ = new ::std::string;
   }
   return java_package_;
 }
+inline ::std::string* FileOptions::release_java_package() {
+  clear_has_java_package();
+  if (java_package_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = java_package_;
+    java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional string java_outer_classname = 8;
 inline bool FileOptions::has_java_outer_classname() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void FileOptions::set_has_java_outer_classname() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void FileOptions::clear_has_java_outer_classname() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void FileOptions::clear_java_outer_classname() {
-  if (java_outer_classname_ != &_default_java_outer_classname_) {
+  if (java_outer_classname_ != &::google::protobuf::internal::kEmptyString) {
     java_outer_classname_->clear();
   }
-  _clear_bit(1);
+  clear_has_java_outer_classname();
 }
 inline const ::std::string& FileOptions::java_outer_classname() const {
   return *java_outer_classname_;
 }
 inline void FileOptions::set_java_outer_classname(const ::std::string& value) {
-  _set_bit(1);
-  if (java_outer_classname_ == &_default_java_outer_classname_) {
+  set_has_java_outer_classname();
+  if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) {
     java_outer_classname_ = new ::std::string;
   }
   java_outer_classname_->assign(value);
 }
 inline void FileOptions::set_java_outer_classname(const char* value) {
-  _set_bit(1);
-  if (java_outer_classname_ == &_default_java_outer_classname_) {
+  set_has_java_outer_classname();
+  if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) {
     java_outer_classname_ = new ::std::string;
   }
   java_outer_classname_->assign(value);
 }
 inline void FileOptions::set_java_outer_classname(const char* value, size_t size) {
-  _set_bit(1);
-  if (java_outer_classname_ == &_default_java_outer_classname_) {
+  set_has_java_outer_classname();
+  if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) {
     java_outer_classname_ = new ::std::string;
   }
   java_outer_classname_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* FileOptions::mutable_java_outer_classname() {
-  _set_bit(1);
-  if (java_outer_classname_ == &_default_java_outer_classname_) {
+  set_has_java_outer_classname();
+  if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) {
     java_outer_classname_ = new ::std::string;
   }
   return java_outer_classname_;
 }
+inline ::std::string* FileOptions::release_java_outer_classname() {
+  clear_has_java_outer_classname();
+  if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = java_outer_classname_;
+    java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional bool java_multiple_files = 10 [default = false];
 inline bool FileOptions::has_java_multiple_files() const {
-  return _has_bit(2);
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void FileOptions::set_has_java_multiple_files() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void FileOptions::clear_has_java_multiple_files() {
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void FileOptions::clear_java_multiple_files() {
   java_multiple_files_ = false;
-  _clear_bit(2);
+  clear_has_java_multiple_files();
 }
 inline bool FileOptions::java_multiple_files() const {
   return java_multiple_files_;
 }
 inline void FileOptions::set_java_multiple_files(bool value) {
-  _set_bit(2);
+  set_has_java_multiple_files();
   java_multiple_files_ = value;
 }
 
+// optional bool java_generate_equals_and_hash = 20 [default = false];
+inline bool FileOptions::has_java_generate_equals_and_hash() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void FileOptions::set_has_java_generate_equals_and_hash() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void FileOptions::clear_has_java_generate_equals_and_hash() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline void FileOptions::clear_java_generate_equals_and_hash() {
+  java_generate_equals_and_hash_ = false;
+  clear_has_java_generate_equals_and_hash();
+}
+inline bool FileOptions::java_generate_equals_and_hash() const {
+  return java_generate_equals_and_hash_;
+}
+inline void FileOptions::set_java_generate_equals_and_hash(bool value) {
+  set_has_java_generate_equals_and_hash();
+  java_generate_equals_and_hash_ = value;
+}
+
 // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
 inline bool FileOptions::has_optimize_for() const {
-  return _has_bit(3);
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+inline void FileOptions::set_has_optimize_for() {
+  _has_bits_[0] |= 0x00000010u;
+}
+inline void FileOptions::clear_has_optimize_for() {
+  _has_bits_[0] &= ~0x00000010u;
 }
 inline void FileOptions::clear_optimize_for() {
   optimize_for_ = 1;
-  _clear_bit(3);
+  clear_has_optimize_for();
 }
 inline ::google::protobuf::FileOptions_OptimizeMode FileOptions::optimize_for() const {
   return static_cast< ::google::protobuf::FileOptions_OptimizeMode >(optimize_for_);
 }
 inline void FileOptions::set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value) {
   GOOGLE_DCHECK(::google::protobuf::FileOptions_OptimizeMode_IsValid(value));
-  _set_bit(3);
+  set_has_optimize_for();
   optimize_for_ = value;
 }
 
-// optional bool cc_generic_services = 16 [default = true];
+// optional bool cc_generic_services = 16 [default = false];
 inline bool FileOptions::has_cc_generic_services() const {
-  return _has_bit(4);
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+inline void FileOptions::set_has_cc_generic_services() {
+  _has_bits_[0] |= 0x00000020u;
+}
+inline void FileOptions::clear_has_cc_generic_services() {
+  _has_bits_[0] &= ~0x00000020u;
 }
 inline void FileOptions::clear_cc_generic_services() {
-  cc_generic_services_ = true;
-  _clear_bit(4);
+  cc_generic_services_ = false;
+  clear_has_cc_generic_services();
 }
 inline bool FileOptions::cc_generic_services() const {
   return cc_generic_services_;
 }
 inline void FileOptions::set_cc_generic_services(bool value) {
-  _set_bit(4);
+  set_has_cc_generic_services();
   cc_generic_services_ = value;
 }
 
-// optional bool java_generic_services = 17 [default = true];
+// optional bool java_generic_services = 17 [default = false];
 inline bool FileOptions::has_java_generic_services() const {
-  return _has_bit(5);
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+inline void FileOptions::set_has_java_generic_services() {
+  _has_bits_[0] |= 0x00000040u;
+}
+inline void FileOptions::clear_has_java_generic_services() {
+  _has_bits_[0] &= ~0x00000040u;
 }
 inline void FileOptions::clear_java_generic_services() {
-  java_generic_services_ = true;
-  _clear_bit(5);
+  java_generic_services_ = false;
+  clear_has_java_generic_services();
 }
 inline bool FileOptions::java_generic_services() const {
   return java_generic_services_;
 }
 inline void FileOptions::set_java_generic_services(bool value) {
-  _set_bit(5);
+  set_has_java_generic_services();
   java_generic_services_ = value;
 }
 
-// optional bool py_generic_services = 18 [default = true];
+// optional bool py_generic_services = 18 [default = false];
 inline bool FileOptions::has_py_generic_services() const {
-  return _has_bit(6);
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+inline void FileOptions::set_has_py_generic_services() {
+  _has_bits_[0] |= 0x00000080u;
+}
+inline void FileOptions::clear_has_py_generic_services() {
+  _has_bits_[0] &= ~0x00000080u;
 }
 inline void FileOptions::clear_py_generic_services() {
-  py_generic_services_ = true;
-  _clear_bit(6);
+  py_generic_services_ = false;
+  clear_has_py_generic_services();
 }
 inline bool FileOptions::py_generic_services() const {
   return py_generic_services_;
 }
 inline void FileOptions::set_py_generic_services(bool value) {
-  _set_bit(6);
+  set_has_py_generic_services();
   py_generic_services_ = value;
 }
 
@@ -3805,33 +4414,45 @@
 
 // optional bool message_set_wire_format = 1 [default = false];
 inline bool MessageOptions::has_message_set_wire_format() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void MessageOptions::set_has_message_set_wire_format() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void MessageOptions::clear_has_message_set_wire_format() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void MessageOptions::clear_message_set_wire_format() {
   message_set_wire_format_ = false;
-  _clear_bit(0);
+  clear_has_message_set_wire_format();
 }
 inline bool MessageOptions::message_set_wire_format() const {
   return message_set_wire_format_;
 }
 inline void MessageOptions::set_message_set_wire_format(bool value) {
-  _set_bit(0);
+  set_has_message_set_wire_format();
   message_set_wire_format_ = value;
 }
 
 // optional bool no_standard_descriptor_accessor = 2 [default = false];
 inline bool MessageOptions::has_no_standard_descriptor_accessor() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void MessageOptions::set_has_no_standard_descriptor_accessor() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void MessageOptions::clear_has_no_standard_descriptor_accessor() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void MessageOptions::clear_no_standard_descriptor_accessor() {
   no_standard_descriptor_accessor_ = false;
-  _clear_bit(1);
+  clear_has_no_standard_descriptor_accessor();
 }
 inline bool MessageOptions::no_standard_descriptor_accessor() const {
   return no_standard_descriptor_accessor_;
 }
 inline void MessageOptions::set_no_standard_descriptor_accessor(bool value) {
-  _set_bit(1);
+  set_has_no_standard_descriptor_accessor();
   no_standard_descriptor_accessor_ = value;
 }
 
@@ -3866,94 +4487,128 @@
 
 // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
 inline bool FieldOptions::has_ctype() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void FieldOptions::set_has_ctype() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void FieldOptions::clear_has_ctype() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void FieldOptions::clear_ctype() {
   ctype_ = 0;
-  _clear_bit(0);
+  clear_has_ctype();
 }
 inline ::google::protobuf::FieldOptions_CType FieldOptions::ctype() const {
   return static_cast< ::google::protobuf::FieldOptions_CType >(ctype_);
 }
 inline void FieldOptions::set_ctype(::google::protobuf::FieldOptions_CType value) {
   GOOGLE_DCHECK(::google::protobuf::FieldOptions_CType_IsValid(value));
-  _set_bit(0);
+  set_has_ctype();
   ctype_ = value;
 }
 
 // optional bool packed = 2;
 inline bool FieldOptions::has_packed() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void FieldOptions::set_has_packed() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void FieldOptions::clear_has_packed() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void FieldOptions::clear_packed() {
   packed_ = false;
-  _clear_bit(1);
+  clear_has_packed();
 }
 inline bool FieldOptions::packed() const {
   return packed_;
 }
 inline void FieldOptions::set_packed(bool value) {
-  _set_bit(1);
+  set_has_packed();
   packed_ = value;
 }
 
 // optional bool deprecated = 3 [default = false];
 inline bool FieldOptions::has_deprecated() const {
-  return _has_bit(2);
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void FieldOptions::set_has_deprecated() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void FieldOptions::clear_has_deprecated() {
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void FieldOptions::clear_deprecated() {
   deprecated_ = false;
-  _clear_bit(2);
+  clear_has_deprecated();
 }
 inline bool FieldOptions::deprecated() const {
   return deprecated_;
 }
 inline void FieldOptions::set_deprecated(bool value) {
-  _set_bit(2);
+  set_has_deprecated();
   deprecated_ = value;
 }
 
 // optional string experimental_map_key = 9;
 inline bool FieldOptions::has_experimental_map_key() const {
-  return _has_bit(3);
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void FieldOptions::set_has_experimental_map_key() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void FieldOptions::clear_has_experimental_map_key() {
+  _has_bits_[0] &= ~0x00000008u;
 }
 inline void FieldOptions::clear_experimental_map_key() {
-  if (experimental_map_key_ != &_default_experimental_map_key_) {
+  if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) {
     experimental_map_key_->clear();
   }
-  _clear_bit(3);
+  clear_has_experimental_map_key();
 }
 inline const ::std::string& FieldOptions::experimental_map_key() const {
   return *experimental_map_key_;
 }
 inline void FieldOptions::set_experimental_map_key(const ::std::string& value) {
-  _set_bit(3);
-  if (experimental_map_key_ == &_default_experimental_map_key_) {
+  set_has_experimental_map_key();
+  if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) {
     experimental_map_key_ = new ::std::string;
   }
   experimental_map_key_->assign(value);
 }
 inline void FieldOptions::set_experimental_map_key(const char* value) {
-  _set_bit(3);
-  if (experimental_map_key_ == &_default_experimental_map_key_) {
+  set_has_experimental_map_key();
+  if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) {
     experimental_map_key_ = new ::std::string;
   }
   experimental_map_key_->assign(value);
 }
 inline void FieldOptions::set_experimental_map_key(const char* value, size_t size) {
-  _set_bit(3);
-  if (experimental_map_key_ == &_default_experimental_map_key_) {
+  set_has_experimental_map_key();
+  if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) {
     experimental_map_key_ = new ::std::string;
   }
   experimental_map_key_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* FieldOptions::mutable_experimental_map_key() {
-  _set_bit(3);
-  if (experimental_map_key_ == &_default_experimental_map_key_) {
+  set_has_experimental_map_key();
+  if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) {
     experimental_map_key_ = new ::std::string;
   }
   return experimental_map_key_;
 }
+inline ::std::string* FieldOptions::release_experimental_map_key() {
+  clear_has_experimental_map_key();
+  if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = experimental_map_key_;
+    experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
 inline int FieldOptions::uninterpreted_option_size() const {
@@ -4102,59 +4757,81 @@
 
 // required string name_part = 1;
 inline bool UninterpretedOption_NamePart::has_name_part() const {
-  return _has_bit(0);
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void UninterpretedOption_NamePart::set_has_name_part() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void UninterpretedOption_NamePart::clear_has_name_part() {
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void UninterpretedOption_NamePart::clear_name_part() {
-  if (name_part_ != &_default_name_part_) {
+  if (name_part_ != &::google::protobuf::internal::kEmptyString) {
     name_part_->clear();
   }
-  _clear_bit(0);
+  clear_has_name_part();
 }
 inline const ::std::string& UninterpretedOption_NamePart::name_part() const {
   return *name_part_;
 }
 inline void UninterpretedOption_NamePart::set_name_part(const ::std::string& value) {
-  _set_bit(0);
-  if (name_part_ == &_default_name_part_) {
+  set_has_name_part();
+  if (name_part_ == &::google::protobuf::internal::kEmptyString) {
     name_part_ = new ::std::string;
   }
   name_part_->assign(value);
 }
 inline void UninterpretedOption_NamePart::set_name_part(const char* value) {
-  _set_bit(0);
-  if (name_part_ == &_default_name_part_) {
+  set_has_name_part();
+  if (name_part_ == &::google::protobuf::internal::kEmptyString) {
     name_part_ = new ::std::string;
   }
   name_part_->assign(value);
 }
 inline void UninterpretedOption_NamePart::set_name_part(const char* value, size_t size) {
-  _set_bit(0);
-  if (name_part_ == &_default_name_part_) {
+  set_has_name_part();
+  if (name_part_ == &::google::protobuf::internal::kEmptyString) {
     name_part_ = new ::std::string;
   }
   name_part_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* UninterpretedOption_NamePart::mutable_name_part() {
-  _set_bit(0);
-  if (name_part_ == &_default_name_part_) {
+  set_has_name_part();
+  if (name_part_ == &::google::protobuf::internal::kEmptyString) {
     name_part_ = new ::std::string;
   }
   return name_part_;
 }
+inline ::std::string* UninterpretedOption_NamePart::release_name_part() {
+  clear_has_name_part();
+  if (name_part_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = name_part_;
+    name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // required bool is_extension = 2;
 inline bool UninterpretedOption_NamePart::has_is_extension() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void UninterpretedOption_NamePart::set_has_is_extension() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void UninterpretedOption_NamePart::clear_has_is_extension() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void UninterpretedOption_NamePart::clear_is_extension() {
   is_extension_ = false;
-  _clear_bit(1);
+  clear_has_is_extension();
 }
 inline bool UninterpretedOption_NamePart::is_extension() const {
   return is_extension_;
 }
 inline void UninterpretedOption_NamePart::set_is_extension(bool value) {
-  _set_bit(1);
+  set_has_is_extension();
   is_extension_ = value;
 }
 
@@ -4189,135 +4866,326 @@
 
 // optional string identifier_value = 3;
 inline bool UninterpretedOption::has_identifier_value() const {
-  return _has_bit(1);
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void UninterpretedOption::set_has_identifier_value() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void UninterpretedOption::clear_has_identifier_value() {
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void UninterpretedOption::clear_identifier_value() {
-  if (identifier_value_ != &_default_identifier_value_) {
+  if (identifier_value_ != &::google::protobuf::internal::kEmptyString) {
     identifier_value_->clear();
   }
-  _clear_bit(1);
+  clear_has_identifier_value();
 }
 inline const ::std::string& UninterpretedOption::identifier_value() const {
   return *identifier_value_;
 }
 inline void UninterpretedOption::set_identifier_value(const ::std::string& value) {
-  _set_bit(1);
-  if (identifier_value_ == &_default_identifier_value_) {
+  set_has_identifier_value();
+  if (identifier_value_ == &::google::protobuf::internal::kEmptyString) {
     identifier_value_ = new ::std::string;
   }
   identifier_value_->assign(value);
 }
 inline void UninterpretedOption::set_identifier_value(const char* value) {
-  _set_bit(1);
-  if (identifier_value_ == &_default_identifier_value_) {
+  set_has_identifier_value();
+  if (identifier_value_ == &::google::protobuf::internal::kEmptyString) {
     identifier_value_ = new ::std::string;
   }
   identifier_value_->assign(value);
 }
 inline void UninterpretedOption::set_identifier_value(const char* value, size_t size) {
-  _set_bit(1);
-  if (identifier_value_ == &_default_identifier_value_) {
+  set_has_identifier_value();
+  if (identifier_value_ == &::google::protobuf::internal::kEmptyString) {
     identifier_value_ = new ::std::string;
   }
   identifier_value_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* UninterpretedOption::mutable_identifier_value() {
-  _set_bit(1);
-  if (identifier_value_ == &_default_identifier_value_) {
+  set_has_identifier_value();
+  if (identifier_value_ == &::google::protobuf::internal::kEmptyString) {
     identifier_value_ = new ::std::string;
   }
   return identifier_value_;
 }
+inline ::std::string* UninterpretedOption::release_identifier_value() {
+  clear_has_identifier_value();
+  if (identifier_value_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = identifier_value_;
+    identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
 
 // optional uint64 positive_int_value = 4;
 inline bool UninterpretedOption::has_positive_int_value() const {
-  return _has_bit(2);
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void UninterpretedOption::set_has_positive_int_value() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void UninterpretedOption::clear_has_positive_int_value() {
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void UninterpretedOption::clear_positive_int_value() {
   positive_int_value_ = GOOGLE_ULONGLONG(0);
-  _clear_bit(2);
+  clear_has_positive_int_value();
 }
 inline ::google::protobuf::uint64 UninterpretedOption::positive_int_value() const {
   return positive_int_value_;
 }
 inline void UninterpretedOption::set_positive_int_value(::google::protobuf::uint64 value) {
-  _set_bit(2);
+  set_has_positive_int_value();
   positive_int_value_ = value;
 }
 
 // optional int64 negative_int_value = 5;
 inline bool UninterpretedOption::has_negative_int_value() const {
-  return _has_bit(3);
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void UninterpretedOption::set_has_negative_int_value() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void UninterpretedOption::clear_has_negative_int_value() {
+  _has_bits_[0] &= ~0x00000008u;
 }
 inline void UninterpretedOption::clear_negative_int_value() {
   negative_int_value_ = GOOGLE_LONGLONG(0);
-  _clear_bit(3);
+  clear_has_negative_int_value();
 }
 inline ::google::protobuf::int64 UninterpretedOption::negative_int_value() const {
   return negative_int_value_;
 }
 inline void UninterpretedOption::set_negative_int_value(::google::protobuf::int64 value) {
-  _set_bit(3);
+  set_has_negative_int_value();
   negative_int_value_ = value;
 }
 
 // optional double double_value = 6;
 inline bool UninterpretedOption::has_double_value() const {
-  return _has_bit(4);
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+inline void UninterpretedOption::set_has_double_value() {
+  _has_bits_[0] |= 0x00000010u;
+}
+inline void UninterpretedOption::clear_has_double_value() {
+  _has_bits_[0] &= ~0x00000010u;
 }
 inline void UninterpretedOption::clear_double_value() {
   double_value_ = 0;
-  _clear_bit(4);
+  clear_has_double_value();
 }
 inline double UninterpretedOption::double_value() const {
   return double_value_;
 }
 inline void UninterpretedOption::set_double_value(double value) {
-  _set_bit(4);
+  set_has_double_value();
   double_value_ = value;
 }
 
 // optional bytes string_value = 7;
 inline bool UninterpretedOption::has_string_value() const {
-  return _has_bit(5);
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+inline void UninterpretedOption::set_has_string_value() {
+  _has_bits_[0] |= 0x00000020u;
+}
+inline void UninterpretedOption::clear_has_string_value() {
+  _has_bits_[0] &= ~0x00000020u;
 }
 inline void UninterpretedOption::clear_string_value() {
-  if (string_value_ != &_default_string_value_) {
+  if (string_value_ != &::google::protobuf::internal::kEmptyString) {
     string_value_->clear();
   }
-  _clear_bit(5);
+  clear_has_string_value();
 }
 inline const ::std::string& UninterpretedOption::string_value() const {
   return *string_value_;
 }
 inline void UninterpretedOption::set_string_value(const ::std::string& value) {
-  _set_bit(5);
-  if (string_value_ == &_default_string_value_) {
+  set_has_string_value();
+  if (string_value_ == &::google::protobuf::internal::kEmptyString) {
     string_value_ = new ::std::string;
   }
   string_value_->assign(value);
 }
 inline void UninterpretedOption::set_string_value(const char* value) {
-  _set_bit(5);
-  if (string_value_ == &_default_string_value_) {
+  set_has_string_value();
+  if (string_value_ == &::google::protobuf::internal::kEmptyString) {
     string_value_ = new ::std::string;
   }
   string_value_->assign(value);
 }
 inline void UninterpretedOption::set_string_value(const void* value, size_t size) {
-  _set_bit(5);
-  if (string_value_ == &_default_string_value_) {
+  set_has_string_value();
+  if (string_value_ == &::google::protobuf::internal::kEmptyString) {
     string_value_ = new ::std::string;
   }
   string_value_->assign(reinterpret_cast<const char*>(value), size);
 }
 inline ::std::string* UninterpretedOption::mutable_string_value() {
-  _set_bit(5);
-  if (string_value_ == &_default_string_value_) {
+  set_has_string_value();
+  if (string_value_ == &::google::protobuf::internal::kEmptyString) {
     string_value_ = new ::std::string;
   }
   return string_value_;
 }
+inline ::std::string* UninterpretedOption::release_string_value() {
+  clear_has_string_value();
+  if (string_value_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = string_value_;
+    string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
+
+// optional string aggregate_value = 8;
+inline bool UninterpretedOption::has_aggregate_value() const {
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+inline void UninterpretedOption::set_has_aggregate_value() {
+  _has_bits_[0] |= 0x00000040u;
+}
+inline void UninterpretedOption::clear_has_aggregate_value() {
+  _has_bits_[0] &= ~0x00000040u;
+}
+inline void UninterpretedOption::clear_aggregate_value() {
+  if (aggregate_value_ != &::google::protobuf::internal::kEmptyString) {
+    aggregate_value_->clear();
+  }
+  clear_has_aggregate_value();
+}
+inline const ::std::string& UninterpretedOption::aggregate_value() const {
+  return *aggregate_value_;
+}
+inline void UninterpretedOption::set_aggregate_value(const ::std::string& value) {
+  set_has_aggregate_value();
+  if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) {
+    aggregate_value_ = new ::std::string;
+  }
+  aggregate_value_->assign(value);
+}
+inline void UninterpretedOption::set_aggregate_value(const char* value) {
+  set_has_aggregate_value();
+  if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) {
+    aggregate_value_ = new ::std::string;
+  }
+  aggregate_value_->assign(value);
+}
+inline void UninterpretedOption::set_aggregate_value(const char* value, size_t size) {
+  set_has_aggregate_value();
+  if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) {
+    aggregate_value_ = new ::std::string;
+  }
+  aggregate_value_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* UninterpretedOption::mutable_aggregate_value() {
+  set_has_aggregate_value();
+  if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) {
+    aggregate_value_ = new ::std::string;
+  }
+  return aggregate_value_;
+}
+inline ::std::string* UninterpretedOption::release_aggregate_value() {
+  clear_has_aggregate_value();
+  if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) {
+    return NULL;
+  } else {
+    ::std::string* temp = aggregate_value_;
+    aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+    return temp;
+  }
+}
+
+// -------------------------------------------------------------------
+
+// SourceCodeInfo_Location
+
+// repeated int32 path = 1 [packed = true];
+inline int SourceCodeInfo_Location::path_size() const {
+  return path_.size();
+}
+inline void SourceCodeInfo_Location::clear_path() {
+  path_.Clear();
+}
+inline ::google::protobuf::int32 SourceCodeInfo_Location::path(int index) const {
+  return path_.Get(index);
+}
+inline void SourceCodeInfo_Location::set_path(int index, ::google::protobuf::int32 value) {
+  path_.Set(index, value);
+}
+inline void SourceCodeInfo_Location::add_path(::google::protobuf::int32 value) {
+  path_.Add(value);
+}
+inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+SourceCodeInfo_Location::path() const {
+  return path_;
+}
+inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+SourceCodeInfo_Location::mutable_path() {
+  return &path_;
+}
+
+// repeated int32 span = 2 [packed = true];
+inline int SourceCodeInfo_Location::span_size() const {
+  return span_.size();
+}
+inline void SourceCodeInfo_Location::clear_span() {
+  span_.Clear();
+}
+inline ::google::protobuf::int32 SourceCodeInfo_Location::span(int index) const {
+  return span_.Get(index);
+}
+inline void SourceCodeInfo_Location::set_span(int index, ::google::protobuf::int32 value) {
+  span_.Set(index, value);
+}
+inline void SourceCodeInfo_Location::add_span(::google::protobuf::int32 value) {
+  span_.Add(value);
+}
+inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+SourceCodeInfo_Location::span() const {
+  return span_;
+}
+inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+SourceCodeInfo_Location::mutable_span() {
+  return &span_;
+}
+
+// -------------------------------------------------------------------
+
+// SourceCodeInfo
+
+// repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+inline int SourceCodeInfo::location_size() const {
+  return location_.size();
+}
+inline void SourceCodeInfo::clear_location() {
+  location_.Clear();
+}
+inline const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const {
+  return location_.Get(index);
+}
+inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) {
+  return location_.Mutable(index);
+}
+inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location() {
+  return location_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+SourceCodeInfo::location() const {
+  return location_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
+SourceCodeInfo::mutable_location() {
+  return &location_;
+}
 
 
 // @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index cc04aa8..233f879 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -67,6 +67,12 @@
   repeated FieldDescriptorProto extension = 7;
 
   optional FileOptions options = 8;
+
+  // This field contains optional information about the original source code.
+  // You may safely remove this entire field whithout harming runtime
+  // functionality of the descriptors -- the information is needed only by
+  // development tools.
+  optional SourceCodeInfo source_code_info = 9;
 }
 
 // Describes a message type.
@@ -245,6 +251,12 @@
   // top-level extensions defined in the file.
   optional bool java_multiple_files = 10 [default=false];
 
+  // If set true, then the Java code generator will generate equals() and
+  // hashCode() methods for all messages defined in the .proto file. This is
+  // purely a speed optimization, as the AbstractMessage base class includes
+  // reflection-based implementations of these methods.
+  optional bool java_generate_equals_and_hash = 20 [default=false];
+
   // Generated classes can be optimized for speed or code size.
   enum OptimizeMode {
     SPEED = 1;        // Generate complete code for parsing, serialization,
@@ -264,13 +276,12 @@
   // early versions of proto2.
   //
   // Generic services are now considered deprecated in favor of using plugins
-  // that generate code specific to your particular RPC system.  If you are
-  // using such a plugin, set these to false.  In the future, we may change
-  // the default to false, so if you explicitly want generic services, you
-  // should explicitly set these to true.
-  optional bool cc_generic_services = 16 [default=true];
-  optional bool java_generic_services = 17 [default=true];
-  optional bool py_generic_services = 18 [default=true];
+  // that generate code specific to your particular RPC system.  Therefore,
+  // these default to false.  Old code which depends on generic services should
+  // explicitly set them to true.
+  optional bool cc_generic_services = 16 [default=false];
+  optional bool java_generic_services = 17 [default=false];
+  optional bool py_generic_services = 18 [default=false];
 
   // The parser stores options it doesn't recognize here. See above.
   repeated UninterpretedOption uninterpreted_option = 999;
@@ -430,4 +441,93 @@
   optional int64 negative_int_value = 5;
   optional double double_value = 6;
   optional bytes string_value = 7;
+  optional string aggregate_value = 8;
+}
+
+// ===================================================================
+// Optional source code info
+
+// Encapsulates information about the original source file from which a
+// FileDescriptorProto was generated.
+message SourceCodeInfo {
+  // A Location identifies a piece of source code in a .proto file which
+  // corresponds to a particular definition.  This information is intended
+  // to be useful to IDEs, code indexers, documentation generators, and similar
+  // tools.
+  //
+  // For example, say we have a file like:
+  //   message Foo {
+  //     optional string foo = 1;
+  //   }
+  // Let's look at just the field definition:
+  //   optional string foo = 1;
+  //   ^       ^^     ^^  ^  ^^^
+  //   a       bc     de  f  ghi
+  // We have the following locations:
+  //   span   path               represents
+  //   [a,i)  [ 4, 0, 2, 0 ]     The whole field definition.
+  //   [a,b)  [ 4, 0, 2, 0, 4 ]  The label (optional).
+  //   [c,d)  [ 4, 0, 2, 0, 5 ]  The type (string).
+  //   [e,f)  [ 4, 0, 2, 0, 1 ]  The name (foo).
+  //   [g,h)  [ 4, 0, 2, 0, 3 ]  The number (1).
+  //
+  // Notes:
+  // - A location may refer to a repeated field itself (i.e. not to any
+  //   particular index within it).  This is used whenever a set of elements are
+  //   logically enclosed in a single code segment.  For example, an entire
+  //   extend block (possibly containing multiple extension definitions) will
+  //   have an outer location whose path refers to the "extensions" repeated
+  //   field without an index.
+  // - Multiple locations may have the same path.  This happens when a single
+  //   logical declaration is spread out across multiple places.  The most
+  //   obvious example is the "extend" block again -- there may be multiple
+  //   extend blocks in the same scope, each of which will have the same path.
+  // - A location's span is not always a subset of its parent's span.  For
+  //   example, the "extendee" of an extension declaration appears at the
+  //   beginning of the "extend" block and is shared by all extensions within
+  //   the block.
+  // - Just because a location's span is a subset of some other location's span
+  //   does not mean that it is a descendent.  For example, a "group" defines
+  //   both a type and a field in a single declaration.  Thus, the locations
+  //   corresponding to the type and field and their components will overlap.
+  // - Code which tries to interpret locations should probably be designed to
+  //   ignore those that it doesn't understand, as more types of locations could
+  //   be recorded in the future.
+  repeated Location location = 1;
+  message Location {
+    // Identifies which part of the FileDescriptorProto was defined at this
+    // location.
+    //
+    // Each element is a field number or an index.  They form a path from
+    // the root FileDescriptorProto to the place where the definition.  For
+    // example, this path:
+    //   [ 4, 3, 2, 7, 1 ]
+    // refers to:
+    //   file.message_type(3)  // 4, 3
+    //       .field(7)         // 2, 7
+    //       .name()           // 1
+    // This is because FileDescriptorProto.message_type has field number 4:
+    //   repeated DescriptorProto message_type = 4;
+    // and DescriptorProto.field has field number 2:
+    //   repeated FieldDescriptorProto field = 2;
+    // and FieldDescriptorProto.name has field number 1:
+    //   optional string name = 1;
+    //
+    // Thus, the above path gives the location of a field name.  If we removed
+    // the last element:
+    //   [ 4, 3, 2, 7 ]
+    // this path refers to the whole field declaration (from the beginning
+    // of the label to the terminating semicolon).
+    repeated int32 path = 1 [packed=true];
+
+    // Always has exactly three or four elements: start line, start column,
+    // end line (optional, otherwise assumed same as start line), end column.
+    // These are packed into a single field for efficiency.  Note that line
+    // and column numbers are zero-based -- typically you will want to add
+    // 1 to each before displaying to a user.
+    repeated int32 span = 2 [packed=true];
+
+    // TODO(kenton):  Record comments appearing before and after the
+    // declaration.
+  }
 }
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index d70c9bf..55aebfd 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -2212,6 +2212,45 @@
   EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo());
 }
 
+// Check that aggregate options were parsed and saved correctly in
+// the appropriate descriptors.
+TEST(CustomOptions, AggregateOptions) {
+  const Descriptor* msg = protobuf_unittest::AggregateMessage::descriptor();
+  const FileDescriptor* file = msg->file();
+  const FieldDescriptor* field = msg->FindFieldByName("fieldname");
+  const EnumDescriptor* enumd = file->FindEnumTypeByName("AggregateEnum");
+  const EnumValueDescriptor* enumv = enumd->FindValueByName("VALUE");
+  const ServiceDescriptor* service = file->FindServiceByName(
+      "AggregateService");
+  const MethodDescriptor* method = service->FindMethodByName("Method");
+
+  // Tests for the different types of data embedded in fileopt
+  const protobuf_unittest::Aggregate& file_options =
+      file->options().GetExtension(protobuf_unittest::fileopt);
+  EXPECT_EQ(100, file_options.i());
+  EXPECT_EQ("FileAnnotation", file_options.s());
+  EXPECT_EQ("NestedFileAnnotation", file_options.sub().s());
+  EXPECT_EQ("FileExtensionAnnotation",
+            file_options.file().GetExtension(protobuf_unittest::fileopt).s());
+  EXPECT_EQ("EmbeddedMessageSetElement",
+            file_options.mset().GetExtension(
+                protobuf_unittest::AggregateMessageSetElement
+                ::message_set_extension).s());
+
+  // Simple tests for all the other types of annotations
+  EXPECT_EQ("MessageAnnotation",
+            msg->options().GetExtension(protobuf_unittest::msgopt).s());
+  EXPECT_EQ("FieldAnnotation",
+            field->options().GetExtension(protobuf_unittest::fieldopt).s());
+  EXPECT_EQ("EnumAnnotation",
+            enumd->options().GetExtension(protobuf_unittest::enumopt).s());
+  EXPECT_EQ("EnumValueAnnotation",
+            enumv->options().GetExtension(protobuf_unittest::enumvalopt).s());
+  EXPECT_EQ("ServiceAnnotation",
+            service->options().GetExtension(protobuf_unittest::serviceopt).s());
+  EXPECT_EQ("MethodAnnotation",
+            method->options().GetExtension(protobuf_unittest::methodopt).s());
+}
 
 // ===================================================================
 
@@ -3425,25 +3464,50 @@
     "string option \"foo\".\n");
 }
 
-TEST_F(ValidationErrorTest, TryingToSetMessageValuedOption) {
+// Helper function for tests that check for aggregate value parsing
+// errors.  The "value" argument is embedded inside the
+// "uninterpreted_option" portion of the result.
+static string EmbedAggregateValue(const char* value) {
+  return strings::Substitute(
+      "name: \"foo.proto\" "
+      "dependency: \"google/protobuf/descriptor.proto\" "
+      "message_type { name: \"Foo\" } "
+      "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
+      "            type: TYPE_MESSAGE type_name: \"Foo\" "
+      "            extendee: \"google.protobuf.FileOptions\" }"
+      "options { uninterpreted_option { name { name_part: \"foo\" "
+      "                                        is_extension: true } "
+      "                                 $0 } }",
+      value);
+}
+
+TEST_F(ValidationErrorTest, AggregateValueNotFound) {
   BuildDescriptorMessagesInTestPool();
 
   BuildFileWithErrors(
-    "name: \"foo.proto\" "
-    "dependency: \"google/protobuf/descriptor.proto\" "
-    "message_type { "
-    "  name: \"TestMessage\" "
-    "  field { name:\"baz\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING }"
-    "}"
-    "extension { name: \"bar\" number: 7672757 label: LABEL_OPTIONAL "
-    "            type: TYPE_MESSAGE type_name: \"TestMessage\" "
-    "            extendee: \"google.protobuf.FileOptions\" }"
-    "options { uninterpreted_option { name { name_part: \"bar\" "
-    "                                        is_extension: true } "
-    "                                 identifier_value: \"QUUX\" } }",
+      EmbedAggregateValue("string_value: \"\""),
+      "foo.proto: foo.proto: OPTION_VALUE: Option \"foo\" is a message. "
+      "To set the entire message, use syntax like "
+      "\"foo = { <proto text format> }\". To set fields within it, use "
+      "syntax like \"foo.foo = value\".\n");
+}
 
-    "foo.proto: foo.proto: OPTION_NAME: Option field \"(bar)\" cannot be of "
-    "message type.\n");
+TEST_F(ValidationErrorTest, AggregateValueParseError) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+      EmbedAggregateValue("aggregate_value: \"1+2\""),
+      "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
+      "value for \"foo\": Expected identifier.\n");
+}
+
+TEST_F(ValidationErrorTest, AggregateValueUnknownFields) {
+  BuildDescriptorMessagesInTestPool();
+
+  BuildFileWithErrors(
+      EmbedAggregateValue("aggregate_value: \"x:100\""),
+      "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
+      "value for \"foo\": Message type \"Foo\" has no field named \"x\".\n");
 }
 
 TEST_F(ValidationErrorTest, NotLiteImportsLite) {
@@ -3483,7 +3547,11 @@
 TEST_F(ValidationErrorTest, NoLiteServices) {
   BuildFileWithErrors(
     "name: \"foo.proto\" "
-    "options { optimize_for: LITE_RUNTIME } "
+    "options {"
+    "  optimize_for: LITE_RUNTIME"
+    "  cc_generic_services: true"
+    "  java_generic_services: true"
+    "} "
     "service { name: \"Foo\" }",
 
     "foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot "
@@ -3497,7 +3565,7 @@
     "  cc_generic_services: false"
     "  java_generic_services: false"
     "} "
-    "service { name: \"Foo\" }");
+    "service { name: \"Bar\" }");
 }
 
 TEST_F(ValidationErrorTest, RollbackAfterError) {
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index 6084885..1a6f5df 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -186,6 +186,18 @@
   return iter->second.GetSize();
 }
 
+FieldType ExtensionSet::ExtensionType(int number) const {
+  map<int, Extension>::const_iterator iter = extensions_.find(number);
+  if (iter == extensions_.end()) {
+    GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (1). ";
+    return 0;
+  }
+  if (iter->second.is_cleared) {
+    GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (2). ";
+  }
+  return iter->second.type;
+}
+
 void ExtensionSet::ClearExtension(int number) {
   map<int, Extension>::iterator iter = extensions_.find(number);
   if (iter == extensions_.end()) return;
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index 14d5d15..ac1ada0 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -39,11 +39,11 @@
 #define GOOGLE_PROTOBUF_EXTENSION_SET_H__
 
 #include <vector>
-#include <stack>
 #include <map>
 #include <utility>
 #include <string>
 
+
 #include <google/protobuf/stubs/common.h>
 
 namespace google {
@@ -214,6 +214,7 @@
 
   bool Has(int number) const;
   int ExtensionSize(int number) const;   // Size of a repeated extension.
+  FieldType ExtensionType(int number) const;
   void ClearExtension(int number);
 
   // singular fields -------------------------------------------------
@@ -451,6 +452,7 @@
     int SpaceUsedExcludingSelf() const;
   };
 
+
   // Gets the extension with the given number, creating it if it does not
   // already exist.  Returns true if the extension did not already exist.
   bool MaybeNewExtension(int number, const FieldDescriptor* descriptor,
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index 0f065ff..a0dd75c 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -45,8 +45,6 @@
 namespace protobuf {
 namespace internal {
 
-namespace { const string kEmptyString; }
-
 int StringSpaceUsedExcludingSelf(const string& str) {
   const void* start = &str;
   const void* end = &str + 1;
@@ -69,7 +67,6 @@
 }
 
 const string& NameOfEnum(const EnumDescriptor* descriptor, int value) {
-  static string kEmptyString;
   const EnumValueDescriptor* d = descriptor->FindValueByNumber(value);
   return (d == NULL ? kEmptyString : d->name());
 }
diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc
index 7ac015d..76e547b 100644
--- a/src/google/protobuf/generated_message_util.cc
+++ b/src/google/protobuf/generated_message_util.cc
@@ -47,6 +47,8 @@
   return std::numeric_limits<double>::quiet_NaN();
 }
 
+const ::std::string kEmptyString;
+
 
 }  // namespace internal
 }  // namespace protobuf
diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h
index daa16f7..1a2343d 100644
--- a/src/google/protobuf/generated_message_util.h
+++ b/src/google/protobuf/generated_message_util.h
@@ -38,6 +38,8 @@
 #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
 #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
 
+#include <string>
+
 #include <google/protobuf/stubs/common.h>
 
 
@@ -66,8 +68,11 @@
 
 
 // Constants for special floating point values.
-LIBPROTOBUF_EXPORT double Infinity();
-LIBPROTOBUF_EXPORT double NaN();
+double Infinity();
+double NaN();
+
+// Constant used for empty default strings.
+extern const ::std::string kEmptyString;
 
 
 }  // namespace internal
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index 6a91a13..57d486f 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -56,6 +56,15 @@
 static const int kMaxVarint32Bytes = 5;
 
 
+inline bool NextNonEmpty(ZeroCopyInputStream* input,
+                         const void** data, int* size) {
+  bool success;
+  do {
+    success = input->Next(data, size);
+  } while (success && *size == 0);
+  return success;
+}
+
 }  // namespace
 
 // CodedInputStream ==================================================
@@ -489,7 +498,7 @@
 
   const void* void_buffer;
   int buffer_size;
-  if (input_->Next(&void_buffer, &buffer_size)) {
+  if (NextNonEmpty(input_, &void_buffer, &buffer_size)) {
     buffer_ = reinterpret_cast<const uint8*>(void_buffer);
     buffer_end_ = buffer_ + buffer_size;
     GOOGLE_CHECK_GE(buffer_size, 0);
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index 93effc8..73a54dd 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -129,8 +129,8 @@
 #endif
 #include <google/protobuf/stubs/common.h>
 
-namespace google {
 
+namespace google {
 namespace protobuf {
 
 class DescriptorPool;
@@ -782,7 +782,8 @@
 }
 
 inline bool CodedInputStream::ReadLittleEndian32(uint32* value) {
-#if defined(PROTOBUF_LITTLE_ENDIAN)
+#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \
+    defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
   if (GOOGLE_PREDICT_TRUE(BufferSize() >= static_cast<int>(sizeof(*value)))) {
     memcpy(value, buffer_, sizeof(*value));
     Advance(sizeof(*value));
@@ -796,7 +797,8 @@
 }
 
 inline bool CodedInputStream::ReadLittleEndian64(uint64* value) {
-#if defined(PROTOBUF_LITTLE_ENDIAN)
+#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \
+    defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
   if (GOOGLE_PREDICT_TRUE(BufferSize() >= static_cast<int>(sizeof(*value)))) {
     memcpy(value, buffer_, sizeof(*value));
     Advance(sizeof(*value));
@@ -1093,10 +1095,10 @@
 }  // namespace io
 }  // namespace protobuf
 
-}  // namespace google
 
 #if defined(_MSC_VER) && _MSC_VER >= 1300
   #pragma runtime_checks("c", restore)
 #endif  // _MSC_VER
 
+}  // namespace google
 #endif  // GOOGLE_PROTOBUF_IO_CODED_STREAM_H__
diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc
index 7d29833..ff268ab 100644
--- a/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/src/google/protobuf/io/coded_stream_unittest.cc
@@ -208,6 +208,33 @@
   EXPECT_EQ(kVarintCases_case.size, input.ByteCount());
 }
 
+// This is the regression test that verifies that there is no issues
+// with the empty input buffers handling.
+TEST_F(CodedStreamTest, EmptyInputBeforeEos) {
+  class In : public ZeroCopyInputStream {
+   public:
+    In() : count_(0) {}
+   private:
+    virtual bool Next(const void** data, int* size) {
+      *data = NULL;
+      *size = 0;
+      return count_++ < 2;
+    }
+    virtual void BackUp(int count)  {
+      GOOGLE_LOG(FATAL) << "Tests never call this.";
+    }
+    virtual bool Skip(int count) {
+      GOOGLE_LOG(FATAL) << "Tests never call this.";
+      return false;
+    }
+    virtual int64 ByteCount() const { return 0; }
+    int count_;
+  } in;
+  CodedInputStream input(&in);
+  input.ReadTag();
+  EXPECT_TRUE(input.ConsumedEntireMessage());
+}
+
 TEST_1D(CodedStreamTest, ExpectTag, kVarintCases) {
   // Leave one byte at the beginning of the buffer so we can read it
   // to force the first buffer to be loaded.
@@ -995,6 +1022,7 @@
   EXPECT_FALSE(coded_input.ConsumedEntireMessage());
 }
 
+
 TEST_F(CodedStreamTest, RecursionLimit) {
   ArrayInputStream input(buffer_, sizeof(buffer_));
   CodedInputStream coded_input(&input);
diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc
index 84d277f..0f1ff87 100644
--- a/src/google/protobuf/io/gzip_stream.cc
+++ b/src/google/protobuf/io/gzip_stream.cc
@@ -73,6 +73,17 @@
   zerror_ = inflateEnd(&zcontext_);
 }
 
+static inline int internalInflateInit2(
+    z_stream* zcontext, GzipInputStream::Format format) {
+  int windowBitsFormat = 0;
+  switch (format) {
+    case GzipInputStream::GZIP: windowBitsFormat = 16; break;
+    case GzipInputStream::AUTO: windowBitsFormat = 32; break;
+    case GzipInputStream::ZLIB: windowBitsFormat = 0; break;
+  }
+  return inflateInit2(zcontext, /* windowBits */15 | windowBitsFormat);
+}
+
 int GzipInputStream::Inflate(int flush) {
   if ((zerror_ == Z_OK) && (zcontext_.avail_out == 0)) {
     // previous inflate filled output buffer. don't change input params yet.
@@ -89,14 +100,7 @@
     zcontext_.next_in = static_cast<Bytef*>(const_cast<void*>(in));
     zcontext_.avail_in = in_size;
     if (first) {
-      int windowBitsFormat = 0;
-      switch (format_) {
-        case GZIP: windowBitsFormat = 16; break;
-        case AUTO: windowBitsFormat = 32; break;
-        case ZLIB: windowBitsFormat = 0; break;
-      }
-      int error = inflateInit2(&zcontext_,
-        /* windowBits */15 | windowBitsFormat);
+      int error = internalInflateInit2(&zcontext_, format_);
       if (error != Z_OK) {
         return error;
       }
@@ -127,9 +131,21 @@
     return true;
   }
   if (zerror_ == Z_STREAM_END) {
-    *data = NULL;
-    *size = 0;
-    return false;
+    if (zcontext_.next_out != NULL) {
+      // sub_stream_ may have concatenated streams to follow
+      zerror_ = inflateEnd(&zcontext_);
+      if (zerror_ != Z_OK) {
+        return false;
+      }
+      zerror_ = internalInflateInit2(&zcontext_, format_);
+      if (zerror_ != Z_OK) {
+        return false;
+      }
+    } else {
+      *data = NULL;
+      *size = 0;
+      return false;
+    }
   }
   zerror_ = Inflate(Z_NO_FLUSH);
   if ((zerror_ == Z_STREAM_END) && (zcontext_.next_out == NULL)) {
@@ -251,8 +267,7 @@
     }
     error = deflate(&zcontext_, flush);
   } while (error == Z_OK && zcontext_.avail_out == 0);
-  if (((flush == Z_FULL_FLUSH) || (flush == Z_FINISH))
-      && (zcontext_.avail_out != sub_data_size_)) {
+  if ((flush == Z_FULL_FLUSH) || (flush == Z_FINISH)) {
     // Notify lower layer of data.
     sub_stream_->BackUp(zcontext_.avail_out);
     // We don't own the buffer anymore.
diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc
index c7d3074..9ab90de 100644
--- a/src/google/protobuf/io/printer.cc
+++ b/src/google/protobuf/io/printer.cc
@@ -132,6 +132,17 @@
   Print(vars, text);
 }
 
+void Printer::Print(const char* text,
+                    const char* variable1, const string& value1,
+                    const char* variable2, const string& value2,
+                    const char* variable3, const string& value3) {
+  map<string, string> vars;
+  vars[variable1] = value1;
+  vars[variable2] = value2;
+  vars[variable3] = value3;
+  Print(vars, text);
+}
+
 void Printer::Indent() {
   indent_ += "  ";
 }
diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h
index de08538..5be4854 100644
--- a/src/google/protobuf/io/printer.h
+++ b/src/google/protobuf/io/printer.h
@@ -82,7 +82,11 @@
   // Like the first Print(), except the substitutions are given as parameters.
   void Print(const char* text, const char* variable1, const string& value1,
                                const char* variable2, const string& value2);
-  // TODO(kenton):  Overloaded versions with more variables?  Two seems
+  // Like the first Print(), except the substitutions are given as parameters.
+  void Print(const char* text, const char* variable1, const string& value1,
+                               const char* variable2, const string& value2,
+                               const char* variable3, const string& value3);
+  // TODO(kenton):  Overloaded versions with more variables?  Three seems
   //   to be enough.
 
   // Indent text by two spaces.  After calling Indent(), two spaces will be
diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc
index 38fa351..513831d 100644
--- a/src/google/protobuf/io/tokenizer.cc
+++ b/src/google/protobuf/io/tokenizer.cc
@@ -193,6 +193,7 @@
 
   current_.line = 0;
   current_.column = 0;
+  current_.end_column = 0;
   current_.type = TYPE_START;
 
   Refresh();
@@ -277,6 +278,7 @@
     current_.text.append(buffer_ + token_start_, buffer_pos_ - token_start_);
   }
   token_start_ = -1;
+  current_.end_column = column_;
 }
 
 // -------------------------------------------------------------------
@@ -462,7 +464,7 @@
 // -------------------------------------------------------------------
 
 bool Tokenizer::Next() {
-  TokenType last_token_type = current_.type;
+  previous_ = current_;
 
   // Did we skip any characters after the last token?
   bool skipped_stuff = false;
@@ -517,7 +519,7 @@
 
         if (TryConsumeOne<Digit>()) {
           // It's a floating-point number.
-          if (last_token_type == TYPE_IDENTIFIER && !skipped_stuff) {
+          if (previous_.type == TYPE_IDENTIFIER && !skipped_stuff) {
             // We don't accept syntax like "blah.123".
             error_collector_->AddError(line_, column_ - 2,
               "Need space between identifier and decimal point.");
@@ -551,6 +553,7 @@
   current_.text.clear();
   current_.line = line_;
   current_.column = column_;
+  current_.end_column = column_;
   return false;
 }
 
diff --git a/src/google/protobuf/io/tokenizer.h b/src/google/protobuf/io/tokenizer.h
index d115161..8f759ab 100644
--- a/src/google/protobuf/io/tokenizer.h
+++ b/src/google/protobuf/io/tokenizer.h
@@ -122,12 +122,17 @@
     // the token within the input stream.  They are zero-based.
     int line;
     int column;
+    int end_column;
   };
 
   // Get the current token.  This is updated when Next() is called.  Before
   // the first call to Next(), current() has type TYPE_START and no contents.
   const Token& current();
 
+  // Return the previous token -- i.e. what current() returned before the
+  // previous call to Next().
+  const Token& previous();
+
   // Advance to the next token.  Returns false if the end of the input is
   // reached.
   bool Next();
@@ -180,6 +185,7 @@
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Tokenizer);
 
   Token current_;           // Returned by current().
+  Token previous_;          // Returned by previous().
 
   ZeroCopyInputStream* input_;
   ErrorCollector* error_collector_;
@@ -291,6 +297,10 @@
   return current_;
 }
 
+inline const Tokenizer::Token& Tokenizer::previous() {
+  return previous_;
+}
+
 inline void Tokenizer::ParseString(const string& text, string* output) {
   output->clear();
   ParseStringAppend(text, output);
diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc
index 358ec56..106d080 100644
--- a/src/google/protobuf/io/tokenizer_unittest.cc
+++ b/src/google/protobuf/io/tokenizer_unittest.cc
@@ -257,6 +257,7 @@
   EXPECT_EQ("", tokenizer.current().text);
   EXPECT_EQ(0, tokenizer.current().line);
   EXPECT_EQ(0, tokenizer.current().column);
+  EXPECT_EQ(0, tokenizer.current().end_column);
 
   // Parse the token.
   ASSERT_TRUE(tokenizer.Next());
@@ -268,6 +269,8 @@
   // Check that it is located at the beginning of the input
   EXPECT_EQ(0, tokenizer.current().line);
   EXPECT_EQ(0, tokenizer.current().column);
+  EXPECT_EQ(kSimpleTokenCases_case.input.size(),
+            tokenizer.current().end_column);
 
   // There should be no more input.
   EXPECT_FALSE(tokenizer.Next());
@@ -277,6 +280,8 @@
   EXPECT_EQ("", tokenizer.current().text);
   EXPECT_EQ(0, tokenizer.current().line);
   EXPECT_EQ(kSimpleTokenCases_case.input.size(), tokenizer.current().column);
+  EXPECT_EQ(kSimpleTokenCases_case.input.size(),
+            tokenizer.current().end_column);
 
   // There should be no errors.
   EXPECT_TRUE(error_collector.text_.empty());
@@ -339,76 +344,83 @@
 
   // Test all token types at the same time.
   { "foo 1 1.2 + 'bar'", {
-    { Tokenizer::TYPE_IDENTIFIER, "foo"  , 0,  0 },
-    { Tokenizer::TYPE_INTEGER   , "1"    , 0,  4 },
-    { Tokenizer::TYPE_FLOAT     , "1.2"  , 0,  6 },
-    { Tokenizer::TYPE_SYMBOL    , "+"    , 0, 10 },
-    { Tokenizer::TYPE_STRING    , "'bar'", 0, 12 },
-    { Tokenizer::TYPE_END       , ""     , 0, 17 },
+    { Tokenizer::TYPE_IDENTIFIER, "foo"  , 0,  0,  3 },
+    { Tokenizer::TYPE_INTEGER   , "1"    , 0,  4,  5 },
+    { Tokenizer::TYPE_FLOAT     , "1.2"  , 0,  6,  9 },
+    { Tokenizer::TYPE_SYMBOL    , "+"    , 0, 10, 11 },
+    { Tokenizer::TYPE_STRING    , "'bar'", 0, 12, 17 },
+    { Tokenizer::TYPE_END       , ""     , 0, 17, 17 },
   }},
 
   // Test that consecutive symbols are parsed as separate tokens.
   { "!@+%", {
-    { Tokenizer::TYPE_SYMBOL    , "!"    , 0, 0 },
-    { Tokenizer::TYPE_SYMBOL    , "@"    , 0, 1 },
-    { Tokenizer::TYPE_SYMBOL    , "+"    , 0, 2 },
-    { Tokenizer::TYPE_SYMBOL    , "%"    , 0, 3 },
-    { Tokenizer::TYPE_END       , ""     , 0, 4 },
+    { Tokenizer::TYPE_SYMBOL    , "!"    , 0, 0, 1 },
+    { Tokenizer::TYPE_SYMBOL    , "@"    , 0, 1, 2 },
+    { Tokenizer::TYPE_SYMBOL    , "+"    , 0, 2, 3 },
+    { Tokenizer::TYPE_SYMBOL    , "%"    , 0, 3, 4 },
+    { Tokenizer::TYPE_END       , ""     , 0, 4, 4 },
   }},
 
   // Test that newlines affect line numbers correctly.
   { "foo bar\nrab oof", {
-    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0 },
-    { Tokenizer::TYPE_IDENTIFIER, "bar", 0,  4 },
-    { Tokenizer::TYPE_IDENTIFIER, "rab", 1,  0 },
-    { Tokenizer::TYPE_IDENTIFIER, "oof", 1,  4 },
-    { Tokenizer::TYPE_END       , ""   , 1,  7 },
+    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0, 3 },
+    { Tokenizer::TYPE_IDENTIFIER, "bar", 0,  4, 7 },
+    { Tokenizer::TYPE_IDENTIFIER, "rab", 1,  0, 3 },
+    { Tokenizer::TYPE_IDENTIFIER, "oof", 1,  4, 7 },
+    { Tokenizer::TYPE_END       , ""   , 1,  7, 7 },
   }},
 
   // Test that tabs affect column numbers correctly.
   { "foo\tbar  \tbaz", {
-    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0 },
-    { Tokenizer::TYPE_IDENTIFIER, "bar", 0,  8 },
-    { Tokenizer::TYPE_IDENTIFIER, "baz", 0, 16 },
-    { Tokenizer::TYPE_END       , ""   , 0, 19 },
+    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0,  3 },
+    { Tokenizer::TYPE_IDENTIFIER, "bar", 0,  8, 11 },
+    { Tokenizer::TYPE_IDENTIFIER, "baz", 0, 16, 19 },
+    { Tokenizer::TYPE_END       , ""   , 0, 19, 19 },
+  }},
+
+  // Test that tabs in string literals affect column numbers correctly.
+  { "\"foo\tbar\" baz", {
+    { Tokenizer::TYPE_STRING    , "\"foo\tbar\"", 0,  0, 12 },
+    { Tokenizer::TYPE_IDENTIFIER, "baz"         , 0, 13, 16 },
+    { Tokenizer::TYPE_END       , ""            , 0, 16, 16 },
   }},
 
   // Test that line comments are ignored.
   { "foo // This is a comment\n"
     "bar // This is another comment", {
-    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0 },
-    { Tokenizer::TYPE_IDENTIFIER, "bar", 1,  0 },
-    { Tokenizer::TYPE_END       , ""   , 1, 30 },
+    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0,  3 },
+    { Tokenizer::TYPE_IDENTIFIER, "bar", 1,  0,  3 },
+    { Tokenizer::TYPE_END       , ""   , 1, 30, 30 },
   }},
 
   // Test that block comments are ignored.
   { "foo /* This is a block comment */ bar", {
-    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0 },
-    { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 34 },
-    { Tokenizer::TYPE_END       , ""   , 0, 37 },
+    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0,  3 },
+    { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 34, 37 },
+    { Tokenizer::TYPE_END       , ""   , 0, 37, 37 },
   }},
 
   // Test that sh-style comments are not ignored by default.
   { "foo # bar\n"
     "baz", {
-    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0 },
-    { Tokenizer::TYPE_SYMBOL    , "#"  , 0,  4 },
-    { Tokenizer::TYPE_IDENTIFIER, "bar", 0,  6 },
-    { Tokenizer::TYPE_IDENTIFIER, "baz", 1,  0 },
-    { Tokenizer::TYPE_END       , ""   , 1, 3 },
+    { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 },
+    { Tokenizer::TYPE_SYMBOL    , "#"  , 0, 4, 5 },
+    { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 6, 9 },
+    { Tokenizer::TYPE_IDENTIFIER, "baz", 1, 0, 3 },
+    { Tokenizer::TYPE_END       , ""   , 1, 3, 3 },
   }},
 
   // Bytes with the high-order bit set should not be seen as control characters.
   { "\300", {
-    { Tokenizer::TYPE_SYMBOL, "\300", 0, 0 },
-    { Tokenizer::TYPE_END   , ""    , 0, 1 },
+    { Tokenizer::TYPE_SYMBOL, "\300", 0, 0, 1 },
+    { Tokenizer::TYPE_END   , ""    , 0, 1, 1 },
   }},
 
   // Test all whitespace chars
   { "foo\n\t\r\v\fbar", {
-    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0 },
-    { Tokenizer::TYPE_IDENTIFIER, "bar", 1, 11 },
-    { Tokenizer::TYPE_END       , ""   , 1, 14 },
+    { Tokenizer::TYPE_IDENTIFIER, "foo", 0,  0,  3 },
+    { Tokenizer::TYPE_IDENTIFIER, "bar", 1, 11, 14 },
+    { Tokenizer::TYPE_END       , ""   , 1, 14, 14 },
   }},
 };
 
@@ -425,6 +437,7 @@
   EXPECT_EQ("", tokenizer.current().text);
   EXPECT_EQ(0, tokenizer.current().line);
   EXPECT_EQ(0, tokenizer.current().column);
+  EXPECT_EQ(0, tokenizer.current().end_column);
 
   // Loop through all expected tokens.
   int i = 0;
@@ -434,6 +447,8 @@
 
     SCOPED_TRACE(testing::Message() << "Token #" << i << ": " << token.text);
 
+    Tokenizer::Token previous = tokenizer.current();
+
     // Next() should only return false when it hits the end token.
     if (token.type != Tokenizer::TYPE_END) {
       ASSERT_TRUE(tokenizer.Next());
@@ -441,11 +456,19 @@
       ASSERT_FALSE(tokenizer.Next());
     }
 
+    // Check that the previous token is set correctly.
+    EXPECT_EQ(previous.type, tokenizer.previous().type);
+    EXPECT_EQ(previous.text, tokenizer.previous().text);
+    EXPECT_EQ(previous.line, tokenizer.previous().line);
+    EXPECT_EQ(previous.column, tokenizer.previous().column);
+    EXPECT_EQ(previous.end_column, tokenizer.previous().end_column);
+
     // Check that the token matches the expected one.
     EXPECT_EQ(token.type, tokenizer.current().type);
     EXPECT_EQ(token.text, tokenizer.current().text);
     EXPECT_EQ(token.line, tokenizer.current().line);
     EXPECT_EQ(token.column, tokenizer.current().column);
+    EXPECT_EQ(token.end_column, tokenizer.current().end_column);
 
   } while (token.type != Tokenizer::TYPE_END);
 
diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc
index 8229ee6..5196d90 100644
--- a/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -61,6 +61,7 @@
 #include <sstream>
 
 #include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/io/coded_stream.h>
 
 #if HAVE_ZLIB
 #include <google/protobuf/io/gzip_stream.h>
@@ -285,6 +286,57 @@
   }
 }
 
+TEST_F(IoTest, TwoSessionWrite) {
+  // Test that two concatenated write sessions read correctly
+
+  static const char* strA = "0123456789";
+  static const char* strB = "WhirledPeas";
+  const int kBufferSize = 2*1024;
+  uint8* buffer = new uint8[kBufferSize];
+  char* temp_buffer = new char[40];
+
+  for (int i = 0; i < kBlockSizeCount; i++) {
+    for (int j = 0; j < kBlockSizeCount; j++) {
+      ArrayOutputStream* output =
+          new ArrayOutputStream(buffer, kBufferSize, kBlockSizes[i]);
+      CodedOutputStream* coded_output = new CodedOutputStream(output);
+      coded_output->WriteVarint32(strlen(strA));
+      coded_output->WriteRaw(strA, strlen(strA));
+      delete coded_output;  // flush
+      int64 pos = output->ByteCount();
+      delete output;
+      output = new ArrayOutputStream(
+          buffer + pos, kBufferSize - pos, kBlockSizes[i]);
+      coded_output = new CodedOutputStream(output);
+      coded_output->WriteVarint32(strlen(strB));
+      coded_output->WriteRaw(strB, strlen(strB));
+      delete coded_output;  // flush
+      int64 size = pos + output->ByteCount();
+      delete output;
+
+      ArrayInputStream* input =
+          new ArrayInputStream(buffer, size, kBlockSizes[j]);
+      CodedInputStream* coded_input = new CodedInputStream(input);
+      uint32 insize;
+      EXPECT_TRUE(coded_input->ReadVarint32(&insize));
+      EXPECT_EQ(strlen(strA), insize);
+      EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize));
+      EXPECT_EQ(0, memcmp(temp_buffer, strA, insize));
+
+      EXPECT_TRUE(coded_input->ReadVarint32(&insize));
+      EXPECT_EQ(strlen(strB), insize);
+      EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize));
+      EXPECT_EQ(0, memcmp(temp_buffer, strB, insize));
+
+      delete coded_input;
+      delete input;
+    }
+  }
+
+  delete [] temp_buffer;
+  delete [] buffer;
+}
+
 #if HAVE_ZLIB
 TEST_F(IoTest, GzipIo) {
   const int kBufferSize = 2*1024;
@@ -296,8 +348,12 @@
         int size;
         {
           ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]);
-          GzipOutputStream gzout(
-              &output, GzipOutputStream::GZIP, gzip_buffer_size);
+          GzipOutputStream::Options options;
+          options.format = GzipOutputStream::GZIP;
+          if (gzip_buffer_size != -1) {
+            options.buffer_size = gzip_buffer_size;
+          }
+          GzipOutputStream gzout(&output, options);
           WriteStuff(&gzout);
           gzout.Close();
           size = output.ByteCount();
@@ -324,8 +380,12 @@
         int size;
         {
           ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]);
-          GzipOutputStream gzout(
-              &output, GzipOutputStream::ZLIB, gzip_buffer_size);
+          GzipOutputStream::Options options;
+          options.format = GzipOutputStream::ZLIB;
+          if (gzip_buffer_size != -1) {
+            options.buffer_size = gzip_buffer_size;
+          }
+          GzipOutputStream gzout(&output, options);
           WriteStuff(&gzout);
           gzout.Close();
           size = output.ByteCount();
@@ -348,7 +408,9 @@
   int size;
   {
     ArrayOutputStream output(buffer, kBufferSize);
-    GzipOutputStream gzout(&output, GzipOutputStream::ZLIB);
+    GzipOutputStream::Options options;
+    options.format = GzipOutputStream::ZLIB;
+    GzipOutputStream gzout(&output, options);
     WriteStuff(&gzout);
     gzout.Close();
     size = output.ByteCount();
@@ -360,7 +422,9 @@
   }
   {
     ArrayOutputStream output(buffer, kBufferSize);
-    GzipOutputStream gzout(&output, GzipOutputStream::GZIP);
+    GzipOutputStream::Options options;
+    options.format = GzipOutputStream::GZIP;
+    GzipOutputStream gzout(&output, options);
     WriteStuff(&gzout);
     gzout.Close();
     size = output.ByteCount();
@@ -432,6 +496,71 @@
   EXPECT_TRUE(Uncompress(gzip_compressed) == golden);
   EXPECT_TRUE(Uncompress(zlib_compressed) == golden);
 }
+
+TEST_F(IoTest, TwoSessionWriteGzip) {
+  // Test that two concatenated gzip streams can be read correctly
+
+  static const char* strA = "0123456789";
+  static const char* strB = "QuickBrownFox";
+  const int kBufferSize = 2*1024;
+  uint8* buffer = new uint8[kBufferSize];
+  char* temp_buffer = new char[40];
+
+  for (int i = 0; i < kBlockSizeCount; i++) {
+    for (int j = 0; j < kBlockSizeCount; j++) {
+      ArrayOutputStream* output =
+          new ArrayOutputStream(buffer, kBufferSize, kBlockSizes[i]);
+      GzipOutputStream* gzout = new GzipOutputStream(output);
+      CodedOutputStream* coded_output = new CodedOutputStream(gzout);
+      int32 outlen = strlen(strA) + 1;
+      coded_output->WriteVarint32(outlen);
+      coded_output->WriteRaw(strA, outlen);
+      delete coded_output;  // flush
+      delete gzout;  // flush
+      int64 pos = output->ByteCount();
+      delete output;
+      output = new ArrayOutputStream(
+          buffer + pos, kBufferSize - pos, kBlockSizes[i]);
+      gzout = new GzipOutputStream(output);
+      coded_output = new CodedOutputStream(gzout);
+      outlen = strlen(strB) + 1;
+      coded_output->WriteVarint32(outlen);
+      coded_output->WriteRaw(strB, outlen);
+      delete coded_output;  // flush
+      delete gzout;  // flush
+      int64 size = pos + output->ByteCount();
+      delete output;
+
+      ArrayInputStream* input =
+          new ArrayInputStream(buffer, size, kBlockSizes[j]);
+      GzipInputStream* gzin = new GzipInputStream(input);
+      CodedInputStream* coded_input = new CodedInputStream(gzin);
+      uint32 insize;
+      EXPECT_TRUE(coded_input->ReadVarint32(&insize));
+      EXPECT_EQ(strlen(strA) + 1, insize);
+      EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize));
+      EXPECT_EQ(0, memcmp(temp_buffer, strA, insize))
+          << "strA=" << strA << " in=" << temp_buffer;
+
+      EXPECT_TRUE(coded_input->ReadVarint32(&insize));
+      EXPECT_EQ(strlen(strB) + 1, insize);
+      EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize));
+      EXPECT_EQ(0, memcmp(temp_buffer, strB, insize))
+          << " out_block_size=" << kBlockSizes[i]
+          << " in_block_size=" << kBlockSizes[j]
+          << " pos=" << pos
+          << " size=" << size
+          << " strB=" << strB << " in=" << temp_buffer;
+
+      delete coded_input;
+      delete gzin;
+      delete input;
+    }
+  }
+
+  delete [] temp_buffer;
+  delete [] buffer;
+}
 #endif
 
 // There is no string input, only string output.  Also, it doesn't support
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index d117fe2..4bbc641 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -123,6 +123,7 @@
 
 #include <google/protobuf/stubs/common.h>
 
+
 namespace google {
 namespace protobuf {
 
diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc
index f7beb11..0937774 100644
--- a/src/google/protobuf/repeated_field.cc
+++ b/src/google/protobuf/repeated_field.cc
@@ -32,11 +32,14 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <algorithm>
+
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/stubs/common.h>
 
 namespace google {
 namespace protobuf {
+
 namespace internal {
 
 void RepeatedPtrFieldBase::Reserve(int new_size) {
@@ -88,8 +91,8 @@
   delete value;
 }
 
+}  // namespace internal
 
-} // namespace internal
 
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index cc07fdb..ae96107 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -72,8 +72,11 @@
 class RepeatedField {
  public:
   RepeatedField();
+  RepeatedField(const RepeatedField& other);
   ~RepeatedField();
 
+  RepeatedField& operator=(const RepeatedField& other);
+
   int size() const;
 
   const Element& Get(int index) const;
@@ -90,6 +93,7 @@
   void RemoveLast();
   void Clear();
   void MergeFrom(const RepeatedField& other);
+  void CopyFrom(const RepeatedField& other);
 
   // Reserve space to expand the field to at least the given size.  If the
   // array is grown, it will always be at least doubled in size.
@@ -116,6 +120,7 @@
   // STL-like iterator support
   typedef Element* iterator;
   typedef const Element* const_iterator;
+  typedef Element value_type;
 
   iterator begin();
   const_iterator begin() const;
@@ -127,8 +132,6 @@
   int SpaceUsedExcludingSelf() const;
 
  private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedField);
-
   static const int kInitialSize = 4;
 
   Element* elements_;
@@ -203,6 +206,8 @@
   void Clear();
   template <typename TypeHandler>
   void MergeFrom(const RepeatedPtrFieldBase& other);
+  template <typename TypeHandler>
+  void CopyFrom(const RepeatedPtrFieldBase& other);
 
   void Reserve(int new_size);
 
@@ -300,7 +305,7 @@
   static void Merge(const string& from, string* to) { *to = from; }
 };
 
-class StringTypeHandler : public StringTypeHandlerBase {
+class LIBPROTOBUF_EXPORT StringTypeHandler : public StringTypeHandlerBase {
  public:
   static int SpaceUsed(const string& value)  {
     return sizeof(value) + StringSpaceUsedExcludingSelf(value);
@@ -316,9 +321,11 @@
 class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
  public:
   RepeatedPtrField();
-
+  RepeatedPtrField(const RepeatedPtrField& other);
   ~RepeatedPtrField();
 
+  RepeatedPtrField& operator=(const RepeatedPtrField& other);
+
   int size() const;
 
   const Element& Get(int index) const;
@@ -327,6 +334,7 @@
   void RemoveLast();  // Remove the last element in the array.
   void Clear();
   void MergeFrom(const RepeatedPtrField& other);
+  void CopyFrom(const RepeatedPtrField& other);
 
   // Reserve space to expand the field to at least the given size.  This only
   // resizes the pointer array; it doesn't allocate any objects.  If the
@@ -349,6 +357,7 @@
   // STL-like iterator support
   typedef internal::RepeatedPtrIterator<Element> iterator;
   typedef internal::RepeatedPtrIterator<const Element> const_iterator;
+  typedef Element value_type;
 
   iterator begin();
   const_iterator begin() const;
@@ -365,11 +374,6 @@
   // excluding sizeof(*this).
   int SpaceUsedExcludingSelf() const;
 
-  // The spaced used just by the pointer array, not counting the objects pointed
-  // at.  Returns zero if the array is inlined (i.e. initial_space_ is being
-  // used).
-  int SpaceUsedByArray() const;
-
   // Advanced memory management --------------------------------------
   // When hardcore memory management becomes necessary -- as it often
   // does here at Google -- the following methods may be useful.
@@ -410,9 +414,6 @@
   //   methods on RepeatedPtrFieldBase.
   class TypeHandler;
 
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrField);
 };
 
 // implementation ====================================================
@@ -425,6 +426,14 @@
 }
 
 template <typename Element>
+inline RepeatedField<Element>::RepeatedField(const RepeatedField& other)
+  : elements_(initial_space_),
+    current_size_(0),
+    total_size_(kInitialSize) {
+  CopyFrom(other);
+}
+
+template <typename Element>
 RepeatedField<Element>::~RepeatedField() {
   if (elements_ != initial_space_) {
     delete [] elements_;
@@ -432,6 +441,13 @@
 }
 
 template <typename Element>
+inline RepeatedField<Element>&
+RepeatedField<Element>::operator=(const RepeatedField& other) {
+  CopyFrom(other);
+  return *this;
+}
+
+template <typename Element>
 inline int RepeatedField<Element>::size() const {
   return current_size_;
 }
@@ -502,6 +518,12 @@
 }
 
 template <typename Element>
+inline void RepeatedField<Element>::CopyFrom(const RepeatedField& other) {
+  Clear();
+  MergeFrom(other);
+}
+
+template <typename Element>
 inline Element* RepeatedField<Element>::mutable_data() {
   return elements_;
 }
@@ -679,6 +701,12 @@
   }
 }
 
+template <typename TypeHandler>
+inline void RepeatedPtrFieldBase::CopyFrom(const RepeatedPtrFieldBase& other) {
+  RepeatedPtrFieldBase::Clear<TypeHandler>();
+  RepeatedPtrFieldBase::MergeFrom<TypeHandler>(other);
+}
+
 inline int RepeatedPtrFieldBase::Capacity() const {
   return total_size_;
 }
@@ -805,11 +833,24 @@
 inline RepeatedPtrField<Element>::RepeatedPtrField() {}
 
 template <typename Element>
+inline RepeatedPtrField<Element>::RepeatedPtrField(
+    const RepeatedPtrField& other) {
+  CopyFrom(other);
+}
+
+template <typename Element>
 RepeatedPtrField<Element>::~RepeatedPtrField() {
   Destroy<TypeHandler>();
 }
 
 template <typename Element>
+inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=(
+    const RepeatedPtrField& other) {
+  CopyFrom(other);
+  return *this;
+}
+
+template <typename Element>
 inline int RepeatedPtrField<Element>::size() const {
   return RepeatedPtrFieldBase::size();
 }
@@ -846,6 +887,12 @@
 }
 
 template <typename Element>
+inline void RepeatedPtrField<Element>::CopyFrom(
+    const RepeatedPtrField& other) {
+  RepeatedPtrFieldBase::CopyFrom<TypeHandler>(other);
+}
+
+template <typename Element>
 inline Element** RepeatedPtrField<Element>::mutable_data() {
   return RepeatedPtrFieldBase::mutable_data<TypeHandler>();
 }
@@ -944,7 +991,7 @@
   template<typename OtherElement>
   RepeatedPtrIterator(const RepeatedPtrIterator<OtherElement>& other)
       : it_(other.it_) {
-    // Force a compiler error if the other type is not convertable to ours.
+    // Force a compiler error if the other type is not convertible to ours.
     if (false) {
       implicit_cast<Element*, OtherElement*>(0);
     }
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index 7c35f60..e7e1e99 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -232,6 +232,54 @@
   EXPECT_EQ(5, destination.Get(4));
 }
 
+TEST(RepeatedField, CopyFrom) {
+  RepeatedField<int> source, destination;
+
+  source.Add(4);
+  source.Add(5);
+
+  destination.Add(1);
+  destination.Add(2);
+  destination.Add(3);
+
+  destination.CopyFrom(source);
+
+  ASSERT_EQ(2, destination.size());
+
+  EXPECT_EQ(4, destination.Get(0));
+  EXPECT_EQ(5, destination.Get(1));
+}
+
+TEST(RepeatedField, CopyConstruct) {
+  RepeatedField<int> source;
+  source.Add(1);
+  source.Add(2);
+
+  RepeatedField<int> destination(source);
+
+  ASSERT_EQ(2, destination.size());
+  EXPECT_EQ(1, destination.Get(0));
+  EXPECT_EQ(2, destination.Get(1));
+}
+
+TEST(RepeatedField, CopyAssign) {
+  RepeatedField<int> source, destination;
+
+  source.Add(4);
+  source.Add(5);
+
+  destination.Add(1);
+  destination.Add(2);
+  destination.Add(3);
+
+  destination = source;
+
+  ASSERT_EQ(2, destination.size());
+
+  EXPECT_EQ(4, destination.Get(0));
+  EXPECT_EQ(5, destination.Get(1));
+}
+
 TEST(RepeatedField, MutableDataIsMutable) {
   RepeatedField<int> field;
   field.Add(1);
@@ -536,6 +584,55 @@
   EXPECT_EQ("5", destination.Get(4));
 }
 
+TEST(RepeatedPtrField, CopyFrom) {
+  RepeatedPtrField<string> source, destination;
+
+  source.Add()->assign("4");
+  source.Add()->assign("5");
+
+  destination.Add()->assign("1");
+  destination.Add()->assign("2");
+  destination.Add()->assign("3");
+
+  destination.CopyFrom(source);
+
+  ASSERT_EQ(2, destination.size());
+
+  EXPECT_EQ("4", destination.Get(0));
+  EXPECT_EQ("5", destination.Get(1));
+}
+
+TEST(RepeatedPtrField, CopyConstruct) {
+  RepeatedPtrField<string> source;
+
+  source.Add()->assign("1");
+  source.Add()->assign("2");
+
+  RepeatedPtrField<string> destination(source);
+
+  ASSERT_EQ(2, destination.size());
+  EXPECT_EQ("1", destination.Get(0));
+  EXPECT_EQ("2", destination.Get(1));
+}
+
+TEST(RepeatedPtrField, CopyAssign) {
+  RepeatedPtrField<string> source, destination;
+
+  source.Add()->assign("4");
+  source.Add()->assign("5");
+
+  destination.Add()->assign("1");
+  destination.Add()->assign("2");
+  destination.Add()->assign("3");
+
+  destination = source;
+
+  ASSERT_EQ(2, destination.size());
+
+  EXPECT_EQ("4", destination.Get(0));
+  EXPECT_EQ("5", destination.Get(1));
+}
+
 TEST(RepeatedPtrField, MutableDataIsMutable) {
   RepeatedPtrField<string> field;
   *field.Add() = "1";
@@ -564,7 +661,8 @@
 TEST_F(RepeatedFieldIteratorTest, Convertible) {
   RepeatedField<int>::iterator iter = proto_array_.begin();
   RepeatedField<int>::const_iterator c_iter = iter;
-  EXPECT_EQ(0, *c_iter);
+  RepeatedField<int>::value_type value = *c_iter;
+  EXPECT_EQ(0, value);
 }
 
 TEST_F(RepeatedFieldIteratorTest, MutableIteration) {
@@ -613,6 +711,8 @@
 TEST_F(RepeatedPtrFieldIteratorTest, Convertible) {
   RepeatedPtrField<string>::iterator iter = proto_array_.begin();
   RepeatedPtrField<string>::const_iterator c_iter = iter;
+  RepeatedPtrField<string>::value_type value = *c_iter;
+  EXPECT_EQ("foo", value);
 }
 
 TEST_F(RepeatedPtrFieldIteratorTest, MutableIteration) {
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index 137cbce..1494ebd 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -37,6 +37,7 @@
 #include <stdio.h>
 #include <stack>
 #include <limits>
+#include <vector>
 
 #include <google/protobuf/text_format.h>
 
@@ -118,8 +119,10 @@
   ParserImpl(const Descriptor* root_message_type,
              io::ZeroCopyInputStream* input_stream,
              io::ErrorCollector* error_collector,
+             TextFormat::Finder* finder,
              SingularOverwritePolicy singular_overwrite_policy)
     : error_collector_(error_collector),
+      finder_(finder),
       tokenizer_error_collector_(this),
       tokenizer_(input_stream, &tokenizer_error_collector_),
       root_message_type_(root_message_type),
@@ -249,7 +252,9 @@
       }
       DO(Consume("]"));
 
-      field = reflection->FindKnownExtensionByName(field_name);
+      field = (finder_ != NULL
+               ? finder_->FindExtension(message, field_name)
+               : reflection->FindKnownExtensionByName(field_name));
 
       if (field == NULL) {
         ReportError("Extension \"" + field_name + "\" is not defined or "
@@ -301,9 +306,24 @@
       DO(ConsumeFieldMessage(message, reflection, field));
     } else {
       DO(Consume(":"));
-      DO(ConsumeFieldValue(message, reflection, field));
+      if (field->is_repeated() && TryConsume("[")) {
+        // Short repeated format, e.g.  "foo: [1, 2, 3]"
+        while (true) {
+          DO(ConsumeFieldValue(message, reflection, field));
+          if (TryConsume("]")) {
+            break;
+          }
+          DO(Consume(","));
+        }
+      } else {
+        DO(ConsumeFieldValue(message, reflection, field));
+      }
     }
 
+    // For historical reasons, fields may optionally be separated by commas or
+    // semicolons.
+    TryConsume(";") || TryConsume(",");
+
     if (field->options().deprecated()) {
       ReportWarning("text format contains deprecated field \""
                     + field_name + "\"");
@@ -397,29 +417,46 @@
       }
 
       case FieldDescriptor::CPPTYPE_BOOL: {
-        string value;
-        DO(ConsumeIdentifier(&value));
-
-        if (value == "true") {
-          SET_FIELD(Bool, true);
-        } else if (value == "false") {
-          SET_FIELD(Bool, false);
+        if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
+          uint64 value;
+          DO(ConsumeUnsignedInteger(&value, 1));
+          SET_FIELD(Bool, value);
         } else {
-          ReportError("Invalid value for boolean field \"" + field->name()
-                      + "\". Value: \"" + value  + "\".");
-          return false;
+          string value;
+          DO(ConsumeIdentifier(&value));
+          if (value == "true" || value == "t") {
+            SET_FIELD(Bool, true);
+          } else if (value == "false" || value == "f") {
+            SET_FIELD(Bool, false);
+          } else {
+            ReportError("Invalid value for boolean field \"" + field->name()
+                        + "\". Value: \"" + value  + "\".");
+            return false;
+          }
         }
         break;
       }
 
       case FieldDescriptor::CPPTYPE_ENUM: {
         string value;
-        DO(ConsumeIdentifier(&value));
-
-        // Find the enumeration value.
         const EnumDescriptor* enum_type = field->enum_type();
-        const EnumValueDescriptor* enum_value
-            = enum_type->FindValueByName(value);
+        const EnumValueDescriptor* enum_value = NULL;
+
+        if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
+          DO(ConsumeIdentifier(&value));
+          // Find the enumeration value.
+          enum_value = enum_type->FindValueByName(value);
+
+        } else if (LookingAt("-") ||
+                   LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
+          int64 int_value;
+          DO(ConsumeSignedInteger(&int_value, kint32max));
+          value = SimpleItoa(int_value);        // for error reporting
+          enum_value = enum_type->FindValueByNumber(int_value);
+        } else {
+          ReportError("Expected integer or identifier.");
+          return false;
+        }
 
         if (enum_value == NULL) {
           ReportError("Unknown enumeration value of \"" + value  + "\" for "
@@ -632,6 +669,7 @@
   };
 
   io::ErrorCollector* error_collector_;
+  TextFormat::Finder* finder_;
   ParserErrorCollector tokenizer_error_collector_;
   io::Tokenizer tokenizer_;
   const Descriptor* root_message_type_;
@@ -765,9 +803,14 @@
 
 // ===========================================================================
 
+TextFormat::Finder::~Finder() {
+}
+
 TextFormat::Parser::Parser()
   : error_collector_(NULL),
-    allow_partial_(false) {}
+    finder_(NULL),
+    allow_partial_(false) {
+}
 
 TextFormat::Parser::~Parser() {}
 
@@ -775,7 +818,7 @@
                                Message* output) {
   output->Clear();
   ParserImpl parser(output->GetDescriptor(), input, error_collector_,
-                    ParserImpl::FORBID_SINGULAR_OVERWRITES);
+                    finder_, ParserImpl::FORBID_SINGULAR_OVERWRITES);
   return MergeUsingImpl(input, output, &parser);
 }
 
@@ -788,7 +831,7 @@
 bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input,
                                Message* output) {
   ParserImpl parser(output->GetDescriptor(), input, error_collector_,
-                    ParserImpl::ALLOW_SINGULAR_OVERWRITES);
+                    finder_, ParserImpl::ALLOW_SINGULAR_OVERWRITES);
   return MergeUsingImpl(input, output, &parser);
 }
 
@@ -818,7 +861,7 @@
     Message* output) {
   io::ArrayInputStream input_stream(input.data(), input.size());
   ParserImpl parser(output->GetDescriptor(), &input_stream, error_collector_,
-                    ParserImpl::ALLOW_SINGULAR_OVERWRITES);
+                    finder_, ParserImpl::ALLOW_SINGULAR_OVERWRITES);
   return parser.ParseField(field, output);
 }
 
@@ -853,7 +896,7 @@
 TextFormat::Printer::~Printer() {}
 
 bool TextFormat::Printer::PrintToString(const Message& message,
-                                        string* output) {
+                                        string* output) const {
   GOOGLE_DCHECK(output) << "output specified is NULL";
 
   output->clear();
@@ -866,7 +909,7 @@
 
 bool TextFormat::Printer::PrintUnknownFieldsToString(
     const UnknownFieldSet& unknown_fields,
-    string* output) {
+    string* output) const {
   GOOGLE_DCHECK(output) << "output specified is NULL";
 
   output->clear();
@@ -875,7 +918,7 @@
 }
 
 bool TextFormat::Printer::Print(const Message& message,
-                                io::ZeroCopyOutputStream* output) {
+                                io::ZeroCopyOutputStream* output) const {
   TextGenerator generator(output, initial_indent_level_);
 
   Print(message, generator);
@@ -886,7 +929,7 @@
 
 bool TextFormat::Printer::PrintUnknownFields(
     const UnknownFieldSet& unknown_fields,
-    io::ZeroCopyOutputStream* output) {
+    io::ZeroCopyOutputStream* output) const {
   TextGenerator generator(output, initial_indent_level_);
 
   PrintUnknownFields(unknown_fields, generator);
@@ -896,7 +939,7 @@
 }
 
 void TextFormat::Printer::Print(const Message& message,
-                                TextGenerator& generator) {
+                                TextGenerator& generator) const {
   const Reflection* reflection = message.GetReflection();
   vector<const FieldDescriptor*> fields;
   reflection->ListFields(message, &fields);
@@ -910,7 +953,7 @@
     const Message& message,
     const FieldDescriptor* field,
     int index,
-    string* output) {
+    string* output) const {
 
   GOOGLE_DCHECK(output) << "output specified is NULL";
 
@@ -924,7 +967,7 @@
 void TextFormat::Printer::PrintField(const Message& message,
                                      const Reflection* reflection,
                                      const FieldDescriptor* field,
-                                     TextGenerator& generator) {
+                                     TextGenerator& generator) const {
   if (use_short_repeated_primitives_ &&
       field->is_repeated() &&
       field->cpp_type() != FieldDescriptor::CPPTYPE_STRING &&
@@ -980,10 +1023,11 @@
   }
 }
 
-void TextFormat::Printer::PrintShortRepeatedField(const Message& message,
-                                                  const Reflection* reflection,
-                                                  const FieldDescriptor* field,
-                                                  TextGenerator& generator) {
+void TextFormat::Printer::PrintShortRepeatedField(
+    const Message& message,
+    const Reflection* reflection,
+    const FieldDescriptor* field,
+    TextGenerator& generator) const {
   // Print primitive repeated field in short form.
   PrintFieldName(message, reflection, field, generator);
 
@@ -1003,7 +1047,7 @@
 void TextFormat::Printer::PrintFieldName(const Message& message,
                                          const Reflection* reflection,
                                          const FieldDescriptor* field,
-                                         TextGenerator& generator) {
+                                         TextGenerator& generator) const {
   if (field->is_extension()) {
     generator.Print("[");
     // We special-case MessageSet elements for compatibility with proto1.
@@ -1031,7 +1075,7 @@
     const Reflection* reflection,
     const FieldDescriptor* field,
     int index,
-    TextGenerator& generator) {
+    TextGenerator& generator) const {
   GOOGLE_DCHECK(field->is_repeated() || (index == -1))
       << "Index must be -1 for non-repeated fields";
 
@@ -1143,7 +1187,7 @@
 }
 
 void TextFormat::Printer::PrintUnknownFields(
-    const UnknownFieldSet& unknown_fields, TextGenerator& generator) {
+    const UnknownFieldSet& unknown_fields, TextGenerator& generator) const {
   for (int i = 0; i < unknown_fields.field_count(); i++) {
     const UnknownField& field = unknown_fields.field(i);
     string field_number = SimpleItoa(field.number());
diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h
index e78e104..03c0491 100644
--- a/src/google/protobuf/text_format.h
+++ b/src/google/protobuf/text_format.h
@@ -90,20 +90,20 @@
     ~Printer();
 
     // Like TextFormat::Print
-    bool Print(const Message& message, io::ZeroCopyOutputStream* output);
+    bool Print(const Message& message, io::ZeroCopyOutputStream* output) const;
     // Like TextFormat::PrintUnknownFields
     bool PrintUnknownFields(const UnknownFieldSet& unknown_fields,
-                            io::ZeroCopyOutputStream* output);
+                            io::ZeroCopyOutputStream* output) const;
     // Like TextFormat::PrintToString
-    bool PrintToString(const Message& message, string* output);
+    bool PrintToString(const Message& message, string* output) const;
     // Like TextFormat::PrintUnknownFieldsToString
     bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields,
-                                    string* output);
+                                    string* output) const;
     // Like TextFormat::PrintFieldValueToString
     void PrintFieldValueToString(const Message& message,
                                  const FieldDescriptor* field,
                                  int index,
-                                 string* output);
+                                 string* output) const;
 
     // Adjust the initial indent level of all output.  Each indent level is
     // equal to two spaces.
@@ -121,8 +121,7 @@
     //   field_name: [1, 2, 3, 4]
     // instead of printing each value on its own line.  Short format applies
     // only to primitive values -- i.e. everything except strings and
-    // sub-messages/groups.  Note that at present this format is not recognized
-    // by the parser.
+    // sub-messages/groups.
     void SetUseShortRepeatedPrimitives(bool use_short_repeated_primitives) {
       use_short_repeated_primitives_ = use_short_repeated_primitives;
     }
@@ -143,26 +142,26 @@
     // Internal Print method, used for writing to the OutputStream via
     // the TextGenerator class.
     void Print(const Message& message,
-               TextGenerator& generator);
+               TextGenerator& generator) const;
 
     // Print a single field.
     void PrintField(const Message& message,
                     const Reflection* reflection,
                     const FieldDescriptor* field,
-                    TextGenerator& generator);
+                    TextGenerator& generator) const;
 
     // Print a repeated primitive field in short form.
     void PrintShortRepeatedField(const Message& message,
                                  const Reflection* reflection,
                                  const FieldDescriptor* field,
-                                 TextGenerator& generator);
+                                 TextGenerator& generator) const;
 
     // Print the name of a field -- i.e. everything that comes before the
     // ':' for a single name/value pair.
     void PrintFieldName(const Message& message,
                         const Reflection* reflection,
                         const FieldDescriptor* field,
-                        TextGenerator& generator);
+                        TextGenerator& generator) const;
 
     // Outputs a textual representation of the value of the field supplied on
     // the message supplied or the default value if not set.
@@ -170,13 +169,13 @@
                          const Reflection* reflection,
                          const FieldDescriptor* field,
                          int index,
-                         TextGenerator& generator);
+                         TextGenerator& generator) const;
 
     // Print the fields in an UnknownFieldSet.  They are printed by tag number
     // only.  Embedded messages are heuristically identified by attempting to
     // parse them.
     void PrintUnknownFields(const UnknownFieldSet& unknown_fields,
-                            TextGenerator& generator);
+                            TextGenerator& generator) const;
 
     int initial_indent_level_;
 
@@ -207,6 +206,20 @@
                                         const FieldDescriptor* field,
                                         Message* message);
 
+  // Interface that TextFormat::Parser can use to find extensions.
+  // This class may be extended in the future to find more information
+  // like fields, etc.
+  class LIBPROTOBUF_EXPORT Finder {
+   public:
+    virtual ~Finder();
+
+    // Try to find an extension of *message by fully-qualified field
+    // name.  Returns NULL if no extension is known for this name or number.
+    virtual const FieldDescriptor* FindExtension(
+        Message* message,
+        const string& name) const = 0;
+  };
+
   // For more control over parsing, use this class.
   class LIBPROTOBUF_EXPORT Parser {
    public:
@@ -228,6 +241,13 @@
       error_collector_ = error_collector;
     }
 
+    // Set how parser finds extensions.  If NULL (the default), the
+    // parser will use the standard Reflection object associated with
+    // the message being parsed.
+    void SetFinder(Finder* finder) {
+      finder_ = finder;
+    }
+
     // Normally parsing fails if, after parsing, output->IsInitialized()
     // returns false.  Call AllowPartialMessage(true) to skip this check.
     void AllowPartialMessage(bool allow) {
@@ -251,6 +271,7 @@
                         ParserImpl* parser_impl);
 
     io::ErrorCollector* error_collector_;
+    Finder* finder_;
     bool allow_partial_;
   };
 
diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
index ddf8ff7..00ea8c3 100644
--- a/src/google/protobuf/text_format_unittest.cc
+++ b/src/google/protobuf/text_format_unittest.cc
@@ -353,6 +353,25 @@
   TestUtil::ExpectAllExtensionsSet(proto_);
 }
 
+TEST_F(TextFormatTest, ParseEnumFieldFromNumber) {
+  // Create a parse string with a numerical value for an enum field.
+  string parse_string = strings::Substitute("optional_nested_enum: $0",
+                                            unittest::TestAllTypes::BAZ);
+  EXPECT_TRUE(TextFormat::ParseFromString(parse_string, &proto_));
+  EXPECT_TRUE(proto_.has_optional_nested_enum());
+  EXPECT_EQ(unittest::TestAllTypes::BAZ, proto_.optional_nested_enum());
+}
+
+TEST_F(TextFormatTest, ParseEnumFieldFromNegativeNumber) {
+  ASSERT_LT(unittest::SPARSE_E, 0);
+  string parse_string = strings::Substitute("sparse_enum: $0",
+                                            unittest::SPARSE_E);
+  unittest::SparseEnumMessage proto;
+  EXPECT_TRUE(TextFormat::ParseFromString(parse_string, &proto));
+  EXPECT_TRUE(proto.has_sparse_enum());
+  EXPECT_EQ(unittest::SPARSE_E, proto.sparse_enum());
+}
+
 TEST_F(TextFormatTest, ParseStringEscape) {
   // Create a parse string with escpaed characters in it.
   string parse_string = "optional_string: "
@@ -406,6 +425,34 @@
   EXPECT_EQ(1.0, proto_.optional_float());
 }
 
+TEST_F(TextFormatTest, ParseShortRepeatedForm) {
+  string parse_string =
+      // Mixed short-form and long-form are simply concatenated.
+      "repeated_int32: 1\n"
+      "repeated_int32: [456, 789]\n"
+      "repeated_nested_enum: [  FOO ,BAR, # comment\n"
+      "                         3]\n"
+      // Note that while the printer won't print repeated strings in short-form,
+      // the parser will accept them.
+      "repeated_string: [ \"foo\", 'bar' ]\n";
+
+  ASSERT_TRUE(TextFormat::ParseFromString(parse_string, &proto_));
+
+  ASSERT_EQ(3, proto_.repeated_int32_size());
+  EXPECT_EQ(1, proto_.repeated_int32(0));
+  EXPECT_EQ(456, proto_.repeated_int32(1));
+  EXPECT_EQ(789, proto_.repeated_int32(2));
+
+  ASSERT_EQ(3, proto_.repeated_nested_enum_size());
+  EXPECT_EQ(unittest::TestAllTypes::FOO, proto_.repeated_nested_enum(0));
+  EXPECT_EQ(unittest::TestAllTypes::BAR, proto_.repeated_nested_enum(1));
+  EXPECT_EQ(unittest::TestAllTypes::BAZ, proto_.repeated_nested_enum(2));
+
+  ASSERT_EQ(2, proto_.repeated_string_size());
+  EXPECT_EQ("foo", proto_.repeated_string(0));
+  EXPECT_EQ("bar", proto_.repeated_string(1));
+}
+
 TEST_F(TextFormatTest, Comments) {
   // Test that comments are ignored.
 
@@ -771,7 +818,12 @@
   // bool
   EXPECT_FIELD(bool, true, "true");
   EXPECT_FIELD(bool, false, "false");
-  EXPECT_INVALID(bool, "1");
+  EXPECT_FIELD(bool, true, "1");
+  EXPECT_FIELD(bool, true, "t");
+  EXPECT_FIELD(bool, false, "0");
+  EXPECT_FIELD(bool, false, "f");
+  EXPECT_INVALID(bool, "2");
+  EXPECT_INVALID(bool, "-0");
   EXPECT_INVALID(bool, "on");
   EXPECT_INVALID(bool, "a");
   EXPECT_INVALID(bool, "True");
@@ -799,7 +851,8 @@
 
   // enum
   EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAR, "BAR");
-  EXPECT_INVALID(nested_enum, "1");  // number not supported
+  EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAZ,
+               SimpleItoa(unittest::TestAllTypes::BAZ));
   EXPECT_INVALID(nested_enum, "FOOBAR");
 
   // message
@@ -820,7 +873,7 @@
   ExpectFailure("optional_bool: true\n-5\n", "Expected identifier.",
                 2, 1);
 
-  ExpectFailure("optional_bool: true;\n", "Expected identifier.", 1, 20);
+  ExpectFailure("optional_bool: true!\n", "Expected identifier.", 1, 20);
   ExpectFailure("\"some string\"", "Expected identifier.", 1, 1);
 }
 
@@ -890,7 +943,7 @@
 
   // Invalid values for a boolean field.
   ExpectFailure("optional_bool: \"hello\"\n", "Expected identifier.", 1, 16);
-  ExpectFailure("optional_bool: 5\n", "Expected identifier.", 1, 16);
+  ExpectFailure("optional_bool: 5\n", "Integer out of range.", 1, 16);
   ExpectFailure("optional_bool: -7.5\n", "Expected identifier.", 1, 16);
   ExpectFailure("optional_bool: !\n", "Expected identifier.", 1, 16);
 
@@ -911,12 +964,18 @@
                 1, 17);
 
   // Invalid values for an enumeration field.
-  ExpectFailure("optional_nested_enum: \"hello\"\n", "Expected identifier.",
-                1, 23);
+  ExpectFailure("optional_nested_enum: \"hello\"\n",
+                "Expected integer or identifier.", 1, 23);
 
-  ExpectFailure("optional_nested_enum: 5\n", "Expected identifier.", 1, 23);
-  ExpectFailure("optional_nested_enum: -7.5\n", "Expected identifier.", 1, 23);
-  ExpectFailure("optional_nested_enum: !\n", "Expected identifier.", 1, 23);
+  // Valid token, but enum value is not defined.
+  ExpectFailure("optional_nested_enum: 5\n",
+                "Unknown enumeration value of \"5\" for field "
+                "\"optional_nested_enum\".", 2, 1);
+  // We consume the negative sign, so the error position starts one character
+  // later.
+  ExpectFailure("optional_nested_enum: -7.5\n", "Expected integer.", 1, 24);
+  ExpectFailure("optional_nested_enum: !\n",
+                "Expected integer or identifier.", 1, 23);
 
   ExpectFailure(
       "optional_nested_enum: grah\n",
@@ -986,6 +1045,14 @@
   EXPECT_EQ(2, message.c());
 }
 
+TEST_F(TextFormatParserTest, ExplicitDelimiters) {
+  unittest::TestRequired message;
+  EXPECT_TRUE(TextFormat::ParseFromString("a:1,b:2;c:3", &message));
+  EXPECT_EQ(1, message.a());
+  EXPECT_EQ(2, message.b());
+  EXPECT_EQ(3, message.c());
+}
+
 TEST_F(TextFormatParserTest, PrintErrorsToStderr) {
   vector<string> errors;
 
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index d51fa1e..de4425b 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -35,6 +35,12 @@
 // A proto file we will use for unit testing.
 
 
+// Some generic_services option(s) added automatically.
+// See:  http://go/proto2-generic-services-default
+option cc_generic_services = true;     // auto-added
+option java_generic_services = true;   // auto-added
+option py_generic_services = true;     // auto-added
+
 import "google/protobuf/unittest_import.proto";
 
 // We don't put this in a package within proto2 because we need to make sure
@@ -489,6 +495,10 @@
   optional float nan_float = 19 [default = nan];
 }
 
+message SparseEnumMessage {
+  optional TestSparseEnum sparse_enum = 1;
+}
+
 // Test String and Bytes: string is for valid UTF-8 strings
 message OneString {
   optional string data = 1;
@@ -598,6 +608,7 @@
   repeated uint64  repeated_uint64  = 262143;
 }
 
+
 // Test that RPC services work.
 message FooRequest  {}
 message FooResponse {}
diff --git a/src/google/protobuf/unittest_custom_options.proto b/src/google/protobuf/unittest_custom_options.proto
index b6ee03d..a610785 100644
--- a/src/google/protobuf/unittest_custom_options.proto
+++ b/src/google/protobuf/unittest_custom_options.proto
@@ -35,6 +35,12 @@
 // A proto file used to test the "custom options" feature of proto2.
 
 
+// Some generic_services option(s) added automatically.
+// See:  http://go/proto2-generic-services-default
+option cc_generic_services = true;     // auto-added
+option java_generic_services = true;   // auto-added
+option py_generic_services = true;
+
 // A custom file option (defined below).
 option (file_opt1) = 9876543210;
 
@@ -273,3 +279,88 @@
   option (complex_opt3).complexoptiontype5.plugh = 22;
   option (complexopt6).xyzzy = 24;
 }
+
+// ------------------------------------------------------
+// Definitions for testing aggregate option parsing.
+// See descriptor_unittest.cc.
+
+message AggregateMessageSet {
+  option message_set_wire_format = true;
+  extensions 4 to max;
+}
+
+message AggregateMessageSetElement {
+  extend AggregateMessageSet {
+    optional AggregateMessageSetElement message_set_extension = 15447542;
+  }
+  optional string s = 1;
+}
+
+// A helper type used to test aggregate option parsing
+message Aggregate {
+  optional int32 i = 1;
+  optional string s = 2;
+
+  // A nested object
+  optional Aggregate sub = 3;
+
+  // To test the parsing of extensions inside aggregate values
+  optional google.protobuf.FileOptions file = 4;
+  extend google.protobuf.FileOptions {
+    optional Aggregate nested = 15476903;
+  }
+
+  // An embedded message set
+  optional AggregateMessageSet mset = 5;
+}
+
+// Allow Aggregate to be used as an option at all possible locations
+// in the .proto grammer.
+extend google.protobuf.FileOptions      { optional Aggregate fileopt    = 15478479; }
+extend google.protobuf.MessageOptions   { optional Aggregate msgopt     = 15480088; }
+extend google.protobuf.FieldOptions     { optional Aggregate fieldopt   = 15481374; }
+extend google.protobuf.EnumOptions      { optional Aggregate enumopt    = 15483218; }
+extend google.protobuf.EnumValueOptions { optional Aggregate enumvalopt = 15486921; }
+extend google.protobuf.ServiceOptions   { optional Aggregate serviceopt = 15497145; }
+extend google.protobuf.MethodOptions    { optional Aggregate methodopt  = 15512713; }
+
+// Try using AggregateOption at different points in the proto grammar
+option (fileopt) = {
+  s: 'FileAnnotation'
+  // Also test the handling of comments
+  /* of both types */ i: 100
+
+  sub { s: 'NestedFileAnnotation' }
+
+  // Include a google.protobuf.FileOptions and recursively extend it with
+  // another fileopt.
+  file {
+    [protobuf_unittest.fileopt] {
+      s:'FileExtensionAnnotation'
+    }
+  }
+
+  // A message set inside an option value
+  mset {
+    [protobuf_unittest.AggregateMessageSetElement.message_set_extension] {
+      s: 'EmbeddedMessageSetElement'
+    }
+  }
+};
+
+message AggregateMessage {
+  option (msgopt) = { i:101 s:'MessageAnnotation' };
+  optional int32 fieldname = 1 [(fieldopt) = { s:'FieldAnnotation' }];
+}
+
+service AggregateService {
+  option (serviceopt) = { s:'ServiceAnnotation' };
+  rpc Method (AggregateMessage) returns (AggregateMessage) {
+    option (methodopt) = { s:'MethodAnnotation' };
+  }
+}
+
+enum AggregateEnum {
+  option (enumopt) = { s:'EnumAnnotation' };
+  VALUE = 1 [(enumvalopt) = { s:'EnumValueAnnotation' }];
+}
diff --git a/src/google/protobuf/unittest_no_generic_services.proto b/src/google/protobuf/unittest_no_generic_services.proto
index fcae421..cffb412 100644
--- a/src/google/protobuf/unittest_no_generic_services.proto
+++ b/src/google/protobuf/unittest_no_generic_services.proto
@@ -32,9 +32,7 @@
 
 package google.protobuf.no_generic_services_test;
 
-option cc_generic_services = false;
-option java_generic_services = false;
-option py_generic_services = false;
+// *_generic_services are false by default.
 
 message TestMessage {
   optional int32 a = 1;
diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h
index d7b2c30..a461a6c 100644
--- a/src/google/protobuf/wire_format_lite_inl.h
+++ b/src/google/protobuf/wire_format_lite_inl.h
@@ -368,12 +368,24 @@
   return true;
 }
 
-template<typename MessageType>
-inline bool WireFormatLite::ReadGroupNoVirtual(int field_number,
-                                               io::CodedInputStream* input,
-                                               MessageType* value) {
+// We name the template parameter something long and extremely unlikely to occur
+// elsewhere because a *qualified* member access expression designed to avoid
+// virtual dispatch, C++03 [basic.lookup.classref] 3.4.5/4 requires that the
+// name of the qualifying class to be looked up both in the context of the full
+// expression (finding the template parameter) and in the context of the object
+// whose member we are accessing. This could potentially find a nested type
+// within that object. The standard goes on to require these names to refer to
+// the same entity, which this collision would violate. The lack of a safe way
+// to avoid this collision appears to be a defect in the standard, but until it
+// is corrected, we choose the name to avoid accidental collisions.
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline bool WireFormatLite::ReadGroupNoVirtual(
+    int field_number, io::CodedInputStream* input,
+    MessageType_WorkAroundCppLookupDefect* value) {
   if (!input->IncrementRecursionDepth()) return false;
-  if (!value->MessageType::MergePartialFromCodedStream(input)) return false;
+  if (!value->
+      MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input))
+    return false;
   input->DecrementRecursionDepth();
   // Make sure the last thing read was an end tag for this group.
   if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) {
@@ -381,14 +393,16 @@
   }
   return true;
 }
-template<typename MessageType>
-inline bool WireFormatLite::ReadMessageNoVirtual(io::CodedInputStream* input,
-                                                 MessageType* value) {
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline bool WireFormatLite::ReadMessageNoVirtual(
+    io::CodedInputStream* input, MessageType_WorkAroundCppLookupDefect* value) {
   uint32 length;
   if (!input->ReadVarint32(&length)) return false;
   if (!input->IncrementRecursionDepth()) return false;
   io::CodedInputStream::Limit limit = input->PushLimit(length);
-  if (!value->MessageType::MergePartialFromCodedStream(input)) return false;
+  if (!value->
+      MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input))
+    return false;
   // Make sure that parsing stopped when the limit was hit, not at an endgroup
   // tag.
   if (!input->ConsumedEntireMessage()) return false;
@@ -461,21 +475,24 @@
   output->WriteVarint32SignExtended(value);
 }
 
-template<typename MessageType>
-inline void WireFormatLite::WriteGroupNoVirtual(int field_number,
-                                                const MessageType& value,
-                                                io::CodedOutputStream* output) {
+// See comment on ReadGroupNoVirtual to understand the need for this template
+// parameter name.
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline void WireFormatLite::WriteGroupNoVirtual(
+    int field_number, const MessageType_WorkAroundCppLookupDefect& value,
+    io::CodedOutputStream* output) {
   WriteTag(field_number, WIRETYPE_START_GROUP, output);
-  value.MessageType::SerializeWithCachedSizes(output);
+  value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output);
   WriteTag(field_number, WIRETYPE_END_GROUP, output);
 }
-template<typename MessageType>
-inline void WireFormatLite::WriteMessageNoVirtual(int field_number,
-                                                const MessageType& value,
-                                                io::CodedOutputStream* output) {
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline void WireFormatLite::WriteMessageNoVirtual(
+    int field_number, const MessageType_WorkAroundCppLookupDefect& value,
+    io::CodedOutputStream* output) {
   WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
-  output->WriteVarint32(value.MessageType::GetCachedSize());
-  value.MessageType::SerializeWithCachedSizes(output);
+  output->WriteVarint32(
+      value.MessageType_WorkAroundCppLookupDefect::GetCachedSize());
+  value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output);
 }
 
 // ===================================================================
@@ -672,20 +689,26 @@
   return value.SerializeWithCachedSizesToArray(target);
 }
 
-template<typename MessageType>
+// See comment on ReadGroupNoVirtual to understand the need for this template
+// parameter name.
+template<typename MessageType_WorkAroundCppLookupDefect>
 inline uint8* WireFormatLite::WriteGroupNoVirtualToArray(
-    int field_number, const MessageType& value, uint8* target) {
+    int field_number, const MessageType_WorkAroundCppLookupDefect& value,
+    uint8* target) {
   target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target);
-  target = value.MessageType::SerializeWithCachedSizesToArray(target);
+  target = value.MessageType_WorkAroundCppLookupDefect
+      ::SerializeWithCachedSizesToArray(target);
   return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target);
 }
-template<typename MessageType>
+template<typename MessageType_WorkAroundCppLookupDefect>
 inline uint8* WireFormatLite::WriteMessageNoVirtualToArray(
-    int field_number, const MessageType& value, uint8* target) {
+    int field_number, const MessageType_WorkAroundCppLookupDefect& value,
+    uint8* target) {
   target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
   target = io::CodedOutputStream::WriteVarint32ToArray(
-    value.MessageType::GetCachedSize(), target);
-  return value.MessageType::SerializeWithCachedSizesToArray(target);
+    value.MessageType_WorkAroundCppLookupDefect::GetCachedSize(), target);
+  return value.MessageType_WorkAroundCppLookupDefect
+      ::SerializeWithCachedSizesToArray(target);
 }
 
 // ===================================================================
@@ -730,13 +753,17 @@
   return io::CodedOutputStream::VarintSize32(size) + size;
 }
 
-template<typename MessageType>
-inline int WireFormatLite::GroupSizeNoVirtual(const MessageType& value) {
-  return value.MessageType::ByteSize();
+// See comment on ReadGroupNoVirtual to understand the need for this template
+// parameter name.
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline int WireFormatLite::GroupSizeNoVirtual(
+    const MessageType_WorkAroundCppLookupDefect& value) {
+  return value.MessageType_WorkAroundCppLookupDefect::ByteSize();
 }
-template<typename MessageType>
-inline int WireFormatLite::MessageSizeNoVirtual(const MessageType& value) {
-  int size = value.MessageType::ByteSize();
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline int WireFormatLite::MessageSizeNoVirtual(
+    const MessageType_WorkAroundCppLookupDefect& value) {
+  int size = value.MessageType_WorkAroundCppLookupDefect::ByteSize();
   return io::CodedOutputStream::VarintSize32(size) + size;
 }