Squashed 'third_party/protobuf/' changes from e35e248..48cb18e

48cb18e Updated change log for 3.6.1 release
9e1286b Updated version numbers to 3.6.1
e508fc0 Check the message to be encoded is the wrong type. (#4885) (#4949)
fc90fd6 Make assertEquals pass for message (#4947)
d85ffdc Merge pull request #4924 from xfxyjwf/3.6.x
8356d27 Add continuous test for ruby 2.3, 2.4 and 2.5 (#4829)
7fdebf2 Fix cpp_distcheck
6c82411 Fix php conformance test.
11e2eca protoc-artifacts: Update centos base from 6.6 to 6.9
6fc2bac Updated Docker setup to use GCC 4.8
b3e4e3a Remove js_embed binary. (#4709)
0b3b470 Fix cpp benchmark dependency on mac
ae8def6 Comment out unused command from release script.
9327dc7 Run autogen.sh in release script.
9209a41 Add protoc release script for Linux build.
4d0fbd1 Add cpp tests under release docker image.
474fd31 Update protoc build scripts.
b23429e Fix 32bit php tests
8758cc1 Fix php tests
bd1224e fix golang kokoro linux build
359889b fix python cpp kokoro build
c1e6c4d fix linux kokoro build in docker
22503a0 fix for API change in PHP 7.3 (#4898)
e529d16 Make ruby release configs consistent with protoc.
82019f9 Merge pull request #4900 from xfxyjwf/3.6.x
0e38f9e Fix bazel build of examples.
b5975c1 Add kokoro bazel configs for 3.6.x branch.
4a4a60b Merge pull request #4880 from nashimus/3.6.x
e184577 Merge pull request #4878 from acozzette/fix-msvc-initialization
1f7837a Additional support for building and deploying ppcle_64 artifacts
a9abc78 Fix initialization with Visual Studio
f7ada12 Build ruby gem on kokoro (#4819)
56d2753 Rename build_artifacts.cfg to release.cfg (#4818)
b907a03 Add files to build ruby artifact for mac on kokoro (#4814)
ad85c3b Added Kokoro protoc release build for OS X (#4770)
885be9c Work around MSVC issue with std::atomic initialization (#4777)
b0a8220 Added Kokoro Windows release build config for protoc (#4766)
ce04481 Use legacy name in php runtime (#4741)
d6353b4 Update php version to 3.6.0 (#4736)
ab8edf1 Merge pull request #4713 from acozzette/changelog
6ed0141 Merge pull request #4730 from acozzette/xcode
a3f31bf Update code to work for Xcode 10b1 (#4729)
9b77e9e Removed javanano from post_process_dist.sh
adf84b4 Updated the change log with changes for 3.6.0
7e199b9 Merge pull request #4706 from acozzette/cxx-11
39d2f70 Require C++11 and pass -std=c++11
a239ed2 Merge pull request #4702 from TeBoring/3.6.x
4f5eb10 Move methods out of class (#4697)
397ddf9 Add back GeneratedClassName to public (#4686)
d31864a Merge pull request #4696 from acozzette/csharp-fix
6c12ff5 Merge pull request #4695 from TeBoring/3.6.x
9d64d74 Removed duplicate using statement from ReflectionUtil.cs
5bf35ec Fix php memory leak test (#4692)
edaaea0 Merge pull request #4687 from acozzette/js-map-parsing-fix
d1af029 Fixed JS parsing of unspecified map keys
6f723a6 Always add -std=c++11 for mac (#4684)
4885b80 Merge pull request #4675 from TeBoring/3.6.x
dadc954 Fix array constructor in c extension for compatibility (#4667)
2774e54 PHP namespaces for nested messages and enums (#4536)
8b336f8 Implement array constructor in php c extension.
c9b404d PHP array constructors for protobuf messages (#4530)
7eba624 Add missing ruby/tests/test_ruby_package.proto
c19fcee Allows the json marshaller to be passed json marshal options (#4252)
5289ee0 Adopt ruby_package in ruby generated code. (#4627)
d8483a9 Adopt php_metadata_namespace in php code generator (#4622)
449e532 Merge pull request #4673 from acozzette/memory-leak-fix
daf039b Make sure to delete temporary maps used by FileDescriptorTables
15cde29 Merge pull request #4625 from liujisi/3.6.x
45eb28b Update version number to 3.6.0
b61dd9d Add file option php_metadata_namespace and ruby_package (#4609)
2213c1c Merge pull request #4538 from Mizux/patch-2
7377d81 Throw error if user want to access message properties (#4603)
5f7334f Avoid direct check of class name (#4601)
5f9232b use brew install instead of easy_install in OSX (#4537)
25625b9 Merge pull request #4590 from PetterS/undefined_fix
d14cacd Fix error in Clang UndefinedBehaviorSanitizer
513b35d Add VS2017 optional component dependency details to the C# readme (#4128)
4a09836 Fix python ext build on kokoro (#4527)
92898e9 Merge pull request #4586 from chronoxor/master
3474155 MinGW build failed
b0403a7 Merge pull request #4583 from chronoxor/master
f80a886 Cygwin build failed
05c2d01 Fix RepeatedField#delete_if (#4292)
0869b1a Add space between class name and concat message (#4577)
306f4e3 Merge pull request #4581 from Yeolar/3rd_rpc_raster
7d97808 [objectivec] Fix memory leak of exceptions raised by RaiseException() (#4556)
35e4430 Add third-party RPC implementation: raster - a network framework supports pbrpc by 'service' keyword.
fc922d1 Merge pull request #4568 from hectim/master
7f2c3ce Merge pull request #4550 from Mizux/master
1b219a1 Fix to allow AOT compilers to play nicely with reflection
9ba2fd3 typo
a21f225 Merge pull request #4553 from pherl/ruby
9972e16 Set ext.no_native = true for non mac platform
2bd7f51 fix duplicate mkdir in update_file_lists.sh
c3b152c CMake: Update CXX Standard management
3ad8efc Add .proto files to extract_includes.bat
8417871 Move to Xcode 9.3 which also means a High Sierra image.
b59da6d Remove the iOS Test App.
c36eeed Merge pull request #4520 from BSBandme/fix_kokoro_benchmark_build
4ca46ed Write messages to backing field in generated C# cloning code (#4440)
0dc4d75 Merge pull request #4504 from xfxyjwf/lite
a29e2bf Update Makefile.am for Java lite files.
8f35073 Fix benchmark build
9497a65 Merge pull request #4517 from rcane/feature/vc2017_build_fix
a9d9326 Merge pull request #4510 from BSBandme/fix_kokoro_benchmark_build
7d6d5f9 Fixed a Visual Studio 2017 build error. (#4488)
0921345 fix java benchmark, fix dashboard build
7d55040 Cleanup + documentation for Java Lite runtime.
320d56c Merge pull request #4478 from BSBandme/proto2_to_proto3_tools
e3af023 fix python
76d76ae fix conflicts
c703061 Add gogo benchmark
5fb73f8 Merge pull request #4415 from BSBandme/experiement
805174e Add script for run and upload the benchmark result to bq
d7d863e fix json_decode call parameters (#4381)
13e627a includes the expected class in the exception, otherwise the error is harder to track down (#3371)
451e044 Add __init__.py files to compiler and util subpackages (#4117)
3b6d027 For windows, all python version should use /MT (#4468)
dce8229 Add the files added in #4485.
ce24b8a Update Xcode settings
da3ce67 Deliberately call simple code to avoid Unity linker pruning
a72da27 Merge pull request #4475 from chenchuanyin/patch-1
e7e6c6b Merge pull request #4283 from ObsidianMinor/csharp/better-test-runners
f72ac9f Updated csharp/README.md to reflect testing changes
d3e8a54 Fix problem: cmake build failed in c++11  by clang
c931743 Merge branch (#4466)
579f81e js message support for jstype string on integers (#4332)
40d6eca Merge pull request #4467 from xfxyjwf/error
8f88a50 Improve error message when googletest is missing.
7f92711 Merge pull request #4411 from pravin-dsilva/protobuf-ppc64le
4274e6a Merge pull request #4447 from ejona86/cleaner-protoc-artifacts
c934d1d Merge pull request #4452 from xfxyjwf/doc
aab0f89 Merge pull request #4464 from thomasvl/includes3
bd941d5 Don't generate imports for the WKTs unless generating the WKTs.
e998b8f Add compile test sources for to test include order.
bca797d Trim imports for bundled generated protos.
014e76e Update instructions about getting protobuf source.
cdbfdd8 protoc-artifacts: Use ENTRYPOINT to enable devtoolset-1.1
67c1cd4 protoc-artifacts: Avoid storing temporary files and use fewer layers
5f052ae protoc-artifacts: Avoid checking out protobuf code
7bf47a6 Merge pull request #4433 from xfxyjwf/license
c8ed695 Merge pull request #4445 from xfxyjwf/badge
eac0e92 Add kokoro build status badges.
59c4328 Merge pull request #4442 from xfxyjwf/clean
107cd70 Delete unused directories.
d3d7cdb Merge pull request #4439 from acozzette/remove-atomicops-stub
612b670 Updated .gitignore to exclude downloaded gmock/ directory
4875dfe Removed atomicops.h since it is no longer used
2537bea Merge pull request #3794 from jskeet/reflection
9c05c35 Address review comments
7b19d20 Add extra C# file to Makefile.am
8e23d4e Work around an "old runtime" issue with reflection
aa59eaa Introduce a compatiblity shim to support .NET 3.5 delegate creation
8ba420f Change C# reflection to avoid using expression trees
63bba9b Merge pull request #4432 from xfxyjwf/rmnanokokoro
5050269 Merge pull request #4434 from xfxyjwf/buildstatus
9f5bded Remove broken build status icons.
9e080f7 Cleanup LICENSE file.
68de0cf Delete javanano kokoro build configs.
3c5442a Include googletest as a submodule (#3993)
1156ee7 source code info for interpreted options; fix source code info for extension range options (#4342)
d34e319 Merge pull request #4431 from xfxyjwf/rmnano
379b7ff Fixes MSVC compiler warning C4800 "Forcing value to bool 'true' or 'false'" (#4350)
ac67376 Merge pull request #4395 from stone4774/fixbug_enum2json2
d5a0024 Remove javanano.
416d418 Merge pull request #4424 from egorpugin/patch-1
dc68d98 Fix missing LIBPROTOC_EXPORT.
2c963d3 Merge pull request #4413 from pmuetschard/msvc
eff52b1 Merge pull request #4422 from acozzette/ruby-conformance
cf7af01 Merge pull request #4421 from acozzette/fix-bazel-build
f91cf05 Updated Ruby conformance test failure list
5bed368 Added missing .inc files to BUILD
a7a746f Merge pull request #4346 from BSBandme/performance_result
745ef89 Add performance.md and add instruction for linking tcmalloc
227363b Merge pull request #4412 from acozzette/remove-old-files
a6957f2 Don't assume Windows builds use MSVC.
0c5fcde Removed some unused C++ source files
36ba04b Add support for power ppc64le
c99f527 Merge branch 'master' into fixbug_enum2json2
d053271 Use the first enum value instead of 0 in DefaultValueObjectWriter::FindEnumDefault
ed4321d Merge pull request #4387 from acozzette/down-integrate
e436ee0 Merge pull request #4361 from BSBandme/go_benchmark
88a4884 Merge pull request #4345 from jskeet/list-json-null
11d26ce Removed unused variables in repeated_scalar_container.cc
fcde518 Try using a new version of Visual Studio on AppVeyor
8b3a72f Removed unused code pertaining to shared_ptr
ec40953 Updated conformance failure lists
ec57f51 Added map_lite_test.proto to fix LiteTest
c5fcce5 Added pyext/thread_unsafe_shared_ptr.h
3fa5dad Removed unrecognized option from no_package.proto
00b1c14 Added new test source files to Makefile.am
616fe05 Removed use of some type traits
d6323c8 Change to deal all messages in one loop
d6a17aa Merge pull request #4397 from pherl/catlog
4880027 Cat the test-suite.log on errors for presubits
773d8c3 Fix bug: whether always_print_enums_as_ints is true or false, it always print the default value of enums as strings
ab95b1b Merge pull request #4371 from Rasrack/gnuc_minor
aae10ed Merge pull request #4370 from felixjendrusch/objc-output-stream-write-check
813848d Merge pull request #4222 from JohnHBrock/increasing_max_csharp_message_size
d5f5725 Merge pull request #4310 from KindDragon/patch-1
837c94b Include no_package.proto in Python test
67952fa Deleted scoped_ptr.h
b1216d9 Updated checked-in generated code
64a5c80 Fixed up proto3_lite_unittest.cc
501c13f Rewrite go_benchmark
afe96b6 Merge branch 'master' into down-integrate
0400cca Integrated internal changes from Google
89b5333 Merge pull request #4378 from acozzette/node-buffer
4f11025 Merge pull request #4167 from mike9005/patch-1
6d2c6a0 some fix
5487d8c Merge pull request #4380 from mateuszmatejczyk/patch-1
4787519 Merge pull request #1333 from cgull/pkg-config-issue
294b575 Output *_pb2_grpc.py when use_grpc_plugin=True
0e34c86 Fix spelling error of __GNUC_MINOR__
f8005a5 Revert "Removed mention of Buffer in byteSourceToUint8Array"
8e44a86 Merge pull request #4347 from xfxyjwf/pluginpb
6ebfa14 Merge pull request #4375 from jo2y/protoc-default
950f5e4 Replace //:protoc and similar default macro arguments with @com_google_protobuf prefixed versions. This allows them to work in 3rd party repositories.
6dd563a Sync upb change (#4373)
1da9ffe Check return value on write of raw pointer
38508e9 Add test for failing write of raw pointer to output stream
4e3c413 Add go benchmark
a48d58d Convert descriptortype to type for upb_msgval_sizeof (#4357)
0f4ad85 For encoding upb needs descriptor type instead of type. (#4354)
55d0758 Merge pull request #4355 from acozzette/typo
5004d09 PHP: fixed typo in message.c
fd595fc Revert "Move `compiler/plugin.pb.cc` to libprotobuf with the other WKT sources."
5140bae Add conformance test for null value in list JSON
822b924 Allow list values to be null when parsing
9dc0a4d Merge pull request #4183 from pcc/win-libcxx
325ecff Merge pull request #4333 from jmillikin/update-file-lists-needs-bash
32db4d3 Merge pull request #4334 from jmillikin/blacklist-internal-proto-srcs
3aaed96 Merge pull request #4195 from alexey-malov/IgnoreUnknownEnumsInJson
bb40c0c Merge pull request #4291 from google/3.5.x
350b135 Blacklist all WELL_KNOWN_PROTOS from Bazel C++ code generation.
724f0be Move `compiler/plugin.pb.cc` to libprotobuf with the other WKT sources.
2e4c52a `update_file_lists.sh` depends on Bash features, thus needs Bash sebang.
a6037c5 Merge pull request #4324 from abdul-sami/master
ac021a0 Merge pull request #1 from abdul-sami/abdul-sami-patch-1
fe33c5f Added instruction for existing ZLIB configuration
177108a Merge pull request #4323 from dtapuska/master
af3813c Rename a shadowed variable.
0475607 Merge pull request #3186 from gkelly/remove-unused-variable
22c477d Support using MSVC intrinsics in Log2FloorNonZero
02452db The JsonParseOptions::ignore_unknown_fields option behavior treats unrecognized string values in enum fields as default ones.
e34ec60 Only check filenames when end with .py in _CalledFromGeneratedFile() (#4262)
96b535c Merge pull request #4302 from BSBandme/down_integ_benchmark
6cd4ec4 Sync internal benchmark changes
4da7706 Remove stray indent on normal imports.
b8e4783 Merge pull request #4288 from nico/nofall
07f0231 Fix up the docs to mention the WKTs generated files also.
c66dd6c Remove use of GOOGLE_FALLTHROUGH_INTENDED from protobuf.
8b2ba9e Remove Google.Protobuf.Test/Program.cs from Makefile.am
a731ecb Adjusted appveyor batch
e823897 Updated NUnit packages, removed NUnitLite added packages for dotnet and Visual Studio, changed dotnet command in buildall to dotnet test, and deleted Program.cs (because it's no longer required).
82e0231 Merge pull request #4259 from Mizux/master
5dad7cc Merge pull request #4257 from davido/support_java9
9717d6f Merge pull request #4265 from BSBandme/upgrade_benchmark_submodule
1ec9beb Use NEW behaviour for project VERSION variables.
8dd0f4e Even with MSVC enable zlib support as default behaviour.
f7a0584 Add CMake ALIAS targets
3bc0282 Add VERSION property to CMake library targets
7f14915 upgrade submodule
4e2bd9e Merge pull request #4266 from brunokim/patch-1
0d397a1 Fix link markup in third party list.
6456e5d Merge pull request #4239 from mrpi/master
85b488f Bazel: Support building with Java 9
864df89 Remove 64MB memory limit when deserializing messages in C#
cf016a4 Work around strange error with atomic and swift under Xcode 8.3.3.
d570d48 Don't assume c-strings are 4 byte aligned.
d83837d Fix to use "nil" instead of "NULL" for objc objects.
81aeed0 Work around the static analyzer false report.
953adb1 Add casts to removed undefined behaviors around shifts.
b718551 Merge pull request #4249 from nlochschmidt/patch-1
204a641 Move kokoro macOS builds to to Xcode 9.1.
14e8852 Fix -fpermissive: '<::' cannot begin a template-argument list
69b1fdc Propose kotlinx.serialization as 3rd party lib
25a90e8 Merge pull request #3825 from ras0219-msft/patch-1
aaf41c6 Add Vcpkg to C++ installation instructions for Windows
1681fe6 Merge pull request #4196 from mathstuf/cmake-private-target-sources
f438ebd Merge pull request #4240 from davido/generate_warning_free_java_code
da6b07a Merge pull request #4209 from acozzette/using-statements
86fdad0 Java: Generate warning free code
39a789e Removed using statements from common.h
91317c2 Merge pull request #4236 from pherl/3.5.x
2a8e102 Bumping number to fix ruby 2.1 on mac
c236896 Merge pull request #4229 from leighmcculloch/patch-1
4a3b42e Remove broken link to code.google.com/p/protorpc
ed14fe4 Merge pull request #3934 from xfxyjwf/builtsources
0c52335 Update .NET SDK to 2.0.3
51293f3 Fix more memory leak for php c extension (#4211)
94f3be0 Merge pull request #4226 from themattchan/patch-1
3e1587f Add an explicit import of stdatomic.h.
6fd2ae7 Bring back import of OSAtomic.
72337d6 Add Haskell implementations
1d02e45 Merge pull request #4224 from davido/drop_java_6_support
019ceea Drop java 6 support
c337d9f Remove the use of BUILT_SOURCES
9ab859f Create std::string in Arena memory
80e016e Merge pull request #4205 from xuwei-k/patch-2
a721bf6 Migrate away from deprecated OSAtomic APIs. (#4184)
1c3b20b fix typo in FieldMaskTree.java comment
9d0a44c cmake: privately add sources to targets
cbdeb6a Merge pull request #4185 from pherl/ruby2.5
53d907f Update rake file to build of 2.1.6.
3ba21cd Add support for libc++ on Windows.
979c2cd Merge pull request #4182 from pherl/ruby2.5
d9f0f0b Support ruby2.5
47b7d2c Add DiscardUnknownFields support for C#
2a6eaeb Fix scope resolution for MessageExts in Ruby
9f80df0 Merge pull request #4158 from BSBandme/FixBenchmarks
473a810 Update py_benchmark.py
fa60e55 Fix java benchmark to use parser, fix cpp benchmark new arena to use Reset, format some files
b77aa80 Merge pull request #4148 from datacompboy/patch-2
d4afdba Merge pull request #4147 from datacompboy/patch-1
bab843b Merge pull request #4132 from BSBandme/JavaCaliperCounter
195253c Add counter to Java benchmark
4adc5a4 Merge pull request #4065 from BSBandme/python_benchmark_real
091eeb1 Update time_test.cc
473c5cf Fix ValidateDateTime: check day instead month
3823897 Well known types are not initialized properly. (#4139)
2fc69b1 Add python benchmark
5aa8f98 Merge pull request #4146 from pherl/fix_protoc
366192f Bump protoc-artifact version for a patch rebuild
a3868af Merge pull request #4131 from pherl/merge
eca1d2a Merge pull request #4116 from amandeepgautam/master
0c0d481 whitelisting aix platform as it has sched_yield
4588e6e Force a copy when saving the NSData that came from another.
43caa38 Merge pull request #4014 from BSBandme/JavaCaliper
ec826c5 Merge remote-tracking branch 'origin/3.5.x' into master
383a494 Merge remote-tracking branch 'origin/3.5.x' into master
39f577c Merge pull request #4124 from pherl/nullptr
5b1caea Merge pull request #4090 from pherl/nopassword
156161d Properly copy maps with string keys but pod values.
aca6c15 Fix some bug
4f3d865 remove nullptr
a147a21 Changed README
8529f2a Resolved issue #3510. Malformed errorr messages replaced with meaningful description
8fc40b5 Fix uploading binary wheel.
88e5573 Merge pull request #4089 from pherl/nocache
7ad8e7a Disable pip cache when testing uploaded packages
099d997 Merge pull request #4083 from matt-kwong/kokoro_jobs
0b2be3c Shard 64-bit Linux languages into different Kokoro jobs
4b2977b Merge pull request #4082 from matt-kwong/kokoro_jobs
ae49cfd Collect xml results for Kokoro
106ffc0 Merge pull request #4073 from pherl/changelog
d69f333 Merge pull request #4080 from pherl/arm64
6003a61 Make Kokoro job pull Dockerimage from Dockerhub
ad8a82e Add support for Windows ARM64 build
b5f09c1 Merge pull request #4077 from mkamilov/master
a5b743f Merge pull request #4030 from cyyber/master
7bf1e19 Update changelog
1e418e4 Merge pull request #4068 from wsw2016/fix_4032
ac1fdd1 line breaks adjsted
e68caa3 formatting issues
d106399 Merge pull request #4072 from google/jieluo
6c3c7f6 Merge pull request #4076 from pherl/stringback
b308580 Cherrypick for csharp, including: Add preserve UnknownFields Compare floating point values bitwise Add auto-generated header to C# generated files
19d0e99 Fix string::back() usage in googletest.cc
62616e1 Update changelog
96810de Merge branch '3.5.x' of github.com:google/protobuf into changelog
eff55ec Merge pull request #4074 from pherl/mapat
8ac050f Migrate Jenkins jobs to Kokoro
9ce29bd Merge pull request #4070 from pherl/3.5.x
501093d Replace C++11 only method std::map::at
7bd1606 Update changelog for 3.5.1
050fc9a Update version number to 3.5.1
ffa18ad resolve issue 4032 and added a unit test
03fb099 Add support for Windows ARM64 build
860d693 Add Xcode 9.2 to the testing support
3a06fe1 Fix file permission for python package.
77d32bc Merge pull request #4053 from xfxyjwf/fixumask
c79ba5c Merge pull request #4034 from TeBoring/php-timestamp-bug
269884a Merge pull request #4040 from bazurbat/3.5.x
0fc85ac Fix file permission for python package.
4b02091 add cpp
396336e Merge pull request #4046 from acozzette/deprecated-valueof-issue-2054
8d6f13e Fix for php5.5
1237c3f Merge pull request #4045 from pherl/deprecate
d971cbf Merge pull request #4049 from pherl/py26
39159c8 Accept DatetimeInterface in fromDatetime
0e2089c Calling Keychecker before checking key in MessageMap
acadade Remove py2.6 support.
594ec22 Fix python descriptor test.
cd32aae Merge branch 'master' of https://github.com/google/protobuf into JavaCaliper
75523ec fix bugs
1a549d9 Avoid using php_date_get_date_ce() in case date extension is not available.
0350111 Generate an annotation to suppress deprecation warnings
426cf6f Add auto-generated header to C# generated files (#4038)
34843ed Fix bugs
a4f68d4 Merge pull request #4044 from xfxyjwf/issue3268
00ac5c1 Merge pull request #4041 from acozzette/fix-license-issue-1775
22e1cfd Add deprecation annotation for oneof case.
b3ac441 Update generated code.
bfd254e  Add unknown field support for csharp (#3936)
50ef6a6 Avoid two consecutive underscores in macro name.
82724e2 Merge pull request #4042 from pherl/cpp_enum
8521624 Merge pull request #4043 from pherl/flush
0a7120a Merge pull request #4037 from xfxyjwf/issue2880
6b01e64 Explicitly propagate the status of Flush().
7ef21dd Use matching enum type for IsPOD.
ecab9c6 Added our standard license header to structurally_valid.cc and its test
edcf15e Create containing directory before generating well_known_types_embed.cc
5ce724b Merge pull request #4036 from xfxyjwf/issue3093
fffe8d3 Call php method via function name instead of calling directly.
0f9bfa8 Merge pull request #4016 from jquesnelle/string-access-ub
27e877f Merge pull request #2834 from aj-michael/master
6c27550 Clarify default value behavior in JSON conversion.
75eceb8 Update generated code.
8489612 Update comments for Timestamp JSON format.
f69a5db Merge pull request #4028 from TeBoring/3.5.x
88102ea Replace private timelib_update_ts with public date_timestamp_get
9f6acea Add PROTOBUF_ENABLE_TIMESTAMP to let user decide whether timestamp util can be used at install time.
5e732e3 Add caliper supported to java benchmark
b1386e7 Merge pull request #4026 from TeBoring/3.5.x
3b13c3f Add backslach to make class explict in global namespace
fc5818b Merge branch '3.5.0.1' into 3.5.x
31c54d1 Regenerated code from previous C# codegen commit
3e5bd2f C# code generation changes to use bitwise comparisons for doubles
f3e9a65 Compare floating point values bitwise in C#
618f06f Merge pull request #4007 from graywolf/patch-1
a426833 Merge pull request #4000 from Kwizatz/master
cf7c15e Fix ruby gc_test in ruby 2.4 (#4011)
9b09a2a Merge pull request #4017 from acozzette/update-file-lists
0fcca8f Merge pull request #4018 from acozzette/android-portable-log2-floor
f5b0862 use const char* instead of const std::string& in normalize()
63a0afc Use the portable version of Log2Floor for Clang with older Android NDK versions
0e7b589 Add discard unknown API in ruby. (#3990)
609d752 Ran update_file_lists.sh to update Bazel and CMake file lists
b32c2a8 fix undefined behavior in C++03
24493ee Using binary one's complement to negate an unsigned int
c370f88 Recursively clear unknown fields in submessages. (#3982)
1b5b3b2 Merge pull request #4013 from laszlocsomor/io_win32
a3a1c93 io_win32_unittest: remove incorrect error check
eb3bd6e io_win32_unittest: fix condition in GetCwdAsUtf8
3f1b1a6 io_win32_unittest: use CWD as last tempdir
57a01c7 io_win32: add more encoding-related tests
65da9fd io_win32: support non-ASCII paths
953a025 io_win32_unittest: make //:win32_test run again
457f6a6 Add release log
ba60b85 Update php c extension version number to 3.5.0.1
212563d Fix memory leak in php7
3b7a5f4 Fix several more memory leak
7d34371 Fix memory leak when creating map field via array.
e0d3aa0 Fix memory leak when creating repeated field via array.
de44982 Remove duplicate typedef. (#3975)
0316ae8 --pre is not necessary
9021f62 Merge pull request #3988 from acozzette/down-integrate
173f304 Merge pull request #3926 from BSBandme/down_sync_benchmark
e372df5 Fixed failing JS tests
db7c043 Merge pull request #3968 from fahhem/patch-2
35119e3 Add a check_protobuf_required_bazel_version() for use in WORKSPACEs
1fd6c17 Fix bugs to pass tests
7bb8584 Updated conformance failure lists
b140cb3 Fix memory leak when creating map field via array.
716acc3 Remove Xcode directives on some configs.
1acacf4 Fix memory leak when creating repeated field via array.
1c062a6 Sync internal benchmark changes
5d647e1 Updated Makefile.am to add a new file to EXTRA_DIST
0ba8eea Merge branch 'master' into down-integrate
92a7e77 Integrated internal changes from Google
a711e3d Merge pull request #3979 from acozzette/3.5.x-merge
a27da09 Merge branch '3.5.x' into 3.5.x-merge
94bb1ee Remove duplicate typedef. (#3975)
74e7dec Provide discardUnknonwnFields API in php (#3976)
6de51ca Merge pull request #3824 from anuraaga/dev_rag
da89eb2 Merge pull request #3955 from linux-on-ibm-z/master
6d60995 Update csharp version number (#3958)
0289dd8 Merge pull request #2519 from rubynerd-forks/ruby-fix-repeated-message-type-field
74f64b6 Fix JsonTokenizer exception message
3e944ae Add a UTF-8 decoder that uses Unsafe to directly decode a byte buffer.
3c6fd3f Merge pull request #3960 from acozzette/libprotoc-export-fix
1b1d1ea Added back in LIBPROTOC_EXPORT which was removed by mistake
34e30e5 Merge pull request #3962 from jleni/fix_dotnet
582d6ac Upgrading dotnet to 1.0.4
f2127b6 Merge pull request #3416 from xiaoshuang-lu/PROTOBUF-3404
642e1ac Adding Release_CompareAndSwap 64-bit variant
8ff2284 [PROTOBUF-3404] add --with-zlib=PATH to configure.ac script
cf65a79 Update version for 3.5.0.post1
f466709 Merge pull request #3941 from google/anandolee-patch-2
45d99a1 Add _file_desc_by_toplevel_extension back
f08e4dd Merge pull request #3919 from jart/less-warnings
b819abf Merge pull request #3918 from OEP/fix-sdist
ac5371d Remove unhelpful build warnings
9935829 Include .cc and .h files in source distribution
baed06e Small code reorder to maybe make #3893 happy.
6700f41 Travis config cleanups and move ObjC to Xcode 9.1.
2b3aa1c Add Setter/Getter type verification. (#3880)
8537f1e Fix up warnings from Xcode 9.1 (#3887)
98836a5 Update version number for php c extension (#3896)
e99e5d0 Merge pull request #3895 from pherl/3.5.x
1ec45f8 Add protobuf-all in post release
857a021 Use fully qualifed name for DescriptorPool in Any.php to avoid name (#3886)
0d46688 Update README.md: C extension works on PHP 7 (#3888)
696653d Merge pull request #3892 from sergiocampama/32bit
7daa320 Merge pull request #3878 from Yangqing/master
02129f0 Fixes 32bit tests.
cf68531 Merge pull request #3891 from thomasvl/travis_cleanups
7417755 Merge pull request #3883 from dmaclach/map_optimizations
8ae6844 codereview cleanup
6552c5a Merge pull request #3884 from dmaclach/unsafe
4ba3092 code review cleanup
af5ad24 Merge pull request #3882 from dmaclach/removeclass2
a839c67 Remove the allowed_failure for python_cpp as the bug was fixed.
2e17639 Remove the ruby tests from travis configs.
c46571b Update some comments about testing.
73e8c8a Instead of listing and then excluding osx builds, just don't list them.
949596e Simplify getter/setter method implementations
9d7f313 Reduce size of GPBDictionary by getting rid of class creation methods
37a6672 Remove unreferenced 'GPBMessageSignatureProtocol' class.
91ff83c Remove non-C# options from C#-only test protos
cba18ef Allow one to omit building libprotoc and protoc binaries
d3537c2 Merge pull request #3834 from sviterok/patch-1
0cd2ad1 Update protoc-artfacts
2720cdc Update README.md
4041600 Merge branch '3.5.x' of github.com:google/protobuf into 3.5.x
4493595 Update release date
2761122 Merge pull request #3868 from pherl/3.5.x
b9f891e Merge pull request #3875 from hchasestevens/add-hypothesis-protobuf-doc
188f180 All integer types should accept null in json. (#3869)
3c33143 Add hypothesis-protobuf library to the 3rd party doc.
8cf53f8 MMinor fix-ups to C# tests from changes in earlier commits
b5cdf0e Regenerated test code for C#
aa77eab Move C#-only test protos to csharp/protos
9a9a66e Run C# codegen when testing it
9c197b7 Support win32 long path for cross compiled build
fe2b4af Merge pull request #3867 from jtattermusch/update_changelog
07df230 update changelog
966a9ed Merge pull request #3861 from jtattermusch/backport_3858
5f96191 ParseFrom<T> for array slice is missing
4a5e1bd check already performed by MergeFrom
435f611 allow message parsing from an array slice
ce0a532 Merge pull request #3858 from jtattermusch/parsing_from_slice
5eb717c Fix arm64 name
b879abc Supports Arm64 (aarch64) protoc artifacts
30b6e54 ParseFrom<T> for array slice is missing
07542e7 check already performed by MergeFrom
0c874a6 allow message parsing from an array slice
0971efb Merge pull request #3854 from pherl/3.5.x
662e8b2 Provide util funtions to figure out correct php class names. (#3850)
181e284 Fix Atomic32/AtomicWord on some platforms.
1144768 Merge pull request #3835 from pherl/3.5.x
8a3c5cc Fix java code example
ce2d528 Changelog for 3.5.0
c258fb3 Merge pull request #3822 from mehrdada/update-benchmark-submodule
2df4726 Fix php well known type conformance tests (#3828) (#3840)
bcda919 Fix php well known type conformance tests (#3828)
239dba5 Merge pull request #3839 from thomasvl/message_equality
1f57e54 When comparing message, require them to have the same descriptor.
1908012 Update generated descritpors.
97dd175 Update version number to 3.5.0
da3bfa6 Fix a typo in WKT's test suite
cbe2505 Fix merging with message-valued oneof
bb35f04 Update google/benchmark submodule to v1.2
6dd8224 Merge pull request #3817 from xuwei-k/joda-url
05b56d0 update joda-time javadoc url
e8c9ae1 Add parser settings WithXyz methods
a985451 Add JsonParser setting to ignore unknown field values
4526d8b Merge pull request #3722 from timou/cmake-windows-clean
23adfeb Reserve unknown in Ruby (#3763)
a08b03d Add missing files
9aaa8e1 Merge pull request #3804 from pherl/merge
2fc7aea Merge pull request #3791 from signalwerk/patch-1
cdc0d95 Merge remote-tracking branch 'origin/3.4.x' into master
ee8a091 Merge pull request #3787 from sergiocampama/coverage
b1f954e Improves coverage of GPBCodedInputStream
44daa59 To be clear that we set a new variable
a23669c Sort MSVC warning suppressions
cefa9d7 Merge pull request #3758 from spinorx/3.4.x
b189389 Merge pull request #3757 from spinorx/master
09e0dbc Merge pull request #3743 from Schtolc/master
2a14214 Merge pull request #3754 from toanju/gcc-fallthrough
07b9238 Merge pull request #3770 from pherl/3.5-integrate
2ee294d Fix Java 1.6 compile
9c407a1 Merge pull request #3751 from uykusuz/master
ca6187d Merge pull request #3578 from pherl/filedeprecation
dedf904 Merge pull request #3764 from zearen/patch-1
37f984f Merge pull request #3698 from hesmar/hesmar/fixProtocIncludeDirs
3d6cc0e Merge pull request #3641 from drivehappy/3.4.x_clang_cleanup_3
2e2614e Merge pull request #3706 from johanbrandhorst/patch-1
188755c Fix JS conformance tests
1c682e0 Fix bazel build
ecf2957 Update descriptor protos
30bfe36 Merge pull request #3736 from jleni/fix_rbpi
6b5912b Merge branch 'master' of github.com:google/protobuf
1a7a7fc Merge from google internal
dc9190f Merge pull request #3769 from pherl/io_win32
cc58be6 Fix unsiged underflow
7dbee32 Remove C++11 only usages in io_win32 tests.
c4f59dc Merge pull request #3760 from jmillikin-stripe/descriptor-memset-ub
aff1097 Fix undefined memory management found by Clang's sanitizers.
3130ce0 Fix iOS cc_library build for protobuf.
16792c6 Fix iOS cc_library build for protobuf.
37e112f fix implicit fallthrough in gcc 7
be13314 fixes issue #3750
f850188 Merge pull request #3744 from fmarier/json-escaping-namespace
5992e24 Move namespace closing brace inside the header guard block
a632f0d Merge pull request #3739 from pherl/merge3.4
1e58006 test for field reassignment
38fd94e CodedInputStream::SetTotalBytesLimit description fix
dd980cc Fix distcheck
de15e73 Merge remote-tracking branch 'origin/3.4.x' into master
08334f0 Converting to immutable hashable types
c4083bb Merge pull request #3735 from sgreenstein/patch-1
68ee916 Don't pass -lpthread and -lm on Windows
6032746 Reserve unknown fields in php (#3659)
d2a5f8b Update third_party.md
2a72840 Suppress VS2017 compiler/linker warnings
77f64bb Add well known types to php runtime. (#3697)
cd5f49d Fix ruby segment fault (#3708)
d6c32a8 Merge pull request #3714 from thomasvl/objc_increase_test_coverage
a274c67 Build out more complete code coverage in the tests.
9477123 Let Xcode 9 update project/scheme settings.
4207066 Merge pull request #3710 from thomasvl/xcode9
c4dce01 Merge pull request #3709 from thomasvl/unknown_field_merge_issue
b586e64 Add Xcode 9 support to the helper script.
3f2dcae ObjC: Fix merging of length delimited unknown fields.
210be26 Use constexpr more with VC++ 2017 (#3707)
fc7a6a2 Add GopherJS protobuf and gRPC links
bd798df Merge pull request #3690 from pherl/3.4.x
a38f876 Merge pull request #3691 from pherl/stringback
f7e2099 protobuf_generate: create include path only for proto files
d2738c0 Add spaces
5a501c6 Fix C++11 string accessors
6d0cf1b Remove ranged based for in io_win32.cc
fc5aa5d Merge pull request #3676 from hesmar/hesmar/fixProtobufGeneratePython
0e069e5 generate python code when calling PROTOBUF_GENERATE_PYTHON
ae55fd2 Enforce all error report for php tests. (#3670)
c204402 Merge pull request #3675 from hesmar/hesmar/cmakeAddDllExport
9829b8f protobuf_generate: add EXPORT_MACRO option
c627530 Merge pull request #3674 from pherl/shutdown
4fc7529 Merge pull request #3627 from zanker/zanker/add-submsg-hash-init
b091bfb Test Shutdown can be called multiple times.
633ef8b Update message.c
2b0ee3f Add $ before url_prefix_len to make it a variable. (#3668)
eade82c Merge pull request #3639 from zanker/zanker/fix-embedded-to_h
8eae3fe Update message.c
8771483 Allow initializing a chain of protos using only a hash
83264bd Fixed to_h with repeated messages to return hashes in Ruby
cf1b29d Merge pull request #2377 from mcos/chore/conformance-null-tests
fa5a69e Merge pull request #3624 from acozzette/down-integrate
655cc83 Merge pull request #3651 from pherl/3.4.x
2eb1bac Bumping minor version for ruby gems
5dd818c Merge pull request #3612 from TeBoring/php-bug
b04e5cb Merge pull request #3642 from pherl/3.4.x
dba647a Bump version for minor release
e3be1fe Clang warning cleanup for unused parameter.
13fd045 Integrated internal changes from Google
d1bc27c Merge pull request #3626 from xfxyjwf/fixgo
8136ccb Fix go example test.
c0d88ae Merge pull request #3635 from drivehappy/clang_cleanup
7f3ded6 Clang warning cleanup for unused parameter.
471b45e Merge pull request #3158 from yeswalrus/fix-policy-warning
3d78561 Merge pull request #3634 from TeBoring/ruby-bug
a459b22 Storing the frame on the map means we don't need the array
c1dd8e8 Move parse frame array to the Map object
8741da3 Revert "Fix js conformance tests. (#3604)" (#3633)
a425dd9 Rename ClassNamePrefix to ConstantNamePrefix
2bd55a9 Fix js conformance tests. (#3604)
f46a01d Exclude valid constant name from reserved name.
06aa8dc Merge pull request #3621 from jtattermusch/upport_3596
ed0a07e Merge pull request #3618 from hesmar/fix_protobuf_generate
5de0565 Google.Protobuf should target net45
444aecd fix protobuf_generate function
b1befb0 Merge pull request #3613 from xfxyjwf/bazel_examples
6945203 Exclude addressbook.proto from C# boostrap test.
ddb9ef9 Change array to map for reserved names in c extension
49b31dc Update C# generated file for addressbook.proto
49b88af Update examples file list.
89069de Change array to associate array.
174c82d Add well-known timestamps to JSON for PHP (#3564)
74bf45f Add bazel support for examples.
e5d000c Add prefix to php reserved keywords.
2ad5c0a Merge pull request #2576 from cristicbz/py-strutil
6a4ffb2 Merge pull request #3596 from jtattermusch/csharp_target_net45
054054c Merge pull request #3590 from NanXiao/patch-1
7f8b91f Add native php support for Duration. (#3583)
35b852f Merge pull request #3594 from buchgr/well-known-protos
699c0eb bazel: Add proto_library rules for well known types. Fixes #2763
50a6475 Google.Protobuf should target net45
f4ff17b Update autogen.sh
6699f2c Merge pull request #3560 from tenderlove/thread-safe-map
f9b8169 Add TODO
dd69d5c Fix dist check
baae7ea Add @Deprecated annotation support for proto file.
b70e0fd Add php support for Timestamp. (#3575)
2807436 change the field number of php_generic_service to fix the conflict with (#3576)
f55c6ec Storing the frame on the map means we don't need the array
d6152dd Move parse frame array to the Map object
c7457ef Add any support in php runtime. (#3486)
21b2372 Merge pull request #3565 from pherl/fixdist
d8c6193 Add mising cmake files in dist
98a3734 Merge pull request #3503 from gburgessiv/master
859d94a Merge pull request #3544 from anandolee/master
92ea0d2 Merge pull request #3556 from matt-kwong/kokoro_mac_v3
78432ea Remove pre-installed softwares
07de70e Merge pull request #3555 from pherl/fixdist
364060b Merge pull request #3547 from matt-kwong/kokoro_mac_build
55fdbe5 Make distcheck aware of test proto files.
e46caba Remove pre-installed softwares
c44c3af Merge pull request #3548 from google/3.4.x
30681c7 Merge pull request #3546 from pherl/deathtest
610e433 Drop python2.6
028d6f1 Add Python 3.5 3.6
6609e52 Disable death tests on windows
e416f5d Merge pull request #3537 from TeBoring/php-bug
7273b3c Merge pull request #3539 from drivehappy/3.4.x_clang_cleanup_1
09fd125 Merge pull request #3540 from drivehappy/3.4.x_clang_cleanup_2
7a43137 Merge pull request #3543 from tony612/patch-1
6cecd20 Work around a bug in clang's static analyzer
2fb7479 Add Elixir protobuf and gRPC to 3rd party doc
c27b56c Merge pull request #3494 from drivehappy/clang_warning_macro
36ac06f Merge pull request #3535 from drivehappy/clang_warn_cleanup
0b7e978 Merge pull request #3535 from drivehappy/clang_warn_cleanup
92d768c Merge pull request #3536 from pherl/io32_11
77a453a Fix compile errors
dd51909 Use message name as defined in php runtime.
4aadcd3 Remove C++11 features in io_win32.cc
ba4e547 Merge pull request #3529 from pherl/merge3.4.x
472f700 remove the parens from the cmp() lambda definition (#3526)
1183f48 Fixing unused parameter warnings under Clang.
139775c Merge remote-tracking branch 'origin/3.4.x' into mergemaster
26ac3e8 Merge pull request #3528 from pherl/rubyfix
fdb5cd5 Merge pull request #3504 from pherl/3.4.x
d76e4c7 Bump gemspec again
1825d6d Merge pull request #3317 from ejona86/protoc-artifacts-jdk8
c2aa26e Revert "Drop Python 3.3 from testing & add Python 3.5, 3.6 (#3512)" (#3524)
703f414 Drop Python 3.3 from testing & add Python 3.5, 3.6 (#3512)
a04eb8c Define cmp() for Python 3 (#3517)
1aa2c34 Merge pull request #3516 from cclauss/patch-3
dded80f define long() for Python 3
6f4c9b0 print() function for Python 3
a1acf25 print() function and lose the semicolons (;)
067543c from __future__ import print_function
7daedbd print() function & define raw_input() for Python 3
45483fd file() was removed in Python 3, use open() instead
5ab8ae7 Merge pull request #3511 from cclauss/patch-3
fa46d11 Merge pull request #3514 from pherl/rubyfix
29c24ab Merge pull request #3502 from pherl/pypi
1926636 Bump gem version for the next upload
958412e Old style exception --> new style exception
d1484cd Update CHANGES.txt
55d938c Update CHANGES.txt
98c6d04 Prefer system distributed binaries/libraries.
e243082 Update php version number to 3.4.0
82dd4b3 Update php c extension version number.
5d5df84 clean up
19a7e20 Update testpypi addresses.
80a37e0 Merge pull request #3495 from pherl/c++11
5e39ecc Merge pull request #3494 from drivehappy/clang_warning_macro
3d2f72b Merge pull request #3496 from pherl/mingw64
6654c8d Update readme
f619621 Merge pull request #3493 from pherl/cmath
d909834 static link for 32 bit build as well.
f7b3dd4 Update comments that cross compile is feasible now
fa086c8 First try static linking pthread
4a4c67b Add std::forward and std::move autoconf check
a23e198 Fixing warning under Clang 6.x (-Wexpansion-to-defined) where the macro expansion producing 'defined' was warning on undefined behavior.
3908b4e Fix cmath/math.h include with non C++11 libstdc++
1cc4ecd Merge pull request #3488 from pherl/changelog
3ae8c4c Update changelog for 3.4.x
eaeca0d Merge pull request #3485 from pherl/mingw
1bd2d1f Merge pull request #3484 from pherl/qualifier
651429b Fix comments
31b3bd9 Make compilers without ref-qualifier support happy.
b4c0cfe Add malloc cast
fd31899 implement remove strdup usage and implement our own
34ebca0 Adding missing imports for strdup
40d1855 Fix mkdir
564f02c Make win32_io only for MSVC
7afa796 Fix the declaration order in ming32
db125b8 Fixing io_win32 for MinGW32
e0d24cc Detect invalid tags with a field number of 0 in C#
d2f3adb Merge pull request #3481 from pherl/nowarning
ccb6b62 Merge pull request #3480 from bklarson/master
1b42347 Clean up typedefs for Atomic32/Atomic64
e8fc066 Make no warning test stricter.
9adb4e8 Merge pull request #3478 from pherl/warning
97d50e3 Make code free of missing-field-initializers warnings
35db267 Merge pull request #3473 from AlanBurlison/master
80e984e Merge pull request #3467 from thomasvl/bump_xcode_version
a68a800 PROTBUF-3394 Potential SIGBUS with UnsafeUtil.getLong
3afcded Merge pull request #3461 from TeBoring/3.4.x
176713d Merge pull request #3468 from vladmos/3.4.x
fae3816 Merge pull request #3454 from anandolee/master
06a825c Make .bzl files compatible with future versions of Bazel
d08c291 Merge pull request #3465 from vladmos/list_plus_equals
fe68821 Move travis to the Xcode 8.3 (8.3.3) image.
ba81c59 Fix up Xcode 8.3.x support.
4fc9304 Make .bzl files compatible with future versions of Bazel
8f4b8e4 Merge branch 'master' into 3.4.x
f14703c Update commit id in Dockerfile to reflect change in #3391 (#3459)
49b44bf Fix the bug in php c extension that setting one field can change anotherĀ field's value. (#3455)
21b0e55 Update PHP descriptors (#3391)
f5817b3 PY26 tests compatibility 1, Some tests in reflection_test PY26 raise TypeError but other versions raise ValueError for convert negative long to unsigned 2, Change compare exception type to compare exception str for testDuplicateExtensionNumber. Original code raise 'Double registration of Extensions' is not an instance of (<type 'exceptions.AssertionError'>, <type 'exceptions.ValueError'>) for PY26 cpp implementation
1ab5adb Merge pull request #3456 from giorgioazzinnaro/patch-1
a3e1752 Update third party addons with ProfaneDB
9150cd8 Skip setUpClass which is newly added in python2.7 for python2.6
d58df3b Add python 2.6 test back for cpp implementation. Json format issue was fixed in #869
c2f69d6 Merge pull request #3450 from pherl/invalidoffset
e243fd8 Merge pull request #3451 from pherl/fixtypo
39a91d3 Fix typo.
4cbbf33 Fix invalid offsetof warning.
25672c1 Add getClass for php Descriptor in c extension (#3443)
7781784 Add destructors for default instances to the shutdown code. Verified test succeed under draconian heap checker
53ae6de Merge pull request #3442 from pherl/csharpversion
6c64f11 Bump csharp version
e0288e7 Merge pull request #3438 from pherl/changelog
9df89cc Fixing HHVM Compatibility (#3437)
c15a326 Expose descriptor API in php c extension (#3422)
8a5208f Update change log
502624f Merge pull request #3419 from pherl/3.4.x
d77c8c5 remove the duplication
bcf1733 Adding the missing header
ebeb472 Export functions in io_win32.h in win DLL build
be73938 Change divideInt64ToInt32 to static (#3436)
d32f5b4 Removes unnecessary pass-by-references in PHP internal classes (#3433)
0724314 Merge pull request #3429 from king6cong/master
d6bd959 Merge pull request #3406 from ax3l/bg-3.4-cmake-pkgconfig
547d76e Add classpath for java example Makefile
9b505a9 Merge pull request #3421 from thomasvl/update_comment
9a4692d Update the comment on the message_type to cover what it should be.
5eb95ef Merge pull request #3420 from thomasvl/objc_proto2_conformance
3caf9fd Review feedback.
c2831a3 Add the proto2 message conformance support for ObjC.
9fd5e59 Generate the proto2 test file and link it in for ObjC.
21800ff Add a objc_class_prefix to test_messages_proto3.proto.
19b8c8b Update conformance tests again.
8d5f2c5 Merge pull request #3410 from adam-26/1745
12c186f Fix makefile.am
de6debc Fix conformance tests
e177739 Fix build files
9b8f658 Remove dependency on guava 20
d974cc2 Update conformance tests
f39d4de Merge remote-tracking branch 'origin/master' into merge
759245a Merge from master
bb86644 need for php math functions. used in mergeFromJsonString (#3409)
e9f4e8e Merge pull request #3407 from bklarson/master
451d061 Fix cycle dependency for repeated field not collected by gc (#3399)
4bff88e Merge pull request #3413 from pherl/3.4.x
ce44167 Merge remote-tracking branch 'origin/3.4.x' into vb
4ae94d6 Merge pull request #3414 from pherl/fixzip
eb6b332 Merge pull request #3412 from anandolee/3.4.x
02250a7 Omit the zip test if tools are not available
9c012ed Add __bool__ as well as __nonzero__ for python3
11b4d5e Update required version on pre-generated files
8b24feb Update pre generated files
7bb39be Update version number for 3.4.0
a484794 Use keys() instead of iterkeys() to be python3 compatbile.
72cc5a6 Merge pull request #3393 from pherl/3.4.x
b6da226 Put AddDescriptorsImpl() in anonymous namespace
a713b73 Merge pull request #3281 from BSBandme/ConformanceTestYilunChong
2b6db00 Fix quotation marks
a3a65b3 Fix issue #1745 - javascript allow dot in filename
f15185d Merge pull request #2969 from laszlocsomor/master
0d9a34c Add -Werror=missing-declarations to test builds
ebe659d Travis: Exclude CMake .pc files
2f3cf52 CMake: Install .pc Files
eef2edc Merge pull request #3403 from ax3l/topic-cmake-pkgconfig
74dcf44 Travis: Exclude CMake .pc files
668712c CMake: Install .pc Files
e8a32d0 Merge pull request #3401 from aschrijver/patch-2
d640cdd Updated outdated hyperlink
062df3d Merge pull request #3179 from bjwatson/fix-duration-typo
040f56e Merge pull request #3397 from acozzette/initialization
bba4c4a Merge pull request #3262 from snnn/master
417aae6 Fixed dynamic initialization for C++ lite
dd091aa Fix code to use values() instead
aa61bb0 compiles removal of newline (#3333) (#3370)
1876a27 Update filelist again
66c1dac Add lite and python extra_dist files
bf658c2 Add java and JS dist files.
988376c remove broken imports in JS
b07cdb6 Use itmes() instead of itervalues() to be python3 compatbile.
e45214e Fix distcheck
8084e03 remove profile
11b6661 update build file list
7986ca7 Update conformance tests
50aa4fe Merge pull request #3375 from TeBoring/3.3.x
3af881c Merge master into 3.4.x
8697530 Update csharp and php descriptor
09354db Merge from Google internal for 3.4 release
942a29c Merge pull request #3390 from danielgtaylor-isp/patch-1
6ec0b7e Merge 3.3.x into master
3370299 Merge pull request #3385 from anandolee/master
4b5b1e6 Add note about includes to README
9e745f7 Support PHP generic services (#3269)
b764e67 Set PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION for pure python comformance test
3354558 Merge pull request #3348 from matthauck/fix-gcc41-again
dd6e420 Merge pull request #3357 from bklarson/master
eb8e3d3 Merge pull request #3134 from lundefugl/javabug1
aaa2550 Merge pull request #3372 from dylanetaft/master
324b20a remove pass by reference for php setters (#3344)
29ff49f Fix Implicit Return Types (#3363)
36fcc2a Expand documentation in Readme.md
c78dbd7 Initial value in generated code cannot be used by c extension. (#3367)
ec3f5dc removes an accidental newline in printing for the php generator (#3333)
3a0382e Add map iterator for c extension (#3350)
d3bbf1c Add space between arrow and casted type (#3353)
6aa4b20 Merge pull request #3327 from htuch/fix-3322
71f2f0d Fix repository URL in C# project file
81142e1 Fix build when using -Werror=undef
727c0dc C#: Implement IReadOnlyDictionary<K,V> in MapField<K,V>
2130fea Fix map_field_inl.h for gcc 4.1
e05e777 Windows: support long paths
9ab7c73 Fix missing std::tr1::hash on GCC 4.1 (#2907)
126082c Add std:: namespace prefix to set and map (#3332)
b9c4daa Uncomment php tests (#3301)
f6ff32c Use consistent hash across NDEBUG/!NDEBUG builds.
bd5ab15 Merge pull request #2482 from andreaseger/fix_ruby_timestamp_accuracy
a9e7a15 protoc-artifacts: Bump JDK to 8u131
bceb830 add comments in makefile.am
6bd51a5 add Grpc Protobuf validation (#3311)
32c8ed3 change csharp failure list
30b4194 Merge branch 'ConformanceTestYilunChong' of github.com:BSBandme/protobuf into ConformanceTestYilunChong
7339c25 delete backup files
cbf7dfb fix php failing list and csharp generated proto
e264b20 Merge pull request #3315 from thomasvl/mutate_unknowns
b30dee3 Expose the initializer for unknown fields.
cdd524a Ensure leaveOpen is true when writing to a buffer
62d7fe5 Make Any easier to work with in C#
e82ba0b Merge branch 'master' into ConformanceTestYilunChong
726ba33 changed php's failing list
5085102 remove backup files
3adb054 add some test proto2 supported, add js proto2 supported, fixed some error
ecca6ea Add json encode/decode for php. (#3226)
a7d5be6 change php objc nodejs csharp ruby
fcb9268 change java to uniform message, revert TestValidDataForType's parameters
020a24d change cpp and python to uniform message
5a52b35 Merge pull request #3287 from sergiocampama/initialized
e55782f Add initialized as a reserved keyword as that's the actual property name
467c1cc fix csharp conformance test
db379e6 fix csharp conformance test
176bac6 Add scripts to build python wheel for linux. (#2693)
ff773c1 fix csharp
cd1dc3f add csharp support
3645021 add message set test case
06c9057 add objec support
5e7e2d3 revert ruby proto built files
cf7b6a4 delete backup files
6c59c25 delete binary
91da852 update .gitignore
0255431 revert .gitignore
696cf77 add java supported
0fa4e58 change ignore
18a0c2c add proto2 supported for cpp,python,nodejs,ruby,php
12acbc2 adds PHPDoc @return and @param for getters and setters respectively (#3131)
2ad74e1 add support for proto2
097bfb5 Merge pull request #3084 from lukaszx0/patch-1
dd7265e Merge pull request #3264 from TeBoring/php-bug
e3c807d Fix more implicit type conversions in public headers and generated code.
1a7e49d Merge pull request #2968 from ngg/cpp-proper-fwd
9c0b35c Enusre public header and generated code have no implicit converion.
4e67590 fix readme.md
58a3c74 add test_proto2_message.proto and change conformnace/makefile.am
f752d81 Merge pull request #3266 from mbrickn/patch-1
d07efba Updated links to use https
eca0f4e Merge pull request #3261 from thomasvl/super_oddcase
db45687 If we fail to get a descriptor just super the method resolving.
4987dda Fix a bazel build error on Windows
5555d3b Fix typos in comment
5532abc Merge pull request #3258 from TeBoring/3.3.x
5520b43 Update C++ generated code.
e7bcfc4 Update version number to 3.3.2
8ecae34 Merge pull request #3255 from TeBoring/3.3.x-3
3b1a875 Remove inclusion of ext/json/php_json.h. (#3241)
c344fe8 Oneof field should be serialized even it's equal to default. (#3153)
dba8928 Add ARRAY for reserved name (#3150)
703cd8e Switch to addEnumType to fix fatal error (#3225)
1325588 Updated upb to fix JSON conformance issues. (#3206)
c2fdef0 Merge pull request #3243 from yjjnls/master
73b7cc0 Merge pull request #3244 from thomasvl/complete_docs
5fd71ce ObjC: Document the exceptions on some of the writing apis.
72e293a Merge pull request #3240 from thomasvl/float_fun
8f367c0 replenish missed header files in install step
5729cf7 Remove inclusion of ext/json/php_json.h. (#3241)
dd19b87 Raise the number of digits used for floats.
710543d Merge pull request #3237 from calder/patch-1
491b320 Merge pull request #3236 from buchgr/bazel-links
888e287 Merge pull request #3235 from buchgr/java-target
4b36d40 Qualify string in java_options.h
36e63da bazel: Make compiled jars java 6 binary compatible.
d0e6f3b bazel: add bazel symlinks to .gitignore
91bf623 Fix php jenkins test (#3233)
8d97b3d Fix incorrect function call (#3232)
b9b34e9 Follows proper autoloading standards (#3123)
09d2994 Merge pull request #3228 from thomasvl/add_tvos_to_podspec
6ecf38f Add tvOS to the podspec.
c722c3d Merge pull request #3216 from traversaro/patch-1
9094bf0 Export symbols used in inline functions
9ba7d1c C++: Do not forward-declare dependencies in generated .h files
96095f3 Merge pull request #3176 from acozzette/fix-3114
c202b06 Merge pull request #3196 from matt-kwong/kokoro
0871e6a Add continuous testing config files for Kokoro
d4d41af Merge pull request #3191 from matt-kwong/kokoro
6156af1 Add MacOS and Linux tests to Kokoro
d555775 Merge pull request #3189 from thomasvl/objc_proto3_unknown_fields
2aeb4ab Merge pull request #3160 from meteorcloudy/winbuild
ddbe360 Merge pull request #3159 from yeswalrus/new-generate
1d0988b ObjC: Preserve unknown fields in proto3 syntax files.
516a81a Merge pull request #3190 from thomasvl/objc_IllegalZeroFieldNum
ecc0f54 Properly error on a tag with field number zero.
656dedb Merge pull request #3157 from yeswalrus/fix-version-check
7ccb251 Remove unused output_file variable from js_embed
6f32580 Add new file option php_namespace. (#3162)
df3f8cf fix check_and_save_build_option not correctly exporting build options
0336770 add protobuf_generate function, allows use of target_sources where available
e9c15d6 Ensure that for Java, imports of .proto files with empty packages works
fbaad36 Merge pull request #3169 from dmaclach/master
63a9728 Merge pull request #3170 from thomasvl/int64_map_issue
46f36d7 Fix some cases of reading of 64bit map values.
ea43e0c Optimize GPBDictionary.m codegen to reduce size of overall library by 46K per architecture.
0b059a3 Refactor cc options in BUILD file for Windows
d8c5865 Fix policy warning CMP0054
a183a0d Fix the check_and_save_build_option macro never evaluating to true
faa5398 fix check_and_save_build_option not correctly exporting build options
ae85cb8 Fix find module not working when no version number was given
d6470ab not to use std::random_device for map.Seed(). (#3133)
e222997 Merge pull request #3149 from KarrokDC/master
1e86ef4 Oneof field should be serialized even it's equal to default. (#3153)
282fb9e Add ARRAY for reserved name (#3150)
4d5daf4 Adds fluent setters for PHP (#3130)
4eb02fe Add headers as part of cmake project tested only on windows with visual studio 2015 as generator
4674cc7 Merge pull request #3113 from phst/master
95749d5 update csharp README and fix .NET 3.5 build error
aea4374 Issue 3112: Object class with fully qualified name
0b07d7e Add IncludeSource in csproj as per review comments
f26e8c2 Convert C# projects to MSBuild (csproj) format
40da1ed Removing undefined behavior and compiler warnings (#1315)
ba987a7 Merge pull request #3126 from mbrukman/fix-readme-formatting
c5125f3 Merge pull request #3117 from KarrokDC/master
d2c1865 Merge pull request #3103 from sergiocampama/perf
2465ae7 Adds serial and parallel parsing tests to check if parallel parsing is faster than serial parsing, which it should
6775570 Fix Markdown formatting in README.
979107e Improve fix for https://github.com/google/protobuf/issues/295
3b22761 show help if protoc is called without any arguments, pre-empts -h and --help to show a useful message instead of just 'Missing input file.'
bf04c83 Merge pull request #3085 from scpeters/issue_3059
8546620 Merge pull request #3104 from thomasvl/ext_registry_copy
49e4ba6 Fix ExtensionRegistry copying and add tests.
b28617b Merge pull request #2815 from devwout/ruby_json_emit_defaults
78cb804 change test for nanosecond accurate timestamps
ad203bc fix floating point accuracy problem in Timestamp#to_f
49a56da Update jenkins Java deps.
129a6e2 Revert guava depedency to version 19.
969e0be regenerate plugin and profile message code
26f0011 Use bool deterministic to suppress warning
474cca5 Add LICENSE in package.xml (#3083)
13f532e Merge pull request #3074 from xfxyjwf/3.3.x
82e50ba Workaround the docker bug when compiling artifacts
de6ae7d Fix upb load descriptor when no messages defined in prorto. (#3080)
2231931 Fix c extension for php7.1. (#3077)
757cc9f Update C++ generated code.
58538ea Update version number to 3.3.1
c2154e1 Merge pull request #3073 from xfxyjwf/3.3.x
d22493b Merge pull request #3064 from randomguy3/offset-type
9b82fce Workaround gcc < 4.5.0 bug
455b61c Merge pull request #3062 from Oppen/master
e062f70 Fix compilation
e82d81a Fix offset type to match the tables it is used in
25abd7b Add compatibility test for php. (#3041)
3c369dc Merge pull request #3057 from xfxyjwf/3.3.x
cd0efc0 Workaround gcc < 4.5.0 bug
99cf2ef Merge pull request #3056 from acozzette/cherry-pick-pr-2873
7378ec2 Add missing LIBRPOTOC_EXPORT.
3a5a072 Skip C# test in C++ only distribution.
8859c07 Add missing files to build files.
4833960 Merge pull request #3043 from acozzette/javascript
22c8772 Fix #1562 by using goog.crypt.byteArrayToString instead of String.fromCharCode.apply
dd0a233 Merge pull request #3055 from chrisn-arm/3.3.x
c3093d3 Fix issue 3046: compilation on alpine 3.5
f00e06c Removed mention of Buffer in byteSourceToUint8Array
a64497c Merge pull request #2873 from myitcv/fix_1562
bcb3506 Fix #1562 by using goog.crypt.byteArrayToString instead of String.fromCharCode.apply
2f4489a Merge pull request #3024 from acozzette/merge-3.3-to-master
286f059 added "objectivec" build target (#3033)
9053033 Merge remote-tracking branch 'remotes/google/3.3.x' into merge-3.3-to-master
067b1ee Merge pull request #3023 from acozzette/min
07c284f Fully qualify min as std::min in wire_format_lite.cc
a6189ac Add prefix to enum value with reserved name. (#3020)
cbd08cb Merge pull request #3018 from acozzette/using-namespace-std
54d1701 Merge pull request #3015 from buchgr/unused-consts
7c76ac1 Remove "using namespace std" from stubs/common.h
3c0855e Add a test case for nested enum, which was missed previously. (#3010)
b1c75bc Remove unused constants.
4920e27 Merge pull request #3008 from postmasters/patch-1
fba2acd Add nested enum descriptor in php rumtime. (#3009)
e64b618 Update php version number to 3.3.0 (#3001)
4777574 Add a link to dart-lang/protobuf
6fff091 Throw exception when parsing invalid data. (#3000)
f418b9e Merge pull request #2996 from xfxyjwf/3.3.x
4523c9c Allow proto files to import descriptor.proto (#2995)
478119f Fix python3 issue.
14afc3f Merge pull request #2992 from xiaogaozi/patch-1
f85eecb Add gogoprotobuf to third-party add-ons list
4c57e84 Prepend "PB" to generated classes whose name are reserved words. (#2990)
b97cd57 Add test for nested enum for php (#2989)
7be0882 Enum defined without package have incorrect class name. (#2988)
190b527 Make PHP c extension work with PHP7 (#2951)
357afc3 Merge pull request #2508 from yliu120/pass_default_env_to_protoc
0a93f67 Merge pull request #2987 from konsumer/patch-1
594f810 Merge pull request #2982 from mda000/issue2972
3055a02 Add node-protoc-plugin to "Other Utilities"
a3873ca Merge pull request #2985 from thomasvl/class_check_tweaks
f5a01d1 Tighten up class usage/checks.
2240a78 Simplify the Element dtor invocation when freeing elements in InternalDeallocate to avoid confusing the compiler when there's a class named Element already defined in the global namespace.
8aa927f Merge pull request #2950 from anuraaga/dev_rag
4323482 Merge pull request #2967 from xfxyjwf/3.3.x
5777259 Cherry-pick cl/152450543
cad0258 Cherry-pick cl/151775298
fc3ea97 Merge pull request #2955 from xfxyjwf/3.3.x
899460c cherrypick descriptor_pool.FindFileContainingSymbol by extensions (#2962)
bfeeb98 Add include for INT_MAX
e91caa1 Merge pull request #2949 from xfxyjwf/3.3.x
bf483df Allow unknown values for Map put*Value methods just like every other enum mutation method.
ee9c7f1 Cleanup reflection objects for map entry.
efec757 Merge pull request #2937 from anuraaga/dev_rag2
18c13c9 Merge pull request #2942 from xfxyjwf/3.3.x
21b0b3c Update generated code.
80f0c0a Update version number and changelog for 3.3.0
69bfde2 Merge pull request #2922 from anandolee/master
09328db Fix test for unexpected type url when parsing Any. Currently, the test fails since TestAllTypes doesn't have field '@type', which is the same test as testUnknownFields.
139fd0a Merge pull request #2933 from mharrend/patch-1
37c7b76 Merge pull request #2930 from anuraaga/dev_rag
662f978 Fix duplicate fields test. The repeated version is passing because null values in a repeated field are rejected and not testing what it wanted to. Also adds a oneof version that verifies the case of oneof fields of different names (currently only same name check seems to be tested).
cc3fa2e Merge pull request #2676 from acozzette/js-compatibility-tests
10ea251 Added compatibility tests for version 3.0.0
7e5f980 Split test protos into two groups
dd04ffb Adding default shell env
58373fa Fix error message for int64 parse error.
11c902e Add IntelliJ project to gitignore for java project.
bd74319 Update Java conformance failure list.
32ad5a3 Use "git reset --hard" to actually reset the code.
b7c813f Update jenkins Java dependencies.
c2b3b3e Update Java version number and dependency.
624d44f Update objective-c conformance failure list.
d582778 Fix C++ distcheck.
fe97d79 Fix MSVC DLL build.
fab8812 Update python conformance failure list.
c52e54f Update jenkins Java maven dependencies.
057a285 Update C# conformance failure list.
e47c068 Update python conformance failure list.
84f6954 Fix Java build.
c348d46 Use PyUnicode_AsEncodedString() instead of PyUnicode_AsEncodedObject()
acde165 Update BUILD file for C# tests.
32d7830 Fix C++ build for down-integration.
d36c0c5 Down-integrate from google3.
4a0dd03 Removes ignored const from return type (#2915)
258406b Merge pull request #2919 from thomasvl/drop_dispatch
130c166 Remove the use of dispatch_once that is heap backed.
ba3fa41 Merge pull request #2918 from thomasvl/xcode_8_3
558ba98 Add support for Xcode 8.3 to the build helper.
04c77c4 Merge pull request #2913 from thomasvl/conformance_ignores
d43eaf2 Fix gcc warning when using map (#2213)
5859932 Merge pull request #2914 from acozzette/nacl
f316375 Added a workaround to allow building for NaCl
8adf57e Add some new ignores for things generated in conformance.
b3f3e12 Merge pull request #2912 from thomasvl/objc_recursion_limit
ddb4388 Raise the recursion limit to 100 to match other languages.
d9e0119 Merge pull request #2858 from haberman/gopackage
c565e25 Merge pull request #1662 from haberman/jsconformance
7610f10 Merge pull request #2884 from anandolee/master
689e4bf Add FormatEnumAsInt support for Json Format. And scale JsonFormatter.Settings to multiple options.
373809e Merge pull request #2897 from cgrushko/patch-5
6f21e29 Compile the Java proto runtime with Java 6
1387a67 Update commit number in Docker to update composer dependency (#2869)
ffa932b Merge pull request #2861 from byronyi/#710
312e2db Update BUILD
db3ef48 Merge pull request #2860 from prehistoric-penguin/master
20181f6 Merge pull request #2854 from hesmar/attributesFix
4d273f2 Merge pull request #2870 from acozzette/memcpy-memmove
15b60bc Merge pull request #2867 from mojoBrendan/master
ea5ef14 Ruby: only link against specific version of memcpy if we're using glibc
c12cc34 Merge pull request #2837 from anandolee/master
6b27c1f Add file option php_class_prefix (#2849)
c0871aa Merge pull request #2848 from xfxyjwf/freebsd
e8e6aa2 Update delimited_message_util_test.cc
89eb4e5 Add option to preserve original proto field names
aec0711 Ruby tests compare parsed JSON instead of raw JSON
1eee320 Add use_snake_case_for_field_names option to JsonPrintOptions
c415a14 fix several issues
44dc555 Merge pull request #2866 from xfxyjwf/nano
ddc0096 Add a notice for nano.
1b0db1c Removed obsolete comments and added docs.
0df2028 Properly regenerated descriptor.proto.
89c3c45 Merge pull request #2859 from haberman/junit-dep-scope
2957703 Merge pull request #2847 from haberman/ruby-toh
0fad0e1 Merge pull request #2794 from acozzette/jspb-extensions
acaa940 add delimited_message_util.cc to libprotobuf.cmake
7008a88 add LIBPROTOBUF_EXPORT to make msvc happy
cb3e84b migrate delimited messages functions to util package
33cc25f Remove duplicated copyright statement
496cd48 Changed scope of Java deps to "test".
e62e30c Changed go_package for plugin.proto.
4842363 Merge pull request #2023 from odeke-em/fix-print-help-to-stdout
e77a09e Incremented Ruby version number to 3.2.0.1
8c40b51 Ruby: update Gemspec.
97cbc42 Fix libprotoc.cmake to generate well_known_types_embed.cc
f23869c Bug fix: When encoding, negative int32 values should be padded to int64 (#2660)
014a550 Ruby: build packages for Ruby 2.4.
c57c77b Merge pull request #2829 from afrantzis/hide-unnecessary-library-symbols
324a299 Made formatting more consistent.
ed0ef54 Merge pull request #2846 from acozzette/bytestream-comment
d18df81 Merge pull request #2855 from thomasvl/copy_note
5e4f14f Document deep copy in the header
b4b855c fix attributes warning
416f909 Fix freebsd build.
9c6b8cb Ruby: fixed Message#to_h for map fields.
95b4427 Build system fixes for JS conformance tests.
43f2db7 Merge pull request #2843 from haberman/check
746ca59 Updated an outdated comment in bytestream.h
874e382 Replace CHECK() with GOOGLE_CHECK().
8df69f0 Conformance test for JS now work, though 15 tests fail.
f0a5c10 Merge pull request #2836 from xfxyjwf/i894
ddfc86b Merge pull request #2835 from pherl/javaep
13d165d Hide unnecessary exported library symbols
d59592a DefaultValueObjectWriter should populate oneof message field
c94555f Double-quote file paths in extract_includes.bat.in
f4f31e7 Suppress the last unchecked warning.
a69bc9d Merge pull request #2822 from anandolee/master
f54fb9d Merge pull request #2832 from pherl/javaep
e11cd3e Merge pull request #2818 from xfxyjwf/i1470
6044b24 Make //:protobuf_python have correct __init__.py.
92064a4 Merge pull request #2824 from xfxyjwf/i1415
cd6eb91 Merge pull request #2826 from xfxyjwf/i1374
81f4fe5 Merge pull request #2827 from xfxyjwf/i1251
81fe52f Fix java code according to error prone.
616e68e Repeated/Map field setter should accept a regular PHP array (#2817)
ae220cd Add auto detect for generated code of WKT protos, addressbook.proto and conformance.proto
03c8c8b Update comments for setSizeLimit.
a1bb147 Merge pull request #2825 from pherl/javawarning
1ece7c0 Add missing thread dependency in cmake.
009e491 Fix GeneratedMessageV3 warnings.
da00355 Merge pull request #2809 from xfxyjwf/i2464
61e87f3 Use per-type table to lookup JSON name.
7c75344 Fix lint warnings in the javalite branch.
cad6a51 Merge pull request #2819 from haberman/pythonexcept
3e6245e update_failure_list.py: fixed Python "raise" statement.
075475f Don't expose gson exceptions in JsonFormat.
bbfb9d5 Merge pull request #2804 from acozzette/ruby-memcpy
8e465dc Merge pull request #2810 from xfxyjwf/i1994
af2d5f5 Merge pull request #2775 from xfxyjwf/fixmajor
9afacb4 Merge pull request #2814 from pherl/javadeprecate
baceff7 Add annotations for deprecated messages in Java
008dc92 Ruby version optionally emits default values in JSON encoding.
9fa4031 Ruby: wrap calls to memcpy so that gem is compatible with pre-2.14 glibc
c311543 Avoid redundant type casts for oneof bytes fields.
4ae8656 Make JsonFormat locale independent.
fa17880 Merge pull request #2602 from GreatFruitOmsk/issue-2428
920af75 Fix Bad Link for Common Lisp
dd8d5f5 Rename encode/decode to serializeToString/mergeFromString (#2795)
769b693 compiler/cli: PrintHelpText prints to stdout instead of stderr
2b7430d Merge pull request #2793 from keveman/master
f6d8c83 Merge pull request #2613 from aausch/fix_memory_leak
21b58b5 Removed a stray return statement, causing compilation error.
651ba62 JS: ensure that extension values are serialized even if they're falsy
06f9f60 Detect if Descriptor.cs changes for csharp
f873d32 Added JavaScript conformance tests.  All tests pass!
27b1f2b WIP.
0c0a887 Merge pull request #2751 from keveman/master
008ff03 Merge pull request #2784 from acozzette/log-2-floor-int
6837b2d Added comment explaining the protobuf_headers target.
af13bff Detect if Descriptor.cs changes for csharp
8610d0a Merge pull request #2755 from xfxyjwf/rubycomp
352526c Merge pull request #2785 from thomasvl/threading_race
2d1c5e2 Handing threading race resolving methods.
938206d Return uint32 from Log2FloorNonZero64
a7e3b0a Merge pull request #2774 from acozzette/closure-builder
8b182cc Disable static analyzer for message semaphore creation (#2748)
6011d7c Fix gcc 4.1 build (#1035) (#1913)
25ecd55 Change hint type to `const void*` (#2568)
bcbaabe Add mergeFrom method on Message (#2766)
671e075 Use closurebuilder.py in favor of calcdeps.py for compiling JavaScript
7339fc0 Merge pull request #2674 from acozzette/js-test-cleanup
b7f25d4 Undef major/minor if they are defined as macro.
aff9d9d Removed log statement from writer_test.js
5274d6e Merge pull request #2770 from xfxyjwf/fixcmake
83b0cc9 Merge pull request #2772 from sschuberth/master
606cb7e There might be duplicated enum values when allow_alias is true. Add PreferredAlias into OriginalNameAttribute to remove the duplication (#2727)
902af08 Prefer the term "3-Clause BSD License" over "New BSD License"
6395a1c Fix links to the New BSD License in meta-data
ffde972 Remove the use of C++11 features.
9118ad6 Add Ruby compatibilty test against 3.0.0.
d41c47f Merge pull request #2733 from wmamrak/patch-1
8d61f9c Merge pull request #2729 from MarcelRaad/fix_inline_msvc12
b4b0e30 Merge pull request #2355 from xfxyjwf/fixjson
8387b88 Merge pull request #2732 from AsturaPhoenix/master
66c64e7 Merge pull request #2747 from liutikas/master
8c8b8e6 Merge pull request #2734 from msabramo/patch-1
72b82e6 Merge pull request #2630 from blodan/master
963473b Merge pull request #2753 from thomasvl/recursive_drop
d071766 Add GPBMessageDropUnknownFieldsRecursively() and tests.
2d430f8 Added a header only cc_library target for the protobuf library.
17174b5 Updating README
f83d129 Upgrading test-related libraries
c9b2c8f Fixes for .NET 3.5 compatibility
a434bfc Fix compiler warnings about unused variables in generated_message_reflection.h
1a8cbfd Merge pull request #2736 from na-ka-na/master3
172e0a6 Add an option to always print enums as ints in Json API
86208c5 README.md: Make docs URL a link
37bd5d5 Disable MSVC warning C4309
01a05a5 const FieldDescriptorCompare
8f9c0a4 Fix unresolved symbols with MSVC12 and /Zc:inline
a9ab38c Merge pull request #2722 from ckennelly/unified
8af35f2 Keep loop bounds in a local variable for string fields.
a6c30d9 Keep loop bounds in a local variable.
9db5b11 Work with truncated tag numbers.
0026dff Expose rvalue setters for repeated string fields.
38b1440 Merge pull request #2663 from ckennelly/varint-size
15360e5 Merge pull request #2689 from ckennelly/aliasing-fixed32-fixed64
38c238e Improve support for plugin parameters.
d2dfe46 Merge pull request #2609 from yixiang/patch-1
3f6f73b Merge pull request #2701 from anandolee/master
ed423c2 Merge pull request #2451 from podsvirov/json-primitive-map
aa78aeb Merge pull request #2704 from liutikas/master
74eb9a0 Add clear method to PHP message (#2700)
46c022a JsonUtilTest: Add ParsePrimitiveMapIn subtest
9079079 Fix compiler warnings about unused variables in wire_format.h
ef927cc Switch to gcc atomic intrinsics for macOS and delete the file that uses (#2699)
7288689 Add csharp compatibility tests against v3.0.0 and run on Travis.
1d2736f Merge pull request #2656 from pcj/patch-1
9f09d18 Add proto and test files for csharp compatibility tests against v3.0.0. All the files are copied from 3.0.0 (JosnFormaterTest was deleted)
c6e0d0e Merge pull request #2647 from anandolee/master
42e1e2a Fix python compatibility test when a new generated code imports an old version(2.6.1 or older) generated code.
e844510 Merge pull request #2692 from cgrushko/patch-3
65a4d20 Update load() statement to latest style
a60cc08 Merge pull request #2691 from cgrushko/patch-3
cba04b1 Implement json encoding decoding for php. (#2682)
6fffd4a Bazel can build protobuf when it's not in the root
56da828 Avoid aliasing CodedInputStream::buffer_ when parsing little endian integers.
c002743 Add fixed version to phpunit used in travis (#2673)
36f51f9 Merge pull request #2681 from sergiocampama/spaces
e7f5c9d Removes trailing whitespaces
5a3405c Update upb for php. (#2662)
bd29f86 Fix CopyTo argument validation
36f68e0 Inline branch-less VarintSize32/VarintSize64 implementations.
3975664 Add conformance test for php (#2655)
7b54b34 Add bazel protobuf resources
7f3e237 Merge 3.2.x branch into master (#2648)
9d3288e Merge pull request #2226 from kchodorow/master
2c36cc3 cache generated classes, optimization and quick workaround to memory leak
afc59ab C#: Implement IReadOnlyList<T> in RepeatedField<T>
87e4976 Merge pull request #2639 from anandolee/master
1ee09c8 python: do not include internal 'strutil.h' header
a83ac86 fix compile error on centos in metadata.h for constructors. (#2599)
a323f1e Oneof accessor should return the field name that is actually set. (#2631)
ccb76ff Add Oneof custom options test
5af0b54 Merge pull request #2619 from anandolee/master
1f09786 Merge pull request #2633 from anandolee/jieluo_branch1
ea51149 Add python compatibility tests against v2.5.0 amd run on Travis.
c15217f Allow OneofOptions to be extended in proto3.
c2a5669 Merge pull request #2626 from sergiocampama/8_3
32fa55e FreeBSD compatibility
4e7ecde Update genfiles paths to work with a different execroot arrangement
3d7b42d Adds nullability modifiers to resolve Xcode 8.3 warnings
140e28d Add python compatibility tests against v2.5.0: copy tests and proto files from v2.5.0
0aa5af3 Merge pull request #2614 from acozzette/gzip-output-stream-options
a101fa5 Set LIBPROTOBUF_EXPORT on GzipOutputStream::Options
e41b667 Undef TYPE_BOOL to avoid conflict with iOS.
047575f Support custom options in C#
eed9951 Merge pull request #2591 from thomasvl/objc_timestamps_take2
24908e1 Update AbstractMessage.java
d0bc096 Timestamp helper fix, Duration helper cleanup.
c9cd6ac Merge pull request #2587 from google/revert-2586-objc_timestamp
1651342 Revert "Fix Timestamps with dates before the Unix epoch that contain fractional seconds."
cf477d4 Merge pull request #2586 from thomasvl/objc_timestamp
adcccd0 Fix Timestamps with dates before the Unix epoch that contain fractional seconds.
feb78fb Merge pull request #2584 from cgrushko/patch-2
e4baf3f Add a proto_lang_toolchain for Java
e53dd99 Merge pull request #2529 from wackoisgod/master
fac90c6 Update AbstractMessage.java
75ac397 Fixing code formatting issues
effcb13 Merge branch 'master' of https://github.com/wackoisgod/protobuf
228d242 Merge pull request #2567 from acozzette/distcheck-fix
fb71df9 Add ByteString.FromStream and ByteString.FromStreamAsync in C#
e76d91a Add global.json file to pick dotnet core SDK version.
0bdf4a6 Fixed "make distcheck" for the Autotools build
2bddffc PHP fix int64 decoding (#2516)
2c16f69 Fix generation of extending nested messages in JavaScript (#2439)
ffa71f8 A few more cases for binary conformance tests. (#2500)
1041710 Merge pull request #2565 from acozzette/cross-compilation
24f0d56 Merge pull request #2563 from thomasvl/autocreator_tweaks
988ffe0 Minor fix for autocreated object repeated fields and maps.
2deb139 Merge pull request #2544 from tiziano88/master
17a8a76 Merge pull request #2536 from jbrianceau/fix-js-embed-include-style
c55175c Merge pull request #2564 from acozzette/arena-nc
a592052 Removed arena_nc.cc and arena_nc_test.py
b40d318 Fixed cross compilations with the Autotools build
f3e86fd handle sanity check for repeating enums correctly
4cb113a Fixed issue with autoloading - Invalid paths (#2538)
30250cd Add link to Elm proto plugin
5f65ee6 Merge pull request #2542 from jbrianceau/fix-embed-cc-warning
4455cdf Fix include in auto-generated well_known_types_embed.cc
05b019a Fix warning in compiler/js/embed.cc
f52e188 Merge pull request #2523 from jbrianceau/init-index-in-metadata
137dc02 Merge pull request #2525 from camillol/lite
abe1725 simpler, cheaper callback to LazyStringOutputStream
4e229c8 add MethodResultCallback_0_0
15a15e3 Init index_in_metadata_ without condition
6c021b3 Added the support for class level deprecation which will in turn also deprecate any fields that are currently using that type
d948b66 Merge pull request #2521 from acozzette/fix-bazel
5731ca5 Added well_known_types_embed.cc to CLEANFILES so that it gets cleaned up
ee0a243 Updated Makefile.am to fix out-of-tree builds
d1e7bd9 Added Bazel genrule for generating well_known_types_embed.cc
cdc2766 Merge pull request #2506 from ckennelly/rvalue-setters
bb2c6b2 Merge pull request #2505 from ckennelly/master
c64830b unwrap descriptor class before comparison of RepeatedField types
fb15862 Merge pull request #2517 from acozzette/js-embed
98d89d4 Fixed "make check" for cmake build
1b3a0c1 Auto-generate well_known_types_embed.cc
183d31c Add rvalue setters for non-arena strings on C++11.
f39cf88 Merge pull request #2227 from KindDragon/3.1.x
b18bc9b Give C# ByteString a sensible GetHashCode implementation.
ef61a9d add a key to ctx.action dict to prevent protoc losing the default env
ba63fa7 Remove spurious NULL checks in ArenaStringPtr::CreateInstance.
a95e38c Merge pull request #2499 from ckennelly/master
a902e25 Define LANG_CXX11 for port.h and use this to guard C++11 features.
83d681e Merge pull request #2495 from acozzette/android-hash
d1c1dad Merge pull request #2498 from sergiocampama/enum
c68fc58 Fixes and expands comments on how to use GPB_ENUM_FWD_DECLARE
2ff42dc Added conformance testing for binary primitive types. (#2491)
f983302 Merge pull request #2496 from xyzzyz/fix-overflow
837fd6b Merge pull request #2493 from jbrianceau/add-missing-climits-include
f77b7d9 Merge pull request #2484 from ngg/uwp_build
4c5d3ed Fix integer overflow in FastUInt32ToBufferLeft
5587562 Removed Android-specific code from stubs/hash.h
7b220f3 Add missing include in embed.cc
9d709f4 Merge pull request #2487 from jtattermusch/csharp_leading_whitespace
83c728a Add missing includes
eb455ce Merge pull request #2471 from jbrianceau/fix-include-style
6b86a89 Merge pull request #2490 from xfxyjwf/icon2
4c252dd Add a badge for bazel build status.
ec021f5 Add support for Windows ARM builds
29fb87e Merge pull request #2454 from pongad/go_package
fda9049 remove leading whitespace in C# xml comments
277a8b6 generate_changelog.py: flush output so piping works correctly.
8494846 Merge pull request #2476 from acozzette/generated-message-reflection-fix
dc11940 Merge pull request #2475 from sergiocampama/rvm2
e19f3b5 Use uint32 in GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET macro
1ac8944 Reenable cocoapods objc test and remove unnecessary workaround for rvm
e43f73e Merge pull request #2473 from thomasvl/update_xcodes
70e21d7 Mark objectivec_cocoapods_integration as failing
bc9d077 Skip benchmark test if cmake isn't installed.
2754586 Xcode 8.1 support
e3da722 Fix #include in cc files
243ebec Merge pull request #2468 from sergei-ivanov/patch-1
d8f54c4 Disable jruby test. (#2469)
09dc933 Update third_party.md
e3e38b8 Update commit id in Dockerfile to trigger update. (#2467)
4474c04 Merge pull request #2462 from jbrianceau/fix-comp-builds-part2
6b4eee4 Merge pull request #2461 from jbrianceau/add-missing-include-in-embed-cc
34a1b6e Merge pull request #2394 from cwelton/formatting
46ae90d Make php generated code conform to PSR-4. (#2435)
631f461 Merge pull request #2466 from thomasvl/deprecation_followup
4c84b47 Merge pull request #2460 from sergiocampama/c11
dad775b Improve ObjC deprecated annotation support.
e219be7 Regenerate descriptor proto
b1295ee C++: export _xxx_default_instance_ symbols
867dbac Add missing include in embed.cc
c836ad4 Merge pull request #2459 from acozzette/android-logging
1d91c25 Include -std=c++11 when compiling protobuf if available.
2f29f0a Send all protobuf logging to logcat by default on Android
057389c Ruby: removed redundant RepeatedField#slice. (#2449)
850d573 Merge pull request #2407 from jbrianceau/fix-comp-builds
788d14a Export symbols used in inline functions
bb77cbf update descriptor.proto's go_package
607b921 Merge pull request #2437 from xfxyjwf/plugin
1a56251 oneOf fix for JsonFormat includingDefaultValueFields
ced8f73 Add version number to plugin protocol.
0509072 Merge pull request #2445 from ramrunner/master
c664b66 Merge pull request #2442 from pherl/fix-bazel
4cc160e when on OpenBSD we include the correct headers for endianess and check the apropriate defines
f92b455 Add missing files.
f1ce60e Factored Conformance and Benchmark test messages into shared test schema. (#1971)
4280c27 Merge pull request #2436 from cgrushko/patch-1
45d92ae Add a proto_lang_toolchain() for cc_proto_library
6b60ddd Merge pull request #2431 from saintstack/2228v2
7550bcd Change CodedInputStream#DEFAULT_SIZE_LIMIT from 64MB to Integer.MAX_SIZE (0x7FFFFFF) #2228
f8ca3ac Generate phpdoc in php generated files. (#2406)
34dc96b LIBPROTOC_EXPORT added to others functions in csharp_names.h and objectivec_helpers.h
b790da5 Missed LIBPROTOC_EXPORT for GRPC added
851cb81 Merge pull request #2429 from thomasvl/issue1833_swift_prefix
f813bd9 Add a swift_prefix file option.
39f9b43 Merge pull request #2403 from google/down-integrate-with-msvc-fix
65479cb Fixed Ruby tests for JRuby 1.7
259dd7e Updated descriptor_pool.py to be compatible with Python 3
db35fe7 Add a "u" suffix to tag numbers in generated code
a7f300d Fixed descriptor_pool_test.py for Python 2.6
c950471 Merge pull request #2404 from wiktortomczak/master
0fa31b2 Support grpc plugin in py_proto_library
a41090e Updated failure_list_java.txt for Java conformance test
72002d8 Merge pull request #2400 from acozzette/jspb-test-fixes
fda876a Added back in binary serialization round-trip in message_test.js
b763246 Merge pull request #2398 from jbrianceau/no-static-init-define-fix
04bd614 Merge pull request #2392 from xfxyjwf/fixdown
40f3586 Fixed remaining JSPB test failures
315350b Updated message_test.js so that it does not depend on fromObject
b4dd686 Updated enum names in test.proto to avoid conflicting with testbinary.proto
a5c30ce C++: Fix use with GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
7807932 Restore jenkins files.
599613e Update EXTRA_DIST lists.
1f077a0 Update conformance failure lists.
530ae30 Add back missing LIBPROTOBUF_EXPORT.
1673389 Updated libprotoc.cmake
5d63097 Merge branch 'master' into down-integrate-with-msvc-fix
5a76e63 Integrated internal changes from Google
cd315dc Merge pull request #2383 from snapsam/patch-1
44edefa Merge pull request #2382 from zhsyourai/master
d571d39 Update README.md
14c147e Add LL to large constant
cb54caf Add tests to demonstrate json parsing for null Timestamp and Duration types
99564c3 Rename Empty to GPBEmpty in php generated file.
fc27ead Merge pull request #2362 from wujingchao/patch-1
a3dfbe6 Merge pull request #2378 from ianfhunter/patch-1
01d321c Merge pull request #2367 from jbrianceau/add-missing-include-in-message-lite-cc
130bb07 typo
83d6411 Fix jenkins tests.
bf37971 Merge pull request #2323 from marcinwyszynski/master
c6f3d70 Merge pull request #1907 from evokly/js-utf8-fix
bd850a2 JS: Well, this is the right place for surrogates.
292c2c9 JS: Re-added comment, moved surrogates code to the right place
6e93fa4 Merge pull request #2366 from jbrianceau/reland-fix-include-js-generator
a95d052 Merge pull request #2368 from jbrianceau/fix-json-style-in-project-json
3c0e0ce Fix csharp/src/Google.Protobuf.Test/project.json
aac9ed8 Add missing include in message_lite.cc
3316062 Fix #include in js_generator.cc
74a636a Move variable declarations before actual code
0c0f7e2 Merge pull request #2364 from haberman/jslicense
5d9dbe3 Fixed JavaScript license declaration.
abeff7b Class is final but declares protected field
a30e5af Merge pull request #2358 from ckennelly/master
e02cb2b Resolve old TODO for StringTypeHandler.
8a4b2c5 Merge pull request #2353 from guptasu/master
df56736 Merge pull request #2357 from D3Hunter/master
ed08341 #2356 : fix ExceptionInInitializerError on IBM J9
bd158fc Speed up JSON parsing.
df83907 Fix php c extension on 32-bit machines. (#2348)
9f75c5a Merge pull request #2337 from sergiocampama/deprecation
fce8b6b Made helper code also consider package name 'proto2' when dealing with MessageOptions.
e75cf40 Fixing references to the removed atomicops_internals_pnacl.h file.
ce5160b Merge pull request #2332 from Kwizatz/master
d584321 Merge pull request #2327 from ctubbsii/fix-maven-compiler-plugin
1f2dbc8 Implement RepeatedFieldIter for c extension. (#2333)
ecc460a Renamed the pnacl version of atomicops.h into C11 atomic, and flagged the mac version to that if atomic is enabled
975d577 Added explicit cast to avoid size warning on Win64.
0d7199e Merge pull request #2329 from acozzette/unused-parameter
ca800ea Merge pull request #2330 from manupsunny/master
089aaa9 Fix message for InvalidProtocolBufferException
8785004 Fix unused parameter warnings in arena_free
eb7f3a3 Use latest maven-compiler-plugin (2.6.0)
7bd11fc Merge pull request #2301 from jbrianceau/arm-atomic-kuser-helpers-fix-v2
4c310d7 Update conformance test failure list
50a37e0 Change JSON field name formatting
cb81314 Fix copy pasta in test
3bdaaa5 More Ruby-eqsue interface
93a4fa2 Merge pull request #2302 from jbrianceau/generic-gcc-atomics-strong-cmpxchg
750b9e2 Merge pull request #2318 from mavrukin/patch-1
4d813de Fix compiler warnings when running :protobuf_test
8fcd24b Merge pull request #2307 from sinzianag/swift_protobuf
ea928a1 Merge pull request #2309 from thomasvl/note_about_coding_support
98c0185 Add note about extension use and Coding support.
9819b72 Adding Apple's Swift Protobuf
a5a2c1d generic atomicops: Use strong compare_exchange
4587a3f [arm/gcc] Don't rely on KUSER_HELPERS feature for atomics
d58b92a Adds pushLimit: and popLimit: into GPBCodedInputStream (#2297)
795976e Trigger update of docker for new changes in #2282. (#2288)
e9d9e56 Merge pull request #2290 from ramrunner/OpenBSDsupport
bfc1299 define no_threadlocal on OpenBSD
734930f Merge pull request #2284 from pherl/plugin_opt
2e314a6 Add comments about converting directives into PluginName
59cd5d0 Support extra parameters for plugins.
51c5ff8 Fix pure php implementation for 32-bit machine. (#2282)
58580da Merge pull request #2274 from nmittler/gae
c0f95c6 Hacking ByteBufferWriter to work with GAE
9c6940f Merge pull request #2264 from rshin/master
7c913d8 Use -DPROTOBUF_PYTHON_ALLOW_OVERSIZE_PROTOS
df5841f Place Python extensions correctly in Bazel build.
008b5a2 Merge pull request #2254 from JasonLunn/patch-1
9ec7a47 Use git clean before installing via bundler
993d604 Merge pull request #1959 from abergmeier-dsfishlabs/feature/cpp
ad88f90 Merge pull request #2251 from TeBoring/master
686a19c Merge 3.1.x into master.
e28286f Add 32-bit machine test on jenkins. (#2245)
afaa827 Merge pull request #2246 from fweikert/patch-1
c2b3e70 Declare all inputs of protoc action
60d95f3 Fix the bug that message without namespace is not found in the descriptor pool. (#2240)
0321baf Merge pull request #2203 from mrry/msvc_fix
7332ffb JS: Replaced fromCodePoint/codePointAt with fromCharCode/charCodeAt because of functions limited availability, fixed typo in tests.
fd046f6 Merge pull request #2234 from TeBoring/master
daba665 Fix python_cpp test on Mac. Link staticly when building extension, so that the extension doesn't require installing protobuf library. (#2232)
5be6325 Add csharp/build_tools.sh for dist check.
63448e6 Fix compile error for php on Mac.
4f3d20a Fix segmentation fault when ZTS is defined.
1e5d4ba PHP: fix ZTS tsrm_ls errors (#2189)
c96dd66 Add test for php zts build.
447dee1 Prepare jenkins for testing php zts build.
7047761 Do strict enum name checking only for proto3
34cdaf4 Add travis test on Mac for php.
c8bd36e Test php5.5_c test on jenkins
c0719f0 Trigger automated tests for php.
91bbff2 Set up environment for php automated tests.
fd332d1 Add php test script for automated tests.
89db7ce Add script to build Google.Protobuf.Tools for csharp.
f2eeaf7 Added alias getFieldProto3 as used by older generated code.
4a4a162 Fixed references to foreign nested messages with CommonJS-style imports
0bf5482 Fixing inconsistent php version number.
ae9455c Fix MSVC stack overflow issue.
e0a6e52 Add php files for make dist.
17cc42a Update change log for 3.1.0 (#2173)
8db25a2 Force a rebuild of Jenkins docker image.
a41349d php: support 5.5.9 for pecl extension (#2174)
39685f6 Fix VS test failures.
2937c67 Use "appveyor DownloadFile"
b155958 Update php supported version.
9e260a3 Reduce test length to avoid stack overflow on VS.
1c4cf0e Fix python cpp.
460e7dd Fix Visual Studio compile issues.
4cf0722 Fix default instance destructor
f9f3c35 Update version number.
0c78525 Bump library version to 11
e62d1f1 Add back removed descriptor field.
fac876d Modify php api version and minimum supported php version.
9372292 PHP: support 7.0 on PHP implementation (#2162)
f933d10 Update version number.
04d72c2 Fix java compatibilty tests.
9d4657a update files to include php generators
633fdfb Update minimum support php version to 5.5
9526385 Fix bugs for internal integration.
89d8e43 Fix travis, jenkins environment issues.
7fecfdb Added new has_bits.h file to cmake/extract_includes.bat.in (#2152)
f7bb847 Fixed quadratic behavior in JSPB deserialization of repeated fields (#2117) (#2146)
31dd499 Fix bugs for csharp and ruby for internal integration.
23d4688 Fix python bugs for internal integration.
93007e1 Bump library veriosn to 3.1
fe1aaad Fix bugs for internal integration.
15f4db6 Bump version number to 3.1.0-alpha-1.
af62fde Fix for maps_test.js in JavaScript. (#2145)
e3f0689 Fix bugs for internal integration.
cc8ca5b Integrate internal changes
337a028 Merge pull request #2236 from hochhaus/master
b2b6584 Silence compile warnings in bazel
bc3bff1 Fix python_cpp test on Mac. Link staticly when building extension, so that the extension doesn't require installing protobuf library. (#2232)
c0c3aee Merge pull request #2229 from xfxyjwf/fixbuild
431cee6 Remove inexist files from build.
d947308 update files to include php generators (#2165)
b0d62dd Add csharp/build_tools.sh for dist check.
96e2d76 Fix compile error for php on Mac.
75b6988 Fix segmentation fault when ZTS is defined.
52ab3b0 PHP: fix ZTS tsrm_ls errors (#2189)
71e5994 Merge pull request #2193 from acozzette/common-js-fix
60bc203 Merge pull request #2199 from JasonLunn/patch-1
2d897c8 Add test for php zts build.
3a055be Prepare jenkins for testing php zts build.
640c947 Merge pull request #2204 from acozzette/enum-names
149659b Do strict enum name checking only for proto3
858db7a Add travis test on Mac for php.
4d87527 Merge pull request #2218 from thomasvl/xcode8_updates
bcb32c0 Test php5.5_c test on jenkins
297449a Update the ObjC projects for Xcode 8
fe1d0a1 JS: Added string encoding/decoding tests for UTF-8
23f108d JS: Fixed UTF-8 string encoder/decoder for high codepoints.
350d494 Merge pull request #2206 from acozzette/gitignore
dae50dc Trigger automated tests for php.
f17528a Set up environment for php automated tests.
1baaedf Add php test script for automated tests.
25dbc8b Updated .gitignore with Java and JavaScript build artifacts
6005648 Add development dependency requirements
1d2c7b6 Fix MSVC build when HAVE_LONG_LONG is defined.
ee19a7c Remove hanging reference to Gemfile.lock
d94ff41 Delete Gemfile.lock
07f3cab Set platform to "java" under JRuby
b9bad65 Add script to build Google.Protobuf.Tools for csharp.
3b88a4a Merge pull request #2196 from haberman/nodefix
3d598ee Merge pull request #2197 from thomasvl/swift_docs
fb85b43 Drop the swift docs directory (and content).
8b54280 Added alias getFieldProto3 as used by older generated code.
c4d7012 Fixed references to foreign nested messages with CommonJS-style imports
3f59452 Merge pull request #2192 from google/3.0.x
787f3fb Fixing inconsistent php version number.
c531b49 Merge pull request #2181 from google/jtattermusch-patch-2
530eede Update README.md
4d3e4cf Fix MSVC stack overflow issue.
a428e42 Add php files for make dist.
e7269aa Update change log for 3.1.0 (#2173)
87d61e4 Merge pull request #2175 from xfxyjwf/fix_json
5248f61 Force a rebuild of Jenkins docker image.
907a075 php: support 5.5.9 for pecl extension (#2174)
3c88e1b Fix VS test failures.
c454b44 Merge pull request #2171 from xfxyjwf/fix_json
73c8723 Use "appveyor DownloadFile"
18f336b Update php supported version.
f6b4d18 Reduce test length to avoid stack overflow on VS.
411968d Fix python cpp.
37c3d05 Merge pull request #2167 from xfxyjwf/fix_vs
0798d91 Fix Visual Studio compile issues.
3bfc09d Merge pull request #2170 from pherl/3.1.x
f184cb6 Fix default instance destructor
34996c3 Merge branch '3.1.x' of github.com:google/protobuf into 3.1.x
a289d43 Added C++ benchmark. (#1525)
d9ff3ef Merge pull request #2153 from haberman/generatechangelog
8c88762 Update version number.
94bbeb4 Bump library version to 11
1b7a844 Add back removed descriptor field.
9cb812f Modify php api version and minimum supported php version.
11433f7 PHP: support 7.0 on PHP implementation (#2162)
39a2a25 update files to include php generators (#2165)
2649844 Update version number.
5270e93 Fix java compatibilty tests.
923314c update files to include php generators
1bf97d8 Merge pull request #2159 from google/jtattermusch-patch-1
da7c026 Update README.md
ca21b28 Merge pull request #2157 from google/csharp_remove_beta_notice
ca8120c Update README.md
8352d52 Update minimum support php version to 5.5
bee5213 Fix bugs for internal integration.
525c632 Fix hash computation for JRuby's RubyMessage
b8e7e89 Fix travis, jenkins environment issues.
b28ab73 Fix gson dependency. gson 2.3 has internal bug that it doesn't work with some versions of maven.
142e2fa Merge pull request #2035 from sergiocampama/cpp
a2e7364 Added convenient script for generating changelog draft.
e25c56a Merge pull request #2149 from khingblue/remove-obsoleted-project
050c014 Added new has_bits.h file to cmake/extract_includes.bat.in (#2152)
f81d44f Fixed quadratic behavior in JSPB deserialization of repeated fields (#2117) (#2146)
741aa87 Remove obsoleted project of j2me
b9bc990 Fix bugs for csharp and ruby for internal integration.
c8b9d41 Fix python bugs for internal integration.
1af7c4c Fixes static analyzer issues from xcode.
08e9f70 Bump library veriosn to 3.1
22d7248 Fix bugs for internal integration.
4f379f8 Merge pull request #2144 from abscondment/fix-jruby-hash
6cb6bd9 Fix gson dependency. gson 2.3 has internal bug that it doesn't work with some versions of maven.
ebcda12 Bump version number to 3.1.0-alpha-1.
679381f Fix for maps_test.js in JavaScript. (#2145)
05aa0df Fix hash computation for JRuby's RubyMessage
a2c6501 Fix bugs for internal integration.
0dca5a5 Use a custom dictionary to avoid NSNumber operations.
96c469d Remove the custom key functions and just use the system provided defaults.
98835fb Integrate internal changes
7b00595 Merge pull request #2137 from thomasvl/objc_extensions_tweak
6ab51a0 Use a custom dictionary to avoid NSNumber operations.
5904279 Remove the custom key functions and just use the system provided defaults.
b5bbdb0 Merge pull request #2037 from abscondment/fix-2036-ruby-hash
c44ca26 Merge pull request #2130 from kilink/substring-comment-fix
9ac84f8 Fix erroneous comment regarding String.substring
3b001ca Some php engine implementation doesn't have return_value_ptr properly set. Explicitly use &return_value.
c6fa9c7 Auto-generate proto files for tests.
f174d36 Add back missing test proto files.
37e0e1f Merge pull request #2111 from pherl/3.0.x
9c4be5f Merge pull request #2112 from pherl/merge
b4235ac Merge pull request #2123 from thomasvl/objc_better_versioning_take2
1aa6500 Update the ObjC version checks to support a min and current version.
e0e5466 Check in php implementation. (#2052)
683412b Update generated files.
58860c0 Merge remote-tracking branch 'origin/3.0.x' into merge
13d6d17 Fix the version number for 3.0.2
86fcd87 Merge pull request #1765 from mbarbon/master
1affbd8 Merge pull request #2021 from zlim/bench-fix
4f032cd Merge pull request #2100 from vladmos/patch-1
22e7fa6 Merge pull request #2092 from dprotaso/master
5caf516 Resolved a conflict
78aee1b Merge pull request #2044 from wychen/Win32ANSI
643a02b Merge pull request #1636 from yugui/feature/generic-plugin
53387e5 Merge pull request #2090 from guoxiao/find
e90292b Merge pull request #2103 from adrianludwin/fix-gtest
1327e6f Update repo to use google test
7377eb2 Merge pull request #1970 from thomasvl/objc_any_helpers
a86e6d8 Compatibility with the new version of Bazel.
5d35e60 Merge pull request #2094 from thomasvl/update_wkt_comments
57170b9 Merge pull request #2096 from pherl/3.0.x
5699b92 More complete nil/reset tests within a oneof
708296e Fix some constants to be correct for the message class in use.
161b937 Fix error and add note about lossy issues
14e74f6 Support the -Wassign-enum compiler flag. (#2085)
1fc416b Allow the JsonFormat.Parser to ignore unknown fields
a15df74 Merge pull request #2087 from khingblue/fix-unused-param
337ec30 Add ObjC helpers for Any WKT.
82133ba include std::find()
08b1c71 Fix #2032 unused parameter 'deterministic'
4bc1657 Merge pull request #2079 from khingblue/fix-generate-descriptor
30e55ae Merge pull request #2083 from pherl/3.0.x
7645a3d Merge pull request #1884 from hochhaus/valueWriterFn
f9fc56c Fix #2071 replacing /bin/sh with bash
1a58673 Merge pull request #2077 from pherl/3.0.x
e298ce5 Update release date in the change log
74638a2 Merge pull request #2047 from jonathon-love/master
65a595d Merge pull request #2062 from pherl/3.0.2
01d1750 Merge pull request #2061 from pherl/changelog
9b8da10 Rm check on dependency in the C# reflection API (#2051)
96a9d97 Merge pull request #2059 from chih-hung/master
7c3f7c6 Fix #1955 clang-tidy warning misc-macro-parentheses
6e11540 Bump version number to 3.0.2
0c9999f ruby, js and c# changes
a098e80 Merge pull request #1862 from pherl/3.0.0-GA
4041ed4 objc change log
9befe47 Merge pull request #1978 from pherl/cp
9d30a98 Merge pull request #2026 from pherl/cpjs
fa6428e Merge pull request #2045 from mike07026/master
85c1adf Merge pull request #2053 from thomasvl/improve_root_registry_wiring
64958cd Fix to typo/oversight in python tests
a7eaf36 Rename UNICODE to protobuf_UNICODE
13a4124 Make Root's +extensionRegistry generation smarter.
d00cab0 Merge pull request #2039 from khingblue/remove-unused-vector
df6088a detect invaild JSON encoding in bytes field
5a17660 detect invaild JSON encoding in bytes field
e514f23 fix #1342 cause by ownership issues
48811b2 Fix Win32ErrorMessage on Unicode build
11d6cb5 Add test for Win32ErrorMessage
588a803 Support Unicode build on Windows
b964976 Merge pull request #2024 from pstavirs/master
52e491b Use 64-bit protoc binaries in compatibility tests.
8ee6f56 Remove unused vector
de02863 fix #2036: use `rb_hash_*` to accumulate hashes
047419a failing test for #2036:
c0a6a6b Merge pull request #2033 from frett/osgiExport
b6dec9b update the OSGi SymbolicName and ExportedPackage for the javanano library
dd45c0b Merge pull request #2012 from haberman/rubymapgcfix
8c93606 Merge pull request #2031 from thomasvl/dont_require_filegenerators
78a6d31 Speed up ObjC Generation with large dependency trees
e721ce6 Merge pull request #2012 from haberman/rubymapgcfix
8335b7d Fix missing import of jspb.Map (#1885)
3a674ff upb bugfix: JSON map entry keys were passing the wrong closure.
eedc7be Restore New*Callback into google::protobuf namespace since these are used by the service stubs code
7e62773 Merge pull request #1920 from gegles/master
c32b9dd Merge pull request #2018 from thomasvl/support_generate_all
f5c7a48 benchmarks: update readme.txt
4fd4471 Merge pull request #2014 from pherl/fixgmock
2e66a61 Support GenerateAll().
1760feb Update gmock links.
1e6dc7d Update links in appveyor.yml
d4213d8 Ruby: make sure map parsing frames are GC-rooted.
3d9d1a1 Merge pull request #2013 from xfxyjwf/gmock
c4a84ab Update links in appveyor.yml
bba446b Update gmock links.
08951c3 Merge pull request #2011 from tomas-abrahamsson/patch-1
4d04fcd Add an Erlang project, gpb, to third_party.md
b97a4a5 Merge pull request #2001 from nicolasnoble/patch-1
866d3e5 Fixing regular expression...
569d5ce Merge pull request #1997 from thomasvl/move_include_package_into_helpers
290d26b Remove the compiler options from ImportWriter.
93362a5 Move the ImportWriter into the ObjC Helpers.
80f65d2 Add note about JSON tests maybe being wrong. (#1992)
b5794ed Merge pull request #1984 from thomasvl/more_json_tests
7437774 More JSON tests
ff2a660 Adds better support for protos without packages  (#1979)
8b30145 Add a jenkins test status badge.
45d04d0 Merge pull request #1977 from thomasvl/bump_cocoapod_spec
584917f Bump the version in prep for the 3.0.2 tag being cut
564c02f Merge pull request #1975 from pherl/cp
a877fdf Record zero for "has" for proto3 if in a oneof.
116596a Never use strlen on utf8 runs so null characters work.
62f2ff8 Fixes extra whitespace on generated comments. (#1950)
a989501 Adds support for appledoc in generated code.  (#1928)
42ab9b4 Migrating documentation of the ObjectiveC runtime code to appledoc. (#1867)
549dde1 Merge pull request #1967 from sergiocampama/cast
e505098 Adding casts so that code importing protobug using -Wconversion does not generate warnings.
e389165 Add more JSON tests around underscores (#1963)
4763e64 Merge pull request #1957 from xfxyjwf/jenkins_badge
d9ccf4d Merge pull request #1964 from thomasvl/missing_ignores
8156410 Fix up ignores and conformance generation
336ee28 Merge pull request #1960 from jskeet/oneof
f9d93f3 Regenerate conformance files to include extra oneof fields.
bbeb983 Need to expose generated protobuf C++ headers so they can actually be accessed from other libraries.
f8c37b9 Add a jenkins test status badge.
a248420 Fixes extra whitespace on generated comments. (#1950)
cd561dd Merge pull request #1949 from thomasvl/objc_more_reset_tests
ff85a17 More complete nil/reset tests within a oneof
a0df678 Fix some constants to be correct for the message class in use.
17d601a More explicit tests for nil behaviors on fields.
91b6d04 Merge pull request #1942 from thomasvl/objc_fix_oneof_zeros
27c8962 Add more types to the zero oneof cases.
ca5b775 Record zero for "has" for proto3 if in a oneof.
ac3df39 Add conformance test for zero fields in oneofs. (#1939)
30bbbe9 Merge pull request #1934 from thomasvl/objc_strings_with_null
1a6c1d0 Never use strlen on utf8 runs so null characters work.
237f321 Adds support for appledoc in generated code.  (#1928)
56b8f44 Merge pull request #1842 from udnaan/master
32fadc0 Migrating documentation of the ObjectiveC runtime code to appledoc. (#1867)
1102a8a Merge pull request #1923 from bryongloden/patch-1
a375e1a close opened file descriptors properly
e30b7b4 Merge pull request #1924 from PiotrSikora/export_license
f1f30b5 Merge pull request #1926 from hotpxl/master
ddf6d1e [master] Add dependency cl. Fixes google/protobuf#295.
faea19c Bazel: export LICENSE file.
c59473d Merge pull request #1044 from mark-whiting/master
6d134ea Merge pull request #1898 from sergiocampama/watchos
ea081fe Fix missing import of jspb.Map (#1885)
0dca3cc Merge pull request #1865 from podsvirov/topic-cmake-project
dedd8ae Merge pull request #1914 from adamatan/typo-fix
3886860 Typo: beffer -> buffer
cf42b60 Merge pull request #1905 from pherl/fixdoc
eefd1fd CMake: Auto find ZLIB from package config if nedded
3916a0a Add and fix C++ runtime docs
8d8115b Merge pull request #1878 from haberman/rubywkt
e0779d5 Merge pull request #1903 from xfxyjwf/compatibility_tests
3cec2ea Ruby: added custom Struct exception type and fixed Makefile.am.
30647ca Use 64-bit protoc binaries in compatibility tests.
ff46627 Merge pull request #1902 from podsvirov/topic-cmake-extract-includes
7d275ec CMake: remove repeated_field_reflection.h from extract list
00d5a7f Amend the conformance tests to only use Int64/Uint64 non-wrapped values which (#1164)
275db04 Adds watch os deployment target for protobuf
6b3d120 Merge pull request #1887 from sheffatguidance/fix-js-api-documentation
1112989 Merge pull request #1884 from hochhaus/valueWriterFn
915d79e Merge pull request #1895 from google/3.0.0-GA
3ef0756 Merge pull request #1894 from pherl/fixdist
e139117 Add python/setup.cfg into dist files
169d0ca Merge pull request #1893 from google/3.0.0-GA
c479042 Merge pull request #1892 from xfxyjwf/compatibility_tests
baa4023 Run Java compatibility tests on Travis.
f3449e5 Merge pull request #1891 from pherl/python
811674f add setup.cfg for building wheels
42e5487 Merge pull request #1882 from legrosbuffle/fix-check
7e93458 Merge pull request #1888 from pherl/fixbuildzip
6a59ac9 Fix the build-zip.sh to add .exe for win packages.
9a11ab4 Fix Issue #1869: faulty js API documentation
a217408 Fix valueWriterFn variable name
c466f4b Be consistent with the use of CHECK()/ GOOGLE_CHECK().
a207a2b Fix for JRuby (assert_true is not present).
e3094a8 Ruby: added API support for well-known types.
de30c56 Merge pull request #1874 from pherl/buildzip
e3fac65 Change the build.zip.sh to support lite
2662fd3 Merge pull request #1871 from pherl/fixwin
1b1a8f4 Fix build protoc script for windows
33d2b2a CMake: Bugfix for protobuf_MODULE_COMPATIBLE
38c5f2f CMake: Link to ZLIB only if protobuf_WITH_ZLIB enabled
e8ae137 Merge pull request #1864 from pherl/galogs
e7982e4 Fixed Makefile.am for Ruby file rename.
e0d817e Change log for 3.0 GA release.
4e169bf Bring C#'s ToPascalCase method in line with C++. (This still doesn't fix the conformance tests, but at least we're now consistent with the C++ code.)
86535a1 Remove legacy_enum_values flag for GA.
be78976 Merge pull request #1861 from jskeet/fix_to_camel_case
af2fa05 Merge pull request #1859 from jskeet/remove-flag
a8aae89 Bring C#'s ToPascalCase method in line with C++. (This still doesn't fix the conformance tests, but at least we're now consistent with the C++ code.)
e672047 Remove legacy_enum_values flag for GA.
7ba044a Merge pull request #1853 from pherl/3.0.0-GA
7c9c314 fix comments.
0750797 Merge remote-tracking branch 'origin/3.0.0-GA' into 3.0.0-GA
54feb9a Fix the script comments.
b1aac0b Make protoc-artifacts able to build plugin.
032fb91 Merge branch 'master' of github.com:google/protobuf into 3.0.0-GA
154e278 fixed cmake config files install path
b6b521b Merge pull request #1851 from xfxyjwf/cint
12581b4 Fixes traivs cpp build.
234ec01 Merge pull request #1847 from haberman/GAfixes
43b36dd Fixed Makefile.am for Ruby file rename.
f11a4f1 Merge pull request #1841 from pherl/3.0.0-GA
b3b07cd Merge branch 'master' into 3.0.0-GA
ba52f2b Merge pull request #1788 from google/rubypackagecap
c43f718 Merge pull request #1846 from xfxyjwf/zip
97e2026 Added new file to ruby_EXTRA_DIST.
6d92233 Added unit test for PascalCasing package names in Ruby.
6cab568 Ruby: translate package names from snake_case -> PascalCase.
b553b87 Add a script to build protoc zip packages.
b1cecb6 Merge pull request #1837 from haberman/rubygencodename
0973822 remove extra zeros.
5a6c921 Make jruby still depend on beta-4
a17367f Define intX as standard exact-width integer types.
fb7a7c5 Bump version number for GA
4f19797 Ruby: generated foo.proto -> foo_pb.rb instead of foo.rb.
868ea59 Merge pull request #1831 from xfxyjwf/protoc
b6cd9dd Merge pull request #1834 from sergiocampama/framework
44bd6bd Merge pull request #1821 from haberman/rubyfreezestr
d07a996 Ruby: fixed string freezing for JRuby.
9e3c98f Fix maven path.
3a1259c Correctly sets the generate_for_named_framework option after parsing.
0622030 Merge pull request #1830 from xfxyjwf/travis
1b3796c Merge pull request #1829 from xfxyjwf/fixcpp
fdd970e Fix maven links.
9702b9f Keep cpp_distcheck on travis for now.
c2ced9a Remove linux tests from travis.
9009662 Fix sign-comparison warnings in public header files.
16adea3 Add a test to catch sign-comparison warnings.
4ddaad4 Merge pull request #1825 from xfxyjwf/jenkins2
de5236d Merge pull request #1828 from sergiocampama/framework
2ff9349 Fixes the parsing of the proto-framework map file.
20fbb35 Add more tests to jenkins.
2ba058c Merge pull request #1822 from xfxyjwf/java6
ff7f68a Ruby: encode and freeze strings when the are assigned or decoded.
ad49ed7 Update travis tests for Java.
30d8416 Merge pull request #1811 from xfxyjwf/fixdist
a4f68b1 Add missing files in EXTRA_DIST and add a test.
af8732e Merge pull request #1810 from xfxyjwf/versioning
e465f26 Merge pull request #1812 from jskeet/fix-travis
dd3d9d6 Merge pull request #1447 from seishun/defaults
73e0b49 fix debug.dump
deaea21 Use the dotnet-release package feed for Travis.
60cb094 Add files missing from "make dist".
36adb40 Update compatibility tests as well.
2e30301 Versioning Java GeneratedMessage.
e4b129f restore old behavior for toObject
db1b2a0 nits
970a4fd Make implicit defaults consistent with explicit defaults
77b08af Merge pull request #1802 from haberman/jsmapbin
e0e7377 Fix goog.require()/goog.provide() ordering.
24ac9c0 Merge pull request #1803 from xfxyjwf/javadoc
fa52702 Include javadoc/source in Java release packages.
7429b91 JavaScript: move extension binary info to separate struct.
2078f61 Merge remote-tracking branch 'origin/3.0.0-beta-4'
923eae8 JavaScript maps: move binary callbacks out of constructor.
56855f6 Merge pull request #1792 from xfxyjwf/changelog
82b43d1 Remove Java deterministic API.
b6a620d Merge pull request #1801 from thomasvl/oneof_framework_build_issues
2e98ed5 Use public methods to fetch oneofs in generated code.
3d9726f Mention Java lite in the changelog.
b99577c Exposes the currently registered extensions for a message and removes the internal sortedExtensionsInUse
f6d1d1a Uses head version of rvm to avoid shell_update_session not found error (#1791)
1349fb8 Added 3.0.0-beta-4 changelog.
3a8d8ea Merge pull request #1787 from xfxyjwf/steppingstone
1bce70d Fix compatiblity issues.
0b68255 Add missing golden test file.
e1f146b Merge pull request #1785 from jskeet/merge-csharp
b5ce525 Move to dotnet cli for building, and .NET Core (netstandard1.0) as target platform (#1727)
5e0de1e Remove the overload for Add(RepeatedField<T>)
2ee1e52 Optimize AddRange for sequences implementing ICollection
b053b92 Implement RepeatedField.AddRange.
d9334ea Improve exception throwing implementation in collections
10a8fb4 Move to dotnet cli for building, and .NET Core (netstandard1.0) as target platform (#1727)
4e0d051 Merge pull request #1781 from xfxyjwf/update_version
c2ebdec Update version number in AssemblyInfo.cs.
8b659b2 Merge pull request #1783 from xfxyjwf/fixlite
047a3b4 Exclude Java lite module from parent pom.xml
dd37b99 Comment out lite conformance test.
932f94e Update version number to 3.0.0-beta-4
06a0248 Add missing LIBPROTOBUF_EXPORT
7a7913e Add missing LIBPROTOBUF_EXPORT.
443eb27 Update generated files.
9086d96 Integrate from internal code base.
042993b Implement RepeatedField.AddRange (#1733)
8eb90e3 Merge pull request #1778 from yeswalrus/fix-prerelease-version
5520447 Fix a bad variable dereference causing <package>_FIND_VERSION_PRERELEASE to be ignored.
70c1ac7 Merge pull request #1776 from thomasvl/fix_dist
0d079bc Remove the baseline files from the make dist file list.
790e6af Fixed out-of-date documentation for CodedInputStream.ReadEnum. (#1581)
3560cc9 Merge pull request #1702 from lukebakken/csharp-nuget-doc-update
297ec74 Add https://metacpan.org/pod/Google::ProtocolBuffers::Dynamic
8779cba Merge pull request #1764 from jskeet/remove-is-value-type
3df146e Remove unnecessary reflection call
c404c2a Merge pull request #1762 from thomasvl/drop_perf_profiles
8c23655 Drop the performace baselines.
8b00675 Merge pull request #1757 from thomasvl/avoid_importing_src
03d9e09 Merge pull request #1735 from jskeet/attribute-placement
c850ebc Merge pull request #1758 from dago/pathmax2
e9a7fc8 Remove WriteGeneratedTypeAttributes which is a no-op
57638d5 Make sure also Solaris x86 gets PATH_MAX
eaf3451 Merge pull request #1753 from xfxyjwf/fixup
be0d7f6 Don't #import the .m files.
0d5091e Merge pull request #1742 from ottok/fix-spelling
d84d0ca Fix data member declaration order.
a29a9c5 Don't support global ::string in stringpiece.h
c10938a Merge pull request #1752 from acozzette/fix-js-tests
c64d86e Fixed failing JS tests
ec45897 Merge pull request #1712 from dkharrat/swift-error-handling
523bfd4 add nullable qualifier to nil return types
c534845 Changes to generated code from previous commit
ada0a81 Move DebuggerNonUserCodeAttribute to function members
d2ae496 Fix spelling error in function ParseTime parameter
3808d09 Fix spelling in strings and comments
cae3b0c Merge pull request #1704 from lizan/json_parse_options
02b55d2 Merge pull request #1738 from xfxyjwf/fixbuild
e102db1 Fix some failing travis tests.
aeff638 Merge pull request #1710 from chezRong/master
7e8c893 Merge pull request #1723 from thomasvl/objc_test_coverage
454dbf1 added minified JSON formatting functionality with test
2fe0556 Fix windows build.
69cc213 Updated failure_list_java.txt to remove tests that now pass
b83af52 Fixed string formatting in text_format.py to be Python2.6-compatible
d64a2d9 Integrated internal changes from Google
6cfc19e Xcode project cleanup/setup.
c18aa77 Validate the tag numbers when parsing. (#1725)
e0016c5 Merge pull request #1720 from thomasvl/issue_1716
31999a3 Add JsonParseOptions to ignore unknown fields
dc0aeaa Adding conditional compiler symbol to support .NET 3.5 (#1713)
fc4c617 Fix GPBGetMessage{Repeated,Map}Field()
7b5648c Merge pull request #1719 from esteluk/patch-1
3be6110 Fix Objective-C generator option typo
2bcd43a Merge pull request #1714 from dnkoutso/master
37ca94f Get value from text format name in GPBEnumDescriptor
0ab78e1 Merge pull request #1705 from haberman/revjsver
6a6f95d JS package.json: Added author and updated Closure Library version.
6f67be6 Merge pull request #1707 from jskeet/format-value
0421238 Expose JsonFormatter.WriteValue.
1dc6280 Moved all dependencies to devDependencies.
48735cb Add "google" to package.json "files" for WKT.
c4b40a3 Create patch release for JS to include WKT.
8069466 Modify csharp README since there are now two NuGet packages
a897ebb Merge pull request #1700 from jskeet/ordering
a230b5d Rename methods to avoid ObjC KVC collisions. (#1699)
e3f6e2b Remove ordering guarantees in the MapField documentation
1a5333b Adds destination flag to xcodebuild to avoid possible flake errors (#1697)
4f93098 Merge pull request #1666 from yeswalrus/cmake-prerelease-examples
b7560df Merge pull request #1696 from haberman/jswkt
8c20e55 Add new generation option for using proto sources from other frameworks.
104723f Fix tests for CommonJS.
98bd6d7 Merge pull request #1692 from vjpai/friendless
4308cc4 Added plugin.proto to well-known types for JS.
6daf3d2 Address review comments on function name
0e27112 Bugfix: base the require logic on the file being required.
1337486 JS: import well-known types from google-protobuf package.
37eaae2 Remove a friend-class template that is only used for the constructor, and instead create an _internal_only getter that gets the needed information. This is a workaround for a deficiency in gcc-4.4 that does not properly support templated friend classes.
52598c6 Merge pull request #1658 from yeswalrus/cmake-fixup-module
a5e116a Merge pull request #1665 from yeswalrus/cmake-package-requirements
f180ef6 Merge pull request #1683 from thomasvl/third_party_framework
a2a3399 Add support for generation sources into a framework.
f0c1492 Add the CocoaPods integration tests to Travis.
71f4a9c Fixes Xcode 8 analyzer warning saying that it was missing a release in dealloc (#1678)
088c5c4 Merge pull request #1664 from bshaffer/patch-1
4150a91 make protobuf_MSVC_STATIC_RUNTIME a dependent option to reflect it's use.
78b3498 Save the relevant options used to create a package, allow users to reject packages based on them.
5ebcfc1 Fix prerelease version matching to be more consistent with the find_package arguments.
f8a969d proper codeblock in README
fba7976 Merge pull request #879 from mathstuf/support-equals-in-proto-path
cadfbc8 Removed handling for ALIASED targets since they are unused.
401e07d Add GOOGLE_ prefix before PROTOBUF_DEPRECATED_ATTR
b60e615 Fix the undefined behavior for opensource users.
6aa981f Merge pull request #1624 from yeswalrus/cmake-prerelease-versioning
dfe0c9a Merge pull request #1643 from yeswalrus/cmake-examples
ed1d560 Merge pull request #1541 from haberman/conformancestrict
350453f Make surrogate regex even more lenient.
923d2c7 JSON surrogates Python: adjust regex for OSX error message.
23fef56 Replace handwritten protobuf-targets with exported version.
09f6a5c Use ExternalProject_Add to build the examples in a stand-alone fashion.
7155629 CMake project updates
6a61894 Added test for surrogates (valid and invalid).
84a1b60 Added update_failure_list.py.
4833b4c Surrogate checking is unpredictable, so always manually check.
bd98eae Fixed Python by updating failure lists and fixed a few broken tests.
ef7894e Make conformance tests more strict about the failure list.
20b5325 Integrate interanl changes
e34c091 Improving the granularity parsing errors (#1623)
0ab7a7f Merge pull request #1640 from os72/master
5977fb0 Generalize plugin support in Bazel Skylark rule
f6be0d1 Add https://github.com/os72/protobuf-dynamic
0420eab For prerelease versions, require protobuf_FIND_VERSION to be set.
f1091ab Include the prerelease version in the protobuf_VERSION
18a9140 Merge pull request #1625 from yeswalrus/note-versions
cc30be1 Merge pull request #1613 from yeswalrus/cmake-min-version
c461193 Merge pull request #1629 from zhongfq/patch-1
a315bb8 Merge pull request #1614 from yeswalrus/cmake-cleanup
e215828 Merge pull request #1630 from google/beta-3
e845187 Merge pull request #1620 from sergiocampama/cleanup1
4629659 add protobuf as3 lib and code generator for as3
457a297 Remove __PROTOBUF_PACKAGE_PREFIX
61c9696 Update the list of places where the version is stored.
a714c40 Removing unused GPBExceptionMessageKey
40ff94e Merge pull request #1617 from thomasvl/more_warnings
86e8f1f Merge pull request #1604 from jonwallg/repeated_types
38b9e74 Add -Woverriding-method-mismatch.
d13b3d0 remove useless cleanup - config.cmake files are executed in their own context.
c57c6ea Bump to the *real* minimum required version. Setting CMP0022 breaks CMake versions < 2.8.12
04265e4 Remove if(TRUE)
e72805e fix expected class checking in GPBSetMessageRepeatedField
0f27cab Merge pull request #1600 from thomasvl/objc_tighter_warnings
ed87c1f Merge pull request #1586 from davidzchen/python
02cd45c Bazel build: Keep generated sources and Python runtime in the same directory.
c8a440d Add more warnings to for the ObjC runtime build
d089f04 Merge pull request #1595 from thomasvl/objc_travis_tweaks
368a2f4 Automated testing tweaks for ObjC
5d0c2ee Merge pull request #1593 from thomasvl/framework_includes
173daf1 Merge pull request #1589 from hochhaus/master
7da023b Better support for using the proto library from a framework.
2131b2d Merge pull request #1588 from jeffmvr/master
7336092 Add js/binary/encoder.js to js_EXTRA_DIST.
733ef98 added missing closing bracket for _cmakedir_desc in cmake/install.cmake line 88
594ce56 Merge pull request #1578 from wal-rus/cmake-install-namespace
28f35b4 add protobuf:: namespace to installed targets
38e4713 Merge pull request #1523 from xfxyjwf/compatibility_tests
a31d14b Describe platform requirements for the compatibility tests.
5c6518f Merge pull request #1583 from thomasvl/pods_integration_followup
2338e03 Merge pull request #1576 from wal-rus/cmake-versionfile
beca1f5 Merge pull request #1575 from wal-rus/cmake-install-msvc
6c47faa Make the CocoaPods integration tests more robust
02a28a8 Update protobuf-config-version.cmake.in to correctly set the required variables (PACKAGE_VERSION_EXACT, PACKAGE_VERSION_COMPATIBLE, PACKAGE_VERSION_UNSUITABLE)
7d79458 Fix the cmake configuration file install path to be more standards compliant (See the description of cmake's config search behavior on https://cmake.org/cmake/help/v3.4/command/find_package.html)
c034ba7 Merge pull request #1574 from thomasvl/test_schemes
20b5bf6 Add shared schemes for the CocoaPods integration tests
12dffd9 Merge pull request #1572 from thomasvl/podspec_tests_2
16dd477 CocoaPod Integration Tests
cc5296b Merge pull request #1558 from haberman/rubyoneof
daec44f Expand the OS X/Xcode gitignores
2d514ce Fixed oneof behavior for enums and fixed JRuby.
b8ded18 Merge pull request #1561 from pherl/beta-3
d550528 Bump objc podspec version number
431ba4b Merge pull request #1549 from xyzzyz/arena_export
ba696e7 Merge pull request #1547 from xyzzyz/js_generator
cbb9183 Merge pull request #1559 from google/beta-3
545527e Ruby oneofs: return default instead of nil for unset fields.
32e3d7a Merge pull request #1412 from google/internal
6673283 Integrate interanl changes
718eb75 Merge pull request #1548 from anandolee/master
97aa8a0 Merge pull request #1551 from pherl/beta-3
fe06eb6 Fix protoc artifact pom version
b01b1a8 JSON format for Any message must print @type first, use OrderedDict instead of {}
4f630a6 Add compatiblity tests against v2.5.0
810ba9b Export class Arena to shared library.
f2885f6 Fix #include in js_generator.cc
67d2d45 Merge pull request #1546 from pherl/beta-3
b3bb46c Added download_url to be able to upload to pypi.
c8be6ee Merge pull request #1542 from google/beta-3
3470b68 Merge pull request #1540 from pherl/changelog
cf1fd7e Merge pull request #1533 from pherl/mapcomment
0ec34bf Update changes for lite
5e7c4cb Remove the comments about iterator validation
f2db1e0 Merge pull request #1532 from pherl/changelog
034867f Update changelogs for C++ maps
dc49706 Merge pull request #1529 from gkraynov/test-redundant-varint
5c29835 Merge pull request #1528 from pherl/master
b126706 Merge pull request #1527 from haberman/changelog
d346f49 Added release notes for Ruby and JavaScript.
ce7e502 Remove the instructions for pbconfig.h
7b87f77 Merge pull request #1521 from zhangkun83/master
04757db Fix the server id in example
9f84114 Merge pull request #1520 from pherl/hashmapvs2008
325cc42 Merge pull request #1522 from xfxyjwf/compatibility_notice
f9fd450 Merge pull request #1524 from anandolee/master
5d54a85 Test redundant varint fields decoding in JS.
371d341 Merge pull request #1518 from jskeet/move_test
e4ca694 python changes
09732c9 Add compatibility notice for Java.
28cb77f Fine-tune build scripts and better documentation.
e1f588a Merge pull request #1 from google/beta-3
71dd9c4 Merge pull request #1515 from pherl/changelog-beta3
ede9cc4 Update comments for csharp, zero-copy and objc.
19472bf Merge pull request #1512 from pherl/beta-3
017d390 Fix csharp version
dbdf6d9 Bridge vs2008 hashmaps.
5668e2e Fix typo.
920ee73 Merge pull request #1483 from wal-rus/fix-boost-incompatibility
7cc9cb4 Move test for standalone BoolValue to JsonParserTest
cca2d44 Merge pull request #1517 from jhickson/boolvalue
835fb94 Fixed parsing of BoolValue.
2b22b61 Merge remote-tracking branch 'refs/remotes/google/master'
c67879b Merge pull request #1514 from pherl/fix_heap_check
0e4d1ea Initial draft for changelog.
e8737d8 Fix the command line interface unittest again
cdd3ec7 Merge pull request #1513 from pherl/fix-build-protoc
25dd690 Fix protoc build artifact script.
5dea201 Update version numbers for other languages
dbed8a0 Update version numbers for beta3
a1938b2 Merge pull request #1510 from thomasvl/nonnull
4755bdc Declare an init and avoid passing NULL to initWithValue:count:
4c6259b Merge pull request #1498 from thomasvl/build_cleanup
f4bc9e0 Remove confounding and unused #define - breaks boost/predef/other/endian.h
d392ed4 Merge pull request #1502 from pherl/master
ce6bec7 Remove accidentally restored deleted files.
9d0f560 Merge pull request #1494 from pherl/master
76a96d4 Merge pull request #1499 from beardedN5rd/master
2eb774e after comment of Feng Xiao changed the entry to g++
ace2690 Merge pull request #1496 from ozkuran/master
b661fb5 Add the missing maintiner-clean entry for benchmarks
ce2ef0d Properly express all outputs for the conformance build
f367642 Add two missing ignores for conformance directory.
b12f630 updated README
9b3357d Updated README.md
5b5e369 Merge pull request #1471 from jskeet/any-host
f8a5c5f Fix using std::shared_ptr
75e5898 Fix the std::string error introduced in integration.
17b6fc3 Merge pull request #1409 from eeight/fix_enum_corruption
72e162c Merge pull request #1482 from nicolasnoble/rake-tweaks-2
edd2949 Properly generating well known proto files for the macos build.
07bcf21 Merge pull request #1464 from google/benchmarks
7dda312 Merge pull request #1473 from nicolasnoble/rake-tweaks
247ef1f Addressed PR comments.
09f1757 Merge pull request #1467 from pherl/master
236b939 Addressing concerns.
e0df23a Update descritpor protos for objc
aed7b34 Merge pull request #1474 from pherl/fixscript
454d5be Merge the script fix.
cf7e99d Fix cp -r usage to be portable.
1f8b6da Few tweaks to the rakefile to permit native gems compilation with the proto files generation.
b2d4b1a Fixed for pre-C++11 ifstream which does not accept std::string.
49a8918 Read files directly from filesystem since xxd isn't always available.
cb36bde Make the C++ tests build the benchmarking code.
1ce5bd8 Updates for PR comments.
61307b8 Allow custom type URL prefixes in Any.Pack
f86d39c Update file lists.
12fdeb9 Merge branch 'master' of github.com:google/protobuf
cf14183 Down integrate from Google internal.
b53417c Merge pull request #1462 from acozzette/ruby-2.3
30a2f70 Added README describing the directory.
2e83110 Added framework for generating/consuming benchmarking data sets.
cbb6b28 Merge pull request #1461 from thomasvl/fix_bool_handing
3064628 Fix up -hash/-isEqual: for bool storage.
bbb68fe Added dig and bsearch_index to RepeatedField methods forwarded to array
f53f911 Merge pull request #1455 from haberman/updateupb
66f0745 Merge pull request #1454 from thomasvl/enum_defaults
18b6a32 Proper checking of enum with non zero default
d419ca1 Updated upb and simplified ruby code a bit with new upb method.
4057447 Merge pull request #1444 from mbrtargeting/master
385755e Add initial design document for Swift protocol buffers. (#1442)
db93833 Added serialVersionUID to ExtendableMessage.
034294b Merge pull request #1438 from xfxyjwf/docs
f4f9aec Fix bug with silent message corruption in LITE_RUNTIME.
0ad2048 Merge pull request #1416 from cwhipkey/master
8052dc7 Add a docs directory and move the third-party add-ons page here.
462e7fa protoc: support '=' in --proto_path arguments
f00300d Merge pull request #1414 from xyzzyz/googletest
1ccb4ca Merge pull request #1434 from jskeet/regenerate
c588ac4 Regenerate well-known types for C#
e539e98 Merge pull request #1433 from thomasvl/check_wkt
511f28b ObjC support for failing the build in the generated WKTs are out of date
f265fb8 Merge pull request #1401 from jskeet/enum-casing
36978c3 Merge pull request #1417 from seishun/windows2
d90d615 Attempt to fix AppVeyor build by exporting GetEnumValueName
790f4c8 Use the original name in JSON formatting.
84ea2c7 Regenerate all C# code and make it compile
75626ed Add C# codegen changes to enum value names (mostly C++)
1dc8194 Merge pull request #1428 from pherl/master
1b0ff34 Add missing includes in field mask test
52825bf Merge pull request #1426 from thomasvl/fix_comment_typo
e664aa6 Regenerate the WKT to pick up current changes to the proto files.
83a7a5e Merge pull request #1402 from davidzchen/py2and3
3633bcd Fix comment typo
072296f Merge pull request #1422 from pherl/master
1f4f3e2 Update file list to include the missing extension lite file.
7ff229f Support Windows in gulpfile.js
ca9bbd7 Merge pull request #1413 from haberman/updateupb
baf52bd Change protobuf CPP proto generator to support the 'lite' option in proto3.
e67ef3d Bugfix for JSON error case.
800e986 Remove no longer applicable documentation from README.md.
194ad62 Ruby JSON: always accept both camelCase and original field names.
1b912fc Remove googletest.h header from stringprintf.cc
90c7f6e Documented the JSON change and compatibility flags.
94e54b3 Updated upb: picked up legacy JSON flags to help Ruby users migrate.
814685c Merge pull request #1397 from google/internal-merge
3c4ce52 Fix for gulpfile.js.
2a197b3 Use 0 as the default value for all enums, rather than finding the actual enum value name
3ffbdd7 Merge pull request #1400 from jskeet/fix-internal
5ebeefb Add missing PY2AND3 srcs_versions attributes to Python Bazel build targets.
0a902ee Fix to csharp_options - initialize internal_access to false.
2cd79bf Removed duplicated operator delete from merge conflict.
4465daa Merge branch 'master' into internal-merge
667f4a6 Merge pull request #1393 from gvaish/master
1523936 Fix for CommonJS tests.
09292d5 Merge pull request #1392 from anandolee/master
a6e3931 Added support for internal_access for C#
cef46e1 Merge pull request #1390 from jskeet/tidy-up
c612074 sync the Manually integrate changes in google3/third_party
28c5c25 Merge pull request #1391 from thomasvl/string_tweaks
f98d2f5 Updating Xcode Settings to use iOS 9.3
2a18bb5 Add more documentation for csharp_options.h
bfd1c84 Line-wrapping changes only for C# generator code
c9167f2 Error during parsing for invalid UTF-8 instead of dropping dropping data.
f3f5b3f Add tests to ensure we read strings with BOMs so we don't forget about lessons of the past.
89719f0 Merge pull request #1349 from gvaish/master
f3fe75b Merge pull request #1386 from andrewharp/patch-2
74d8b0b Added access_level for types
3b4e7dc Update BUILD
b56b461 Do not link in pthread library for Android builds.
a771c9e Merge pull request #852 from qzix/master
268ce28 Added deprecated option handling for objective-c generator
aeacf51 Merge pull request #1381 from pherl/internal-merge
7630a83 Merge branch 'master' into internal-merge
cba75ad Merge branch 'master' of github.com:google/protobuf
89343d8 Do not use C++11 unicode escape in unittest.
452e2b2 Merge pull request #1353 from keveman/master
cf828de Linking the cpp implementation extension statically with libprotobuf
93811ca Do not let windows.h define min/max macros
3b6df06 Allow bigobj for map_unittest
9d7a172 Merge pull request #1377 from jskeet/remove-duplicate-tests
a293180 Merge pull request #1378 from thomasvl/manual_stream_parsing_helpers
331cee5 Add -position and -isAtEnd for use when manually parsing input streams.
46e088e Remove duplicate test cases.
099ff1e Merge pull request #1369 from jskeet/tools-nuspec
203bb5e Fix re-definition issue of winsock.h and winsock2.h
1bf446c Disable sign-compare warning.
7b1cbbd Fix signed-compare warning.
012ac9a revert unexpected change for py26
bc1f2e7 Fix WIN32 build for map_test.
cbfd9d4 Remove export macros for classes nested in a template class.
81eb84c Merge pull request #1371 from keveman/oversize_protos
1283625 Added an API to allow oversize protos when using C++ extension in Python
5805c2d Fix javanano package
fc7eeda Fix json_format.py in py26
5c63266 Merge pull request #1366 from xyzzyz/int128_ostream
94aa50f Fix breakage of referring to table_ in static func
9e7fa06 Temporarily disable begin is fast test.
dfd4760 Remove duplicate line
ca0461c Introduce a new nuget package, Google.Protobuf.Tools, basically to contain protoc on multiple platforms.
a16c8a5 Merge pull request #1362 from jskeet/tweak_json_name
955841e Replace #include <iostream> with #include <ostream>
0de06f5 Merge branch 'master' of github.com:google/protobuf
3b3c8ab Integrate google internal changes.
a25e996 Merge pull request #1360 from pherl/master
34d0cc2 Merge pull request #1295 from haberman/docker
71e8dca Refactoring of FieldDescriptor
261fde1 Merge pull request #1326 from the-alien/csharp_json_name
a15b916 Merge branch 'master' into docker
e164f10 Use the T() instead of NULL for the default value.
af34538 Merge branch 'master' of https://github.com/google/protobuf into csharp_json_name
6f8dd21 Code review fixes
261ee02 Merge pull request #1358 from thomasvl/travis_tweaks
8d47d78 Mark iOS tests as able to fail.
9240acd Merge pull request #1350 from thomasvl/over_release
3f91744 The message was autoreleased, the -releases are an over release.
8126912 Merge pull request #1345 from smparkes/smparkes/well-known-protos
d5a5732 export well known protos
34eeeff Merge pull request #1344 from topillar/patch-1
64dfb5f Update coded_stream.h
698fa8e Merge pull request #1335 from pradeepg26/master
9209136 Merge pull request #1339 from thomasvl/delay_dispatch_semaphore_creation
bd41a39 Only create the readonlySemaphore on demand.
4d98369 Allow custom URLs for Any in JsonFormat
cab5eae Replace ancient m4/acx_pthread.m4 with m4/ax_pthread.m4
0d32ab3 csharp: add support for the json_name option
5e93384 Merge pull request #1325 from thomasvl/shrink_overhead
79a23c4 Shrink ObjC overhead (generated size and some runtime sizes)
ca3dc15 Merge pull request #1318 from smparkes/smparkes/grpc
44fdead Merge pull request #1291 from sergiocampama/devel
9aea0ef Merge pull request #1312 from petewarden/master
a9244ca add java/util support based on java/util/pom.xml
c71f184 Merge pull request #1278 from smparkes/master
dfaf1aa Merge pull request #1317 from benvanik/patch-1
58f0764 Fixing compilation error when building with emscripten.
ea18866 pass correct args to protoc for java wellknown protos when used as an external repository
bc2d6c2 Merge remote-tracking branch 'upstream/master'
f0c1a86 Added iOS settings to Bazel build
48ebb29 Merge pull request #1299 from tatraian/master
e2fb1d9 Comment has been added to fix (issue #1266)
a8db268 Merge pull request #1309 from thomasvl/leading_special_prop_names
1bf4b38 Fix up handing of fields with leading names that should be all caps.
3dd3238 Merge pull request #1306 from silviulica/master
4573edb Update version to 3.0.0b2.post2
6a8815b Merge pull request #1304 from thomasvl/headerdocs
36650a0 HeaderDoc support in the library and generated sources
f2d3408 Merge pull request #1301 from avgweb/master
ad2d775 Replace StringBuilder with TextWriter in JsonFormatter
9242d9b Merge pull request #1298 from craigcitro/fix_setup
3cc35ad Fix compiling clang/libc++ builds. (Issue: #1266)
0e7c0c2 Add back the namespace_packages arg in setup.py.
e70f925 Merge pull request #1139 from haberman/rubyjsoncamel
67c727c Rearranged and commented files for running under Jenkins.
37663e8 Merge pull request #1292 from haberman/ruby-allow-descriptor
35227b4 Removed the generated Ruby file from Makefile.am.
7d793c1 Disable attempt to use ccache for docker build.
2bda98f Properly report C++ build time.
1ee0fda Use a local Maven repository to avoid network fetches during tests.
513875d Generate well-known types in Ruby extension and prune unneeded proto2 dependencies.
b5a35b4 Adds more information to Objective C error when the expected objc_class_prefix option is missing.
2f3f1de Make Java copy into separate directories so the tests can run concurrently.
38bc155 Added code to generate XML output file for more granular results.
ffc8118 Added Ruby 2.1, Oracle Java, and C#.
78f9b68 Upgrade Python packages using pip.
f6153b5 Work around tox bug.
b28b3f6 Configure ccache directory.
d08c39c Put Maven in batch mode to avoid spamming the logs.
483533d Install Python deps in Docker image.
0b931bc Add another test (javanano), but run it in parallel.
0f8c25d Properly add JDK deps in the Docker image.
738393b Try running multiple tests in a row.
d33e93b Added ccache support.
57be1d7 Added some initial shell scripts and docker file.
7810589 Merge pull request #1260 from legrosbuffle/master
584233b Merge pull request #1287 from jskeet/fix-typo
f222a9a Fix copy/paste typo in CodedInputStreamTest
52f62e3 Merge pull request #1274 from murgatroid99/node_relative_requires
9f775a8 Merge pull request #1286 from jskeet/idisposable
c0cf71b Implement IDisposable for CodedInputStream and CodedOutputStream
60a0d41 Merge pull request #1233 from davidzchen/python-path
985c968 Remove hack for building Python support with Bazel.
fb714b3 Merge pull request #1275 from keveman/grpc_support
f5c7363 Fixed grpc C++ plugin support.
c9f8a1b Moved CommonJS-specific files into commonjs directory
a862b6b Fix CommonJS relative require generation, and test it
cc775f7 Merge pull request #1259 from silviulica/master
fc51bdc Merge pull request #1268 from keveman/grpc_support
cb39204 Updated library generation with iOS options
f0966a7 Added grpc plugin support to cc_proto_library.
8f67b16 Merge pull request #1267 from jskeet/vs2015
513a8a6 Merge pull request #804 from bsilver8192/master
4237146 Require VS2015 in the solution file
32daf51 Merge pull request #1215 from haberman/commonjs
24c5424 Added a bit more to README.md, and allowed custom PROTOC var in tests.
894c4d6 Merge pull request #1257 from thomasvl/objc_generics
b3d802d Make cpp generated enum constants constexpr when Options::proto_h is specified.
786f80f Add a modified patch from craigcitro@ to handle namespace sharing.
c003abb Merge pull request #1240 from jskeet/validate_group
4ab9186 Merge pull request #1258 from haberman/releasenotes
81e75c1 Some fixes for the most recent release notes.
f654d49 Updated upb from latest changes.
2480acb Support ObjC Generic Collections
78da666 Changed Ruby to properly camelCase its JSON by default.
907ad4a Properly camelCase when translating to CommonJS.
29d58d3 Removed unused directives from tests that aren't run under CommonJS.
c348af2 Addressed more code review comments.
7726cd2 Integrate review comments.
5195b7f Greatly expanded README.md.
59ea500 Use "node" as binary instead of "nodejs".
35298f9 Fixed definition of extensions, and added CommonJS tests to Travis.
77af5d0 Fixed nested message scopes for CommonJS.
d6a186a Added some documentation in comments.
9e60036 Moved CommonJS-specific files to commonjs/.
e9f31ee CommonJS tests are now passing.
55cc3aa WIP.
9ab11c6 Merge pull request #1255 from thomasvl/mark_os_x_python_cpp_failing
e0dd14c List python_cpp as failing on OS X
507213b Merge pull request #1254 from thomasvl/disable_xctool_updates
8c78450 Disable the xctool updates
abc09f7 Merge pull request #1239 from jskeet/call_generate_protos
c40f8c1 Merge pull request #1229 from keveman/unlimited_binary_proto
61e8e21 Merge pull request #1241 from jskeet/more-merge-wrapper-tests
d41db75 Merge pull request #260 from ejsd1989/issue-#242
8fc045d Merge pull request #1224 from google/rubysentinel
99a3e30 Added PROTOBUF_PYTHON_ALLOW_OVERSIZE_PROTOS macro and setting it when --allow_oversize_protos=true is passed to bazel build. When this macro is set, SetTotalBytesLimit is called to remove the 64MB limit on binary protos when during ParseFromString.
7cf5b81 Merge pull request #1247 from thomasvl/xctool_plain_output
efca368 Move the xctool use of -reporter into a common spot and always use "plain" to get more readable logs on travis.
ee819ea Merge pull request #1245 from thomasvl/tweak_xctool_ios_run
30e645b Tweak the xctool run for iOS tests to try and sort out flake
7d1cc10 Merge pull request #1244 from thomasvl/bump_xcode_version
1324119 Bump up travis to Xcode 7.2
0262e04 Add more tests around merging wrappers
9bdc848 Validate that end-group tags match their corresponding start-group tags
957e877 Generate C# code whenever descriptor.proto changes
69ac430 Removed 'optional' from proto3 syntax file.
fd1c289 Adding missing generic gcc 64-bit atomicops.
ff156e4 Add atomics support for 32-bit PPC.
914605c Removal of null check
a1c5e45 Removal of null check

Change-Id: Id88028efe92b49fd68a02de01e4f991765798c40
git-subtree-dir: third_party/protobuf
git-subtree-split: 48cb18e5c419ddd23d9badcfe4e9df7bde1979b2
diff --git a/src/google/protobuf/compiler/annotation_test_util.cc b/src/google/protobuf/compiler/annotation_test_util.cc
new file mode 100644
index 0000000..a0530b9
--- /dev/null
+++ b/src/google/protobuf/compiler/annotation_test_util.cc
@@ -0,0 +1,166 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/compiler/annotation_test_util.h>
+
+#include <memory>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/descriptor.pb.h>
+
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace annotation_test_util {
+namespace {
+
+// A CodeGenerator that captures the FileDescriptor it's passed as a
+// FileDescriptorProto.
+class DescriptorCapturingGenerator : public CodeGenerator {
+ public:
+  // Does not own file; file must outlive the Generator.
+  explicit DescriptorCapturingGenerator(FileDescriptorProto* file)
+      : file_(file) {}
+
+  virtual bool Generate(const FileDescriptor* file, const string& parameter,
+                        GeneratorContext* context, string* error) const {
+    file->CopyTo(file_);
+    return true;
+  }
+
+ private:
+  FileDescriptorProto* file_;
+};
+}  // namespace
+
+void AddFile(const string& filename, const string& data) {
+  GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/" + filename, data,
+                             true));
+}
+
+bool RunProtoCompiler(const string& filename,
+                      const string& plugin_specific_args,
+                      CommandLineInterface* cli, FileDescriptorProto* file) {
+  cli->SetInputsAreProtoPathRelative(true);
+
+  DescriptorCapturingGenerator capturing_generator(file);
+  cli->RegisterGenerator("--capture_out", &capturing_generator, "");
+
+  string proto_path = "-I" + TestTempDir();
+  string capture_out = "--capture_out=" + TestTempDir();
+
+  const char* argv[] = {"protoc", proto_path.c_str(),
+                        plugin_specific_args.c_str(), capture_out.c_str(),
+                        filename.c_str()};
+
+  return cli->Run(5, argv) == 0;
+}
+
+bool DecodeMetadata(const string& path, GeneratedCodeInfo* info) {
+  string data;
+  GOOGLE_CHECK_OK(File::GetContents(path, &data, true));
+  io::ArrayInputStream input(data.data(), data.size());
+  return info->ParseFromZeroCopyStream(&input);
+}
+
+void FindAnnotationsOnPath(
+    const GeneratedCodeInfo& info, const string& source_file,
+    const std::vector<int>& path,
+    std::vector<const GeneratedCodeInfo::Annotation*>* annotations) {
+  for (int i = 0; i < info.annotation_size(); ++i) {
+    const GeneratedCodeInfo::Annotation* annotation = &info.annotation(i);
+    if (annotation->source_file() != source_file ||
+        annotation->path_size() != path.size()) {
+      continue;
+    }
+    int node = 0;
+    for (; node < path.size(); ++node) {
+      if (annotation->path(node) != path[node]) {
+        break;
+      }
+    }
+    if (node == path.size()) {
+      annotations->push_back(annotation);
+    }
+  }
+}
+
+const GeneratedCodeInfo::Annotation* FindAnnotationOnPath(
+    const GeneratedCodeInfo& info, const string& source_file,
+    const std::vector<int>& path) {
+  std::vector<const GeneratedCodeInfo::Annotation*> annotations;
+  FindAnnotationsOnPath(info, source_file, path, &annotations);
+  if (annotations.empty()) {
+    return NULL;
+  }
+  return annotations[0];
+}
+
+bool AtLeastOneAnnotationMatchesSubstring(
+    const string& file_content,
+    const std::vector<const GeneratedCodeInfo::Annotation*>& annotations,
+    const string& expected_text) {
+  for (std::vector<const GeneratedCodeInfo::Annotation*>::const_iterator
+           i = annotations.begin(),
+           e = annotations.end();
+       i != e; ++i) {
+    const GeneratedCodeInfo::Annotation* annotation = *i;
+    uint32 begin = annotation->begin();
+    uint32 end = annotation->end();
+    if (end < begin || end > file_content.size()) {
+      return false;
+    }
+    if (file_content.substr(begin, end - begin) == expected_text) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool AnnotationMatchesSubstring(const string& file_content,
+                                const GeneratedCodeInfo::Annotation* annotation,
+                                const string& expected_text) {
+  std::vector<const GeneratedCodeInfo::Annotation*> annotations;
+  annotations.push_back(annotation);
+  return AtLeastOneAnnotationMatchesSubstring(file_content, annotations,
+                                              expected_text);
+}
+}  // namespace annotation_test_util
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/annotation_test_util.h b/src/google/protobuf/compiler/annotation_test_util.h
new file mode 100644
index 0000000..90bd88b
--- /dev/null
+++ b/src/google/protobuf/compiler/annotation_test_util.h
@@ -0,0 +1,114 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__
+#define GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__
+
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+// Utilities that assist in writing tests for generator annotations.
+// See java/internal/annotation_unittest.cc for an example.
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace annotation_test_util {
+
+// Struct that contains the file generated from a .proto file and its
+// GeneratedCodeInfo. For example, the Java generator will fill this struct
+// (for some 'foo.proto') with:
+//   file_path = "Foo.java"
+//   file_content = content of Foo.java
+//   file_info = parsed content of Foo.java.pb.meta
+struct ExpectedOutput {
+  string file_path;
+  string file_content;
+  GeneratedCodeInfo file_info;
+  explicit ExpectedOutput(const string& file_path) : file_path(file_path) {}
+};
+
+// Creates a file with name `filename` and content `data` in temp test
+// directory.
+void AddFile(const string& filename, const string& data);
+
+// Runs proto compiler. Captures proto file structrue in FileDescriptorProto.
+// Files will be generated in TestTempDir() folder. Callers of this
+// function must read generated files themselves.
+//
+// filename: source .proto file used to generate code.
+// plugin_specific_args: command line arguments specific to current generator.
+//     For Java, this value might be "--java_out=annotate_code:test_temp_dir"
+// cli: instance of command line interface to run generator. See Java's
+//     annotation_unittest.cc for an example of how to initialize it.
+// file: output parameter, will be set to the descriptor of the proto file
+//     specified in filename.
+bool RunProtoCompiler(const string& filename,
+                      const string& plugin_specific_args,
+                      CommandLineInterface* cli, FileDescriptorProto* file);
+
+bool DecodeMetadata(const string& path, GeneratedCodeInfo* info);
+
+// Finds all of the Annotations for a given source file and path.
+// See Location.path in http://google/protobuf/descriptor.proto for
+// explanation of what path vector is.
+void FindAnnotationsOnPath(
+    const GeneratedCodeInfo& info, const string& source_file,
+    const std::vector<int>& path,
+    std::vector<const GeneratedCodeInfo::Annotation*>* annotations);
+
+// Finds the Annotation for a given source file and path (or returns null if it
+// couldn't). If there are several annotations for given path, returns the first
+// one. See Location.path in
+// http://google/protobuf/descriptor.proto for explanation of what path
+// vector is.
+const GeneratedCodeInfo::Annotation* FindAnnotationOnPath(
+    const GeneratedCodeInfo& info, const string& source_file,
+    const std::vector<int>& path);
+
+// Returns true if at least one of the provided annotations covers a given
+// substring in file_content.
+bool AtLeastOneAnnotationMatchesSubstring(
+    const string& file_content,
+    const std::vector<const GeneratedCodeInfo::Annotation*>& annotations,
+    const string& expected_text);
+
+// Returns true if the provided annotation covers a given substring in
+// file_content.
+bool AnnotationMatchesSubstring(const string& file_content,
+                                const GeneratedCodeInfo::Annotation* annotation,
+                                const string& expected_text);
+
+}  // namespace annotation_test_util
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__
diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc
index 473eb4e..aaabd91 100644
--- a/src/google/protobuf/compiler/code_generator.cc
+++ b/src/google/protobuf/compiler/code_generator.cc
@@ -36,6 +36,8 @@
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/plugin.pb.h>
+#include <google/protobuf/descriptor.h>
 #include <google/protobuf/stubs/strutil.h>
 
 namespace google {
@@ -43,6 +45,33 @@
 namespace compiler {
 
 CodeGenerator::~CodeGenerator() {}
+
+bool CodeGenerator::GenerateAll(
+    const std::vector<const FileDescriptor*>& files,
+    const string& parameter,
+    GeneratorContext* generator_context,
+    string* error) const {
+  // Default implemenation is just to call the per file method, and prefix any
+  // error string with the file to provide context.
+  bool succeeded = true;
+  for (int i = 0; i < files.size(); i++) {
+    const FileDescriptor* file = files[i];
+    succeeded = Generate(file, parameter, generator_context, error);
+    if (!succeeded && error && error->empty()) {
+      *error = "Code generator returned false but provided no error "
+               "description.";
+    }
+    if (error && !error->empty()) {
+      *error = file->name() + ": " + *error;
+      break;
+    }
+    if (!succeeded) {
+      break;
+    }
+  }
+  return succeeded;
+}
+
 GeneratorContext::~GeneratorContext() {}
 
 io::ZeroCopyOutputStream*
@@ -57,18 +86,25 @@
 }
 
 void GeneratorContext::ListParsedFiles(
-    vector<const FileDescriptor*>* output) {
+    std::vector<const FileDescriptor*>* output) {
   GOOGLE_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles";
 }
 
+void GeneratorContext::GetCompilerVersion(Version* version) const {
+  version->set_major(GOOGLE_PROTOBUF_VERSION / 1000000);
+  version->set_minor(GOOGLE_PROTOBUF_VERSION / 1000 % 1000);
+  version->set_patch(GOOGLE_PROTOBUF_VERSION % 1000);
+  version->set_suffix(GOOGLE_PROTOBUF_VERSION_SUFFIX);
+}
+
 // Parses a set of comma-delimited name/value pairs.
 void ParseGeneratorParameter(const string& text,
-                             vector<pair<string, string> >* output) {
-  vector<string> parts = Split(text, ",", true);
+                             std::vector<std::pair<string, string> >* output) {
+  std::vector<string> parts = Split(text, ",", true);
 
   for (int i = 0; i < parts.size(); i++) {
     string::size_type equals_pos = parts[i].find_first_of('=');
-    pair<string, string> value;
+    std::pair<string, string> value;
     if (equals_pos == string::npos) {
       value.first = parts[i];
       value.second = "";
diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h
index b989f15..4c2b3ee 100644
--- a/src/google/protobuf/compiler/code_generator.h
+++ b/src/google/protobuf/compiler/code_generator.h
@@ -50,6 +50,9 @@
 class FileDescriptor;
 
 namespace compiler {
+class AccessInfoMap;
+
+class Version;
 
 // Defined in this file.
 class CodeGenerator;
@@ -66,11 +69,11 @@
   // Generates code for the given proto file, generating one or more files in
   // the given output directory.
   //
-  // A parameter to be passed to the generator can be specified on the
-  // command line.  This is intended to be used by Java and similar languages
-  // to specify which specific class from the proto file is to be generated,
-  // though it could have other uses as well.  It is empty if no parameter was
-  // given.
+  // A parameter to be passed to the generator can be specified on the command
+  // line. This is intended to be used to pass generator specific parameters.
+  // It is empty if no parameter was given. ParseGeneratorParameter (below),
+  // can be used to accept multiple parameters within the single parameter
+  // command line flag.
   //
   // Returns true if successful.  Otherwise, sets *error to a description of
   // the problem (e.g. "invalid parameter") and returns false.
@@ -79,36 +82,27 @@
                         GeneratorContext* generator_context,
                         string* error) const = 0;
 
-  // Generates code for all given proto files, generating one or more files in
-  // the given output directory.
+  // Generates code for all given proto files.
   //
-  // This method should be called instead of |Generate()| when
-  // |HasGenerateAll()| returns |true|. It is used to emulate legacy semantics
-  // when more than one `.proto` file is specified on one compiler invocation.
-  //
-  // WARNING: Please do not use unless legacy semantics force the code generator
-  // to produce a single output file for all input files, or otherwise require
-  // an examination of all input files first. The canonical code generator
-  // design produces one output file per input .proto file, and we do not wish
-  // to encourage alternate designs.
+  // WARNING: The canonical code generator design produces one or two output
+  // files per input .proto file, and we do not wish to encourage alternate
+  // designs.
   //
   // A parameter is given as passed on the command line, as in |Generate()|
   // above.
   //
   // Returns true if successful.  Otherwise, sets *error to a description of
   // the problem (e.g. "invalid parameter") and returns false.
-  virtual bool GenerateAll(const vector<const FileDescriptor*>& files,
+  virtual bool GenerateAll(const std::vector<const FileDescriptor*>& files,
                            const string& parameter,
                            GeneratorContext* generator_context,
-                           string* error) const {
-    *error = "Unimplemented GenerateAll() method.";
-    return false;
-  }
+                           string* error) const;
 
-  // Returns true if the code generator expects to receive all FileDescriptors
-  // at once (via |GenerateAll()|), rather than one at a time (via
-  // |Generate()|). This is required to implement legacy semantics.
-  virtual bool HasGenerateAll() const { return false; }
+  // This is no longer used, but this class is part of the opensource protobuf
+  // library, so it has to remain to keep vtables the same for the current
+  // version of the library. When protobufs does a api breaking change, the
+  // method can be removed.
+  virtual bool HasGenerateAll() const { return true; }
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodeGenerator);
@@ -120,7 +114,8 @@
 // runs.
 class LIBPROTOC_EXPORT GeneratorContext {
  public:
-  inline GeneratorContext() {}
+  inline GeneratorContext() {
+  }
   virtual ~GeneratorContext();
 
   // Opens the given file, truncating it if it exists, and returns a
@@ -150,7 +145,12 @@
   // 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);
+  virtual void ListParsedFiles(std::vector<const FileDescriptor*>* output);
+
+  // Retrieves the version number of the protocol compiler associated with
+  // this GeneratorContext.
+  virtual void GetCompilerVersion(Version* version) const;
+
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorContext);
@@ -166,8 +166,8 @@
 //   "foo=bar,baz,qux=corge"
 // parses to the pairs:
 //   ("foo", "bar"), ("baz", ""), ("qux", "corge")
-extern void ParseGeneratorParameter(const string&,
-            vector<pair<string, string> >*);
+LIBPROTOC_EXPORT void ParseGeneratorParameter(
+    const string&, std::vector<std::pair<string, string> >*);
 
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 3a816b0..8380367 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -33,75 +33,61 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
 #include <google/protobuf/compiler/command_line_interface.h>
+
+
 #include <google/protobuf/stubs/platform_macros.h>
 
 #include <stdio.h>
 #include <sys/types.h>
+#ifdef major
+#undef major
+#endif
+#ifdef minor
+#undef minor
+#endif
 #include <sys/stat.h>
 #include <fcntl.h>
-#ifdef _MSC_VER
-#include <io.h>
-#include <direct.h>
-#else
+#ifndef _MSC_VER
 #include <unistd.h>
 #endif
 #include <errno.h>
+#include <fstream>
 #include <iostream>
 #include <ctype.h>
 
-#ifdef GOOGLE_PROTOBUF_ARCH_SPARC 
 #include <limits.h> //For PATH_MAX
-#endif
 
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 
 #ifdef __APPLE__
 #include <mach-o/dyld.h>
 #endif
 
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/compiler/importer.h>
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/plugin.pb.h>
 #include <google/protobuf/compiler/subprocess.h>
 #include <google/protobuf/compiler/zip_writer.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/text_format.h>
-#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/compiler/plugin.pb.h>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/importer.h>
 #include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/text_format.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.h>
+#include <google/protobuf/stubs/io_win32.h>
 
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 
-#if defined(_WIN32)
-#define mkdir(name, mode) mkdir(name)
-#ifndef W_OK
-#define W_OK 02  // not defined by MSVC for whatever reason
-#endif
-#ifndef F_OK
-#define F_OK 00  // not defined by MSVC for whatever reason
-#endif
-#ifndef STDIN_FILENO
-#define STDIN_FILENO 0
-#endif
-#ifndef STDOUT_FILENO
-#define STDOUT_FILENO 1
-#endif
-#endif
-
 #ifndef O_BINARY
 #ifdef _O_BINARY
 #define O_BINARY _O_BINARY
@@ -111,12 +97,20 @@
 #endif
 
 namespace {
-#if defined(_WIN32) && !defined(__CYGWIN__)
-static const char* kPathSeparator = ";";
-#else
-static const char* kPathSeparator = ":";
+#if defined(_WIN32)
+// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
+// them like we do below.
+using google::protobuf::internal::win32::access;
+using google::protobuf::internal::win32::close;
+using google::protobuf::internal::win32::mkdir;
+using google::protobuf::internal::win32::open;
+using google::protobuf::internal::win32::setmode;
+using google::protobuf::internal::win32::write;
 #endif
 
+static const char* kDefaultDirectDependenciesViolationMsg =
+    "File is imported but not declared in --direct_dependencies: %s";
+
 // Returns true if the text looks like a Windows-style absolute path, starting
 // with a drive letter.  Example:  "C:\foo".  TODO(kenton):  Share this with
 // copy in importer.cc?
@@ -133,9 +127,9 @@
 
 void SetFdToTextMode(int fd) {
 #ifdef _WIN32
-  if (_setmode(fd, _O_TEXT) == -1) {
+  if (setmode(fd, _O_TEXT) == -1) {
     // This should never happen, I think.
-    GOOGLE_LOG(WARNING) << "_setmode(" << fd << ", _O_TEXT): " << strerror(errno);
+    GOOGLE_LOG(WARNING) << "setmode(" << fd << ", _O_TEXT): " << strerror(errno);
   }
 #endif
   // (Text and binary are the same on non-Windows platforms.)
@@ -143,9 +137,9 @@
 
 void SetFdToBinaryMode(int fd) {
 #ifdef _WIN32
-  if (_setmode(fd, _O_BINARY) == -1) {
+  if (setmode(fd, _O_BINARY) == -1) {
     // This should never happen, I think.
-    GOOGLE_LOG(WARNING) << "_setmode(" << fd << ", _O_BINARY): " << strerror(errno);
+    GOOGLE_LOG(WARNING) << "setmode(" << fd << ", _O_BINARY): " << strerror(errno);
   }
 #endif
   // (Text and binary are the same on non-Windows platforms.)
@@ -174,7 +168,7 @@
 // directories listed in |filename|.
 bool TryCreateParentDirectory(const string& prefix, const string& filename) {
   // Recursively create parent directories to the output file.
-  vector<string> parts = Split(filename, "/", true);
+  std::vector<string> parts = Split(filename, "/", true);
   string path_so_far = prefix;
   for (int i = 0; i < parts.size() - 1; i++) {
     path_so_far += parts[i];
@@ -226,9 +220,9 @@
   return access(file_path.c_str(), F_OK) != -1;
 }
 
-// Add the paths where google/protobuf/descritor.proto and other well-known
+// Add the paths where google/protobuf/descriptor.proto and other well-known
 // type protos are installed.
-void AddDefaultProtoPaths(vector<pair<string, string> >* paths) {
+void AddDefaultProtoPaths(std::vector<std::pair<string, string> >* paths) {
   // TODO(xiaofeng): The code currently only checks relative paths of where
   // the protoc binary is installed. We probably should make it handle more
   // cases than that.
@@ -244,12 +238,12 @@
   path = path.substr(0, pos);
   // Check the binary's directory.
   if (IsInstalledProtoPath(path)) {
-    paths->push_back(pair<string, string>("", path));
+    paths->push_back(std::pair<string, string>("", path));
     return;
   }
   // Check if there is an include subdirectory.
   if (IsInstalledProtoPath(path + "/include")) {
-    paths->push_back(pair<string, string>("", path + "/include"));
+    paths->push_back(std::pair<string, string>("", path + "/include"));
     return;
   }
   // Check if the upper level directory has an "include" subdirectory.
@@ -259,23 +253,33 @@
   }
   path = path.substr(0, pos);
   if (IsInstalledProtoPath(path + "/include")) {
-    paths->push_back(pair<string, string>("", path + "/include"));
+    paths->push_back(std::pair<string, string>("", path + "/include"));
     return;
   }
 }
+
+string PluginName(const string& plugin_prefix, const string& directive) {
+  // Assuming the directive starts with "--" and ends with "_out" or "_opt",
+  // strip the "--" and "_out/_opt" and add the plugin prefix.
+  return plugin_prefix + "gen-" + directive.substr(2, directive.size() - 6);
+}
+
 }  // namespace
 
 // A MultiFileErrorCollector that prints errors to stderr.
-class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector,
-                                           public io::ErrorCollector {
+class CommandLineInterface::ErrorPrinter
+    : public MultiFileErrorCollector,
+      public io::ErrorCollector,
+      public DescriptorPool::ErrorCollector {
  public:
   ErrorPrinter(ErrorFormat format, DiskSourceTree *tree = NULL)
-    : format_(format), tree_(tree) {}
+    : format_(format), tree_(tree), found_errors_(false) {}
   ~ErrorPrinter() {}
 
   // implements MultiFileErrorCollector ------------------------------
   void AddError(const string& filename, int line, int column,
                 const string& message) {
+    found_errors_ = true;
     AddErrorOrWarning(filename, line, column, message, "error", std::cerr);
   }
 
@@ -293,10 +297,31 @@
     AddErrorOrWarning("input", line, column, message, "warning", std::clog);
   }
 
+  // implements DescriptorPool::ErrorCollector-------------------------
+  void AddError(
+      const string& filename,
+      const string& element_name,
+      const Message* descriptor,
+      ErrorLocation location,
+      const string& message) {
+    AddErrorOrWarning(filename, -1, -1, message, "error", std::cerr);
+  }
+
+  void AddWarning(
+      const string& filename,
+      const string& element_name,
+      const Message* descriptor,
+      ErrorLocation location,
+      const string& message) {
+    AddErrorOrWarning(filename, -1, -1, message, "warning", std::clog);
+  }
+
+  bool FoundErrors() const { return found_errors_; }
+
  private:
-  void AddErrorOrWarning(
-      const string& filename, int line, int column,
-      const string& message, const string& type, ostream& out) {
+  void AddErrorOrWarning(const string& filename, int line, int column,
+                         const string& message, const string& type,
+                         std::ostream& out) {
     // Print full path when running under MSVS
     string dfile;
     if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS &&
@@ -331,6 +356,7 @@
 
   const ErrorFormat format_;
   DiskSourceTree *tree_;
+  bool found_errors_;
 };
 
 // -------------------------------------------------------------------
@@ -339,7 +365,7 @@
 // them all to disk on demand.
 class CommandLineInterface::GeneratorContextImpl : public GeneratorContext {
  public:
-  GeneratorContextImpl(const vector<const FileDescriptor*>& parsed_files);
+  GeneratorContextImpl(const std::vector<const FileDescriptor*>& parsed_files);
   ~GeneratorContextImpl();
 
   // Write all files in the directory to disk at the given output location,
@@ -355,14 +381,14 @@
   void AddJarManifest();
 
   // Get name of all output files.
-  void GetOutputFilenames(vector<string>* output_filenames);
+  void GetOutputFilenames(std::vector<string>* output_filenames);
 
   // implements GeneratorContext --------------------------------------
   io::ZeroCopyOutputStream* Open(const string& filename);
   io::ZeroCopyOutputStream* OpenForAppend(const string& filename);
   io::ZeroCopyOutputStream* OpenForInsert(
       const string& filename, const string& insertion_point);
-  void ListParsedFiles(vector<const FileDescriptor*>* output) {
+  void ListParsedFiles(std::vector<const FileDescriptor*>* output) {
     *output = parsed_files_;
   }
 
@@ -371,8 +397,8 @@
 
   // 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_;
+  std::map<string, string*> files_;
+  const std::vector<const FileDescriptor*>& parsed_files_;
   bool had_error_;
 };
 
@@ -391,6 +417,13 @@
   virtual int64 ByteCount() const           { return inner_->ByteCount();      }
 
  private:
+  // Checks to see if "filename_.meta" exists in directory_; if so, fixes the
+  // offsets in that GeneratedCodeInfo record to reflect bytes inserted in
+  // filename_ at original offset insertion_offset with length insertion_length.
+  // We assume that insertions will not occur within any given annotated span
+  // of text.
+  void UpdateMetadata(size_t insertion_offset, size_t insertion_length);
+
   // Where to insert the string when it's done.
   GeneratorContextImpl* directory_;
   string filename_;
@@ -403,16 +436,15 @@
   bool append_mode_;
 
   // StringOutputStream writing to data_.
-  google::protobuf::scoped_ptr<io::StringOutputStream> inner_;
+  std::unique_ptr<io::StringOutputStream> inner_;
 };
 
 // -------------------------------------------------------------------
 
 CommandLineInterface::GeneratorContextImpl::GeneratorContextImpl(
-    const vector<const FileDescriptor*>& parsed_files)
+    const std::vector<const FileDescriptor*>& parsed_files)
     : parsed_files_(parsed_files),
-      had_error_(false) {
-}
+      had_error_(false) {}
 
 CommandLineInterface::GeneratorContextImpl::~GeneratorContextImpl() {
   STLDeleteValues(&files_);
@@ -428,7 +460,7 @@
     return false;
   }
 
-  for (map<string, string*>::const_iterator iter = files_.begin();
+  for (std::map<string, string*>::const_iterator iter = files_.begin();
        iter != files_.end(); ++iter) {
     const string& relative_filename = iter->first;
     const char* data = iter->second->data();
@@ -516,7 +548,7 @@
   io::FileOutputStream stream(file_descriptor);
   ZipWriter zip_writer(&stream);
 
-  for (map<string, string*>::const_iterator iter = files_.begin();
+  for (std::map<string, string*>::const_iterator iter = files_.begin();
        iter != files_.end(); ++iter) {
     zip_writer.Write(iter->first, *iter->second);
   }
@@ -545,8 +577,8 @@
 }
 
 void CommandLineInterface::GeneratorContextImpl::GetOutputFilenames(
-    vector<string>* output_filenames) {
-  for (map<string, string*>::iterator iter = files_.begin();
+    std::vector<string>* output_filenames) {
+  for (std::map<string, string*>::iterator iter = files_.begin();
        iter != files_.end(); ++iter) {
     output_filenames->push_back(iter->first);
   }
@@ -588,6 +620,44 @@
       inner_(new io::StringOutputStream(&data_)) {
 }
 
+void CommandLineInterface::MemoryOutputStream::UpdateMetadata(
+    size_t insertion_offset, size_t insertion_length) {
+  std::map<string, string*>::iterator meta_file =
+      directory_->files_.find(filename_ + ".meta");
+  if (meta_file == directory_->files_.end() || !meta_file->second) {
+    // No metadata was recorded for this file.
+    return;
+  }
+  string* encoded_data = meta_file->second;
+  GeneratedCodeInfo metadata;
+  bool is_text_format = false;
+  if (!metadata.ParseFromString(*encoded_data)) {
+    if (!TextFormat::ParseFromString(*encoded_data, &metadata)) {
+      // The metadata is invalid.
+      std::cerr << filename_
+                << ".meta: Could not parse metadata as wire or text format."
+                << std::endl;
+      return;
+    }
+    // Generators that use the public plugin interface emit text-format
+    // metadata (because in the public plugin protocol, file content must be
+    // UTF8-encoded strings).
+    is_text_format = true;
+  }
+  for (int i = 0; i < metadata.annotation_size(); ++i) {
+    GeneratedCodeInfo::Annotation* annotation = metadata.mutable_annotation(i);
+    if (annotation->begin() >= insertion_offset) {
+      annotation->set_begin(annotation->begin() + insertion_length);
+      annotation->set_end(annotation->end() + insertion_length);
+    }
+  }
+  if (is_text_format) {
+    TextFormat::PrintToString(metadata, encoded_data);
+  } else {
+    metadata.SerializeToString(encoded_data);
+  }
+}
+
 CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() {
   // Make sure all data has been written.
   inner_.reset();
@@ -613,7 +683,7 @@
   } else {
     // This was an OpenForInsert().
 
-    // If the data doens't end with a clean line break, add one.
+    // If the data doesn't end with a clean line break, add one.
     if (!data_.empty() && data_[data_.size() - 1] != '\n') {
       data_.push_back('\n');
     }
@@ -640,18 +710,23 @@
       return;
     }
 
-    // Seek backwards to the beginning of the line, which is where we will
-    // insert the data.  Note that this has the effect of pushing the insertion
-    // point down, so the data is inserted before it.  This is intentional
-    // because it means that multiple insertions at the same point will end
-    // up in the expected order in the final output.
-    pos = target->find_last_of('\n', pos);
-    if (pos == string::npos) {
-      // Insertion point is on the first line.
-      pos = 0;
+    if ((pos > 3) && (target->substr(pos - 3, 2) == "/*")) {
+      // Support for inline "/* @@protoc_insertion_point() */"
+      pos = pos - 3;
     } else {
-      // Advance to character after '\n'.
-      ++pos;
+      // Seek backwards to the beginning of the line, which is where we will
+      // insert the data.  Note that this has the effect of pushing the
+      // insertion point down, so the data is inserted before it.  This is
+      // intentional because it means that multiple insertions at the same point
+      // will end up in the expected order in the final output.
+      pos = target->find_last_of('\n', pos);
+      if (pos == string::npos) {
+        // Insertion point is on the first line.
+        pos = 0;
+      } else {
+        // Advance to character after '\n'.
+        ++pos;
+      }
     }
 
     // Extract indent.
@@ -660,6 +735,7 @@
     if (indent_.empty()) {
       // No indent.  This makes things easier.
       target->insert(pos, data_);
+      UpdateMetadata(pos, data_.size());
     } else {
       // Calculate how much space we need.
       int indent_size = 0;
@@ -669,6 +745,7 @@
 
       // Make a hole for it.
       target->insert(pos, data_.size() + indent_size, '\0');
+      UpdateMetadata(pos, data_.size() + indent_size);
 
       // Now copy in the data.
       string::size_type data_pos = 0;
@@ -696,14 +773,22 @@
 
 // ===================================================================
 
+#if defined(_WIN32) && !defined(__CYGWIN__)
+const char* const CommandLineInterface::kPathSeparator = ";";
+#else
+const char* const CommandLineInterface::kPathSeparator = ":";
+#endif
+
 CommandLineInterface::CommandLineInterface()
-  : mode_(MODE_COMPILE),
-    print_mode_(PRINT_NONE),
-    error_format_(ERROR_FORMAT_GCC),
-    imports_in_descriptor_set_(false),
-    source_info_in_descriptor_set_(false),
-    disallow_services_(false),
-    inputs_are_proto_path_relative_(false) {}
+    : mode_(MODE_COMPILE),
+      print_mode_(PRINT_NONE),
+      error_format_(ERROR_FORMAT_GCC),
+      direct_dependencies_explicitly_set_(false),
+      direct_dependencies_violation_msg_(
+          kDefaultDirectDependenciesViolationMsg),
+      imports_in_descriptor_set_(false),
+      source_info_in_descriptor_set_(false),
+      disallow_services_(false) {}
 CommandLineInterface::~CommandLineInterface() {}
 
 void CommandLineInterface::RegisterGenerator(const string& flag_name,
@@ -744,43 +829,41 @@
       break;
   }
 
-  AddDefaultProtoPaths(&proto_path_);
-
-  // Set up the source tree.
-  DiskSourceTree source_tree;
-  for (int i = 0; i < proto_path_.size(); i++) {
-    source_tree.MapPath(proto_path_[i].first, proto_path_[i].second);
-  }
-
-  // Map input files to virtual paths if necessary.
-  if (!inputs_are_proto_path_relative_) {
-    if (!MakeInputsBeProtoPathRelative(&source_tree)) {
+  std::vector<const FileDescriptor*> parsed_files;
+  // null unless descriptor_set_in_names_.empty()
+  std::unique_ptr<DiskSourceTree> disk_source_tree;
+  std::unique_ptr<ErrorPrinter> error_collector;
+  std::unique_ptr<DescriptorPool> descriptor_pool;
+  std::unique_ptr<DescriptorDatabase> descriptor_database;
+  if (descriptor_set_in_names_.empty()) {
+    disk_source_tree.reset(new DiskSourceTree());
+    if (!InitializeDiskSourceTree(disk_source_tree.get())) {
       return 1;
     }
-  }
+    error_collector.reset(
+        new ErrorPrinter(error_format_, disk_source_tree.get()));
 
-  // Allocate the Importer.
-  ErrorPrinter error_collector(error_format_, &source_tree);
-  Importer importer(&source_tree, &error_collector);
+    SourceTreeDescriptorDatabase* database =
+        new SourceTreeDescriptorDatabase(disk_source_tree.get());
+    database->RecordErrorsTo(error_collector.get());
+    descriptor_database.reset(database);
+    descriptor_pool.reset(new DescriptorPool(
+        descriptor_database.get(), database->GetValidationErrorCollector()));
+  } else {
+    error_collector.reset(new ErrorPrinter(error_format_));
 
-  vector<const FileDescriptor*> parsed_files;
-
-  // Parse each file.
-  for (int i = 0; i < input_files_.size(); i++) {
-    // Import the file.
-    importer.AddUnusedImportTrackFile(input_files_[i]);
-    const FileDescriptor* parsed_file = importer.Import(input_files_[i]);
-    importer.ClearUnusedImportTrackFiles();
-    if (parsed_file == NULL) return 1;
-    parsed_files.push_back(parsed_file);
-
-    // Enforce --disallow_services.
-    if (disallow_services_ && parsed_file->service_count() > 0) {
-      cerr << parsed_file->name() << ": This file contains services, but "
-              "--disallow_services was used." << endl;
+    SimpleDescriptorDatabase* database = new SimpleDescriptorDatabase();
+    descriptor_database.reset(database);
+    if (!PopulateSimpleDescriptorDatabase(database)) {
       return 1;
     }
+    descriptor_pool.reset(new DescriptorPool(database, error_collector.get()));
   }
+  descriptor_pool->EnforceWeakDependencies(true);
+  if (!ParseInputFiles(descriptor_pool.get(), &parsed_files)) {
+    return 1;
+  }
+
 
   // We construct a separate GeneratorContext for each output location.  Note
   // that two code generators may output to the same location, in which case
@@ -832,15 +915,16 @@
   }
 
   if (!dependency_out_name_.empty()) {
+    GOOGLE_DCHECK(disk_source_tree.get());
     if (!GenerateDependencyManifestFile(parsed_files, output_directories,
-                                        &source_tree)) {
+                                        disk_source_tree.get())) {
       return 1;
     }
   }
 
   STLDeleteValues(&output_directories);
 
-  if (!descriptor_set_name_.empty()) {
+  if (!descriptor_set_out_name_.empty()) {
     if (!WriteDescriptorSet(parsed_files)) {
       return 1;
     }
@@ -859,12 +943,16 @@
         return 1;
       }
     } else {
-      if (!EncodeOrDecode(importer.pool())) {
+      if (!EncodeOrDecode(descriptor_pool.get())) {
         return 1;
       }
     }
   }
 
+  if (error_collector->FoundErrors()) {
+    return 1;
+  }
+
   if (mode_ == MODE_PRINT) {
     switch (print_mode_) {
       case PRINT_FREE_FIELDS:
@@ -877,7 +965,7 @@
         break;
       case PRINT_NONE:
         GOOGLE_LOG(ERROR) << "If the code reaches here, it usually means a bug of "
-                     "flag parsing in the CommonadLineInterface.";
+                     "flag parsing in the CommandLineInterface.";
         return 1;
 
       // Do not add a default case.
@@ -887,15 +975,125 @@
   return 0;
 }
 
+bool CommandLineInterface::InitializeDiskSourceTree(
+    DiskSourceTree* source_tree) {
+  AddDefaultProtoPaths(&proto_path_);
+
+  // Set up the source tree.
+  for (int i = 0; i < proto_path_.size(); i++) {
+    source_tree->MapPath(proto_path_[i].first, proto_path_[i].second);
+  }
+
+  // Map input files to virtual paths if possible.
+  if (!MakeInputsBeProtoPathRelative(source_tree)) {
+    return false;
+  }
+  return true;
+}
+
+bool CommandLineInterface::PopulateSimpleDescriptorDatabase(
+    SimpleDescriptorDatabase* database) {
+  for (int i = 0; i < descriptor_set_in_names_.size(); i++) {
+    int fd;
+    do {
+      fd = open(descriptor_set_in_names_[i].c_str(), O_RDONLY | O_BINARY);
+    } while (fd < 0 && errno == EINTR);
+    if (fd < 0) {
+      std::cerr << descriptor_set_in_names_[i] << ": "
+                << strerror(ENOENT) << std::endl;
+      return false;
+    }
+
+    FileDescriptorSet file_descriptor_set;
+    bool parsed = file_descriptor_set.ParseFromFileDescriptor(fd);
+    if (close(fd) != 0) {
+      std::cerr << descriptor_set_in_names_[i] << ": close: "
+                << strerror(errno)
+                << std::endl;
+      return false;
+    }
+
+    if (!parsed) {
+      std::cerr << descriptor_set_in_names_[i] << ": Unable to parse."
+                << std::endl;
+      return false;
+    }
+
+    for (int j = 0; j < file_descriptor_set.file_size(); j++) {
+      FileDescriptorProto previously_added_file_descriptor_proto;
+      if (database->FindFileByName(file_descriptor_set.file(j).name(),
+                                   &previously_added_file_descriptor_proto)) {
+        // already present - skip
+        continue;
+      }
+      if (!database->Add(file_descriptor_set.file(j))) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+bool CommandLineInterface::ParseInputFiles(
+    DescriptorPool* descriptor_pool,
+    std::vector<const FileDescriptor*>* parsed_files) {
+
+  // Parse each file.
+  for (int i = 0; i < input_files_.size(); i++) {
+    // Import the file.
+    descriptor_pool->AddUnusedImportTrackFile(input_files_[i]);
+    const FileDescriptor* parsed_file =
+        descriptor_pool->FindFileByName(input_files_[i]);
+    descriptor_pool->ClearUnusedImportTrackFiles();
+    if (parsed_file == NULL) {
+      if (!descriptor_set_in_names_.empty()) {
+        std::cerr << input_files_[i] << ": " << strerror(ENOENT) << std::endl;
+      }
+      return false;
+    }
+    parsed_files->push_back(parsed_file);
+
+    // Enforce --disallow_services.
+    if (disallow_services_ && parsed_file->service_count() > 0) {
+      std::cerr << parsed_file->name() << ": This file contains services, but "
+              "--disallow_services was used." << std::endl;
+      return false;
+    }
+
+    // Enforce --direct_dependencies
+    if (direct_dependencies_explicitly_set_) {
+      bool indirect_imports = false;
+      for (int i = 0; i < parsed_file->dependency_count(); i++) {
+        if (direct_dependencies_.find(parsed_file->dependency(i)->name()) ==
+            direct_dependencies_.end()) {
+          indirect_imports = true;
+          std::cerr << parsed_file->name() << ": "
+                    << StringReplace(direct_dependencies_violation_msg_, "%s",
+                                     parsed_file->dependency(i)->name(),
+                                     true /* replace_all */)
+                    << std::endl;
+        }
+      }
+      if (indirect_imports) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
 void CommandLineInterface::Clear() {
   // Clear all members that are set by Run().  Note that we must not clear
   // members which are set by other methods before Run() is called.
   executable_name_.clear();
   proto_path_.clear();
   input_files_.clear();
+  direct_dependencies_.clear();
+  direct_dependencies_violation_msg_ = kDefaultDirectDependenciesViolationMsg;
   output_directives_.clear();
   codec_type_.clear();
-  descriptor_set_name_.clear();
+  descriptor_set_in_names_.clear();
+  descriptor_set_out_name_.clear();
   dependency_out_name_.clear();
 
   mode_ = MODE_COMPILE;
@@ -903,11 +1101,23 @@
   imports_in_descriptor_set_ = false;
   source_info_in_descriptor_set_ = false;
   disallow_services_ = false;
+  direct_dependencies_explicitly_set_ = false;
 }
 
 bool CommandLineInterface::MakeInputsBeProtoPathRelative(
     DiskSourceTree* source_tree) {
   for (int i = 0; i < input_files_.size(); i++) {
+    // If the input file path is not a physical file path, it must be a virtual
+    // path.
+    if (access(input_files_[i].c_str(), F_OK) < 0) {
+      string disk_file;
+      if (source_tree->VirtualFileToDiskFile(input_files_[i], &disk_file)) {
+        return true;
+      } else {
+        std::cerr << input_files_[i] << ": " << strerror(ENOENT) << std::endl;
+        return false;
+      }
+    }
     string virtual_file, shadowing_disk_file;
     switch (source_tree->DiskFileToVirtualFile(
         input_files_[i], &virtual_file, &shadowing_disk_file)) {
@@ -925,12 +1135,14 @@
       case DiskSourceTree::CANNOT_OPEN:
         std::cerr << input_files_[i] << ": " << strerror(errno) << std::endl;
         return false;
-      case DiskSourceTree::NO_MAPPING:
-        // First check if the file exists at all.
-        if (access(input_files_[i].c_str(), F_OK) < 0) {
-          // File does not even exist.
-          std::cerr << input_files_[i] << ": " << strerror(ENOENT) << std::endl;
+      case DiskSourceTree::NO_MAPPING: {
+        // Try to interpret the path as a virtual path.
+        string disk_file;
+        if (source_tree->VirtualFileToDiskFile(input_files_[i], &disk_file)) {
+          return true;
         } else {
+          // The input file path can't be mapped to any --proto_path and it also
+          // can't be interpreted as a virtual path.
           std::cerr
               << input_files_[i]
               << ": File does not reside within any path "
@@ -939,26 +1151,63 @@
                  "proto_path must be an exact prefix of the .proto file "
                  "names -- protoc is too dumb to figure out when two paths "
                  "(e.g. absolute and relative) are equivalent (it's harder "
-                 "than you think)." << std::endl;
+                 "than you think)."
+              << std::endl;
+          return false;
         }
-        return false;
+      }
     }
   }
 
   return true;
 }
 
+bool CommandLineInterface::ExpandArgumentFile(const string& file,
+                                              std::vector<string>* arguments) {
+  // The argument file is searched in the working directory only. We don't
+  // use the proto import path here.
+  std::ifstream file_stream(file.c_str());
+  if (!file_stream.is_open()) {
+    return false;
+  }
+  string argument;
+  // We don't support any kind of shell expansion right now.
+  while (std::getline(file_stream, argument)) {
+    arguments->push_back(argument);
+  }
+  return true;
+}
+
 CommandLineInterface::ParseArgumentStatus
 CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
   executable_name_ = argv[0];
 
+  std::vector<string> arguments;
+  for (int i = 1; i < argc; ++i) {
+    if (argv[i][0] == '@') {
+      if (!ExpandArgumentFile(argv[i] + 1, &arguments)) {
+        std::cerr << "Failed to open argument file: " << (argv[i] + 1)
+                  << std::endl;
+        return PARSE_ARGUMENT_FAIL;
+      }
+      continue;
+    }
+    arguments.push_back(argv[i]);
+  }
+
+  // if no arguments are given, show help
+  if (arguments.empty()) {
+    PrintHelpText();
+    return PARSE_ARGUMENT_DONE_AND_EXIT;  // Exit without running compiler.
+  }
+
   // Iterate through all arguments and parse them.
-  for (int i = 1; i < argc; i++) {
+  for (int i = 0; i < arguments.size(); ++i) {
     string name, value;
 
-    if (ParseArgument(argv[i], &name, &value)) {
+    if (ParseArgument(arguments[i].c_str(), &name, &value)) {
       // Returned true => Use the next argument as the flag value.
-      if (i + 1 == argc || argv[i+1][0] == '-') {
+      if (i + 1 == arguments.size() || arguments[i + 1][0] == '-') {
         std::cerr << "Missing value for flag: " << name << std::endl;
         if (name == "--decode") {
           std::cerr << "To decode an unknown message, use --decode_raw."
@@ -967,7 +1216,7 @@
         return PARSE_ARGUMENT_FAIL;
       } else {
         ++i;
-        value = argv[i];
+        value = arguments[i];
       }
     }
 
@@ -976,12 +1225,42 @@
       return status;
   }
 
+  // Make sure each plugin option has a matching plugin output.
+  bool foundUnknownPluginOption = false;
+  for (std::map<string, string>::const_iterator i = plugin_parameters_.begin();
+       i != plugin_parameters_.end(); ++i) {
+    if (plugins_.find(i->first) != plugins_.end()) {
+      continue;
+    }
+    bool foundImplicitPlugin = false;
+    for (std::vector<OutputDirective>::const_iterator j = output_directives_.begin();
+         j != output_directives_.end(); ++j) {
+      if (j->generator == NULL) {
+        string plugin_name = PluginName(plugin_prefix_ , j->name);
+        if (plugin_name == i->first) {
+          foundImplicitPlugin = true;
+          break;
+        }
+      }
+    }
+    if (!foundImplicitPlugin) {
+      std::cerr << "Unknown flag: "
+                // strip prefix + "gen-" and add back "_opt"
+                << "--" + i->first.substr(plugin_prefix_.size() + 4) + "_opt"
+                << std::endl;
+      foundUnknownPluginOption = true;
+    }
+  }
+  if (foundUnknownPluginOption) {
+    return PARSE_ARGUMENT_FAIL;
+  }
+
   // If no --proto_path was given, use the current working directory.
   if (proto_path_.empty()) {
     // Don't use make_pair as the old/default standard library on Solaris
     // doesn't support it without explicit template parameters, which are
     // incompatible with C++0x's make_pair.
-    proto_path_.push_back(pair<string, string>("", "."));
+    proto_path_.push_back(std::pair<string, string>("", "."));
   }
 
   // Check some errror cases.
@@ -995,7 +1274,7 @@
     return PARSE_ARGUMENT_FAIL;
   }
   if (mode_ == MODE_COMPILE && output_directives_.empty() &&
-      descriptor_set_name_.empty()) {
+      descriptor_set_out_name_.empty()) {
     std::cerr << "Missing output directives." << std::endl;
     return PARSE_ARGUMENT_FAIL;
   }
@@ -1010,11 +1289,11 @@
         << std::endl;
     return PARSE_ARGUMENT_FAIL;
   }
-  if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) {
+  if (imports_in_descriptor_set_ && descriptor_set_out_name_.empty()) {
     std::cerr << "--include_imports only makes sense when combined with "
                  "--descriptor_set_out." << std::endl;
   }
-  if (source_info_in_descriptor_set_ && descriptor_set_name_.empty()) {
+  if (source_info_in_descriptor_set_ && descriptor_set_out_name_.empty()) {
     std::cerr << "--include_source_info only makes sense when combined with "
                  "--descriptor_set_out." << std::endl;
   }
@@ -1101,11 +1380,19 @@
     input_files_.push_back(value);
 
   } else if (name == "-I" || name == "--proto_path") {
+    if (!descriptor_set_in_names_.empty()) {
+      std::cerr << "Only one of " << name
+                << " and --descriptor_set_in can be specified."
+                << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+
     // Java's -classpath (and some other languages) delimits path components
     // with colons.  Let's accept that syntax too just to make things more
     // intuitive.
-    vector<string> parts = Split(
-        value, kPathSeparator, true);
+    std::vector<string> parts = Split(
+        value, CommandLineInterface::kPathSeparator,
+        true);
 
     for (int i = 0; i < parts.size(); i++) {
       string virtual_path;
@@ -1129,18 +1416,70 @@
 
       // Make sure disk path exists, warn otherwise.
       if (access(disk_path.c_str(), F_OK) < 0) {
-        std::cerr << disk_path << ": warning: directory does not exist."
-                  << std::endl;
+        // Try the original path; it may have just happened to have a '=' in it.
+        if (access(parts[i].c_str(), F_OK) < 0) {
+          std::cerr << disk_path << ": warning: directory does not exist."
+                    << std::endl;
+        } else {
+          virtual_path = "";
+          disk_path = parts[i];
+        }
       }
 
       // Don't use make_pair as the old/default standard library on Solaris
       // doesn't support it without explicit template parameters, which are
       // incompatible with C++0x's make_pair.
-      proto_path_.push_back(pair<string, string>(virtual_path, disk_path));
+      proto_path_.push_back(std::pair<string, string>(virtual_path, disk_path));
     }
 
+  } else if (name == "--direct_dependencies") {
+    if (direct_dependencies_explicitly_set_) {
+      std::cerr << name << " may only be passed once. To specify multiple "
+                           "direct dependencies, pass them all as a single "
+                           "parameter separated by ':'."
+                << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+
+    direct_dependencies_explicitly_set_ = true;
+    std::vector<string> direct = Split(value, ":", true);
+    GOOGLE_DCHECK(direct_dependencies_.empty());
+    direct_dependencies_.insert(direct.begin(), direct.end());
+
+  } else if (name == "--direct_dependencies_violation_msg") {
+    direct_dependencies_violation_msg_ = value;
+
+  } else if (name == "--descriptor_set_in") {
+    if (!descriptor_set_in_names_.empty()) {
+      std::cerr << name << " may only be passed once. To specify multiple "
+                           "descriptor sets, pass them all as a single "
+                           "parameter separated by '"
+                << CommandLineInterface::kPathSeparator << "'."
+                << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    if (value.empty()) {
+      std::cerr << name << " requires a non-empty value." << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    if (!proto_path_.empty()) {
+      std::cerr << "Only one of " << name
+                << " and --proto_path can be specified."
+                << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    if (!dependency_out_name_.empty()) {
+      std::cerr << name << " cannot be used with --dependency_out."
+                << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+
+    descriptor_set_in_names_ = Split(
+        value, CommandLineInterface::kPathSeparator,
+        true);
+
   } else if (name == "-o" || name == "--descriptor_set_out") {
-    if (!descriptor_set_name_.empty()) {
+    if (!descriptor_set_out_name_.empty()) {
       std::cerr << name << " may only be passed once." << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
@@ -1154,7 +1493,7 @@
              "same time." << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
-    descriptor_set_name_ = value;
+    descriptor_set_out_name_ = value;
 
   } else if (name == "--dependency_out") {
     if (!dependency_out_name_.empty()) {
@@ -1165,6 +1504,11 @@
       std::cerr << name << " requires a non-empty value." << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
+    if (!descriptor_set_in_names_.empty()) {
+      std::cerr << name << " cannot be used with --descriptor_set_in."
+                << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
     dependency_out_name_ = value;
 
   } else if (name == "--include_imports") {
@@ -1189,9 +1533,9 @@
     if (!version_info_.empty()) {
       std::cout << version_info_ << std::endl;
     }
-    cout << "libprotoc "
+    std::cout << "libprotoc "
          << protobuf::internal::VersionString(GOOGLE_PROTOBUF_VERSION)
-         << endl;
+         << std::endl;
     return PARSE_ARGUMENT_DONE_AND_EXIT;  // Exit without running compiler.
 
   } else if (name == "--disallow_services") {
@@ -1204,7 +1548,7 @@
                 << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
-    if (!output_directives_.empty() || !descriptor_set_name_.empty()) {
+    if (!output_directives_.empty() || !descriptor_set_out_name_.empty()) {
       std::cerr << "Cannot use " << name
                 << " and generate code or descriptors at the same time."
                 << std::endl;
@@ -1270,7 +1614,7 @@
                 << "other info at the same time." << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
-    if (!output_directives_.empty() || !descriptor_set_name_.empty()) {
+    if (!output_directives_.empty() || !descriptor_set_out_name_.empty()) {
       std::cerr << "Cannot use " << name
                 << " and generate code or descriptors at the same time."
                 << std::endl;
@@ -1286,15 +1630,22 @@
         (plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) {
       // Check if it's a generator option flag.
       generator_info = FindOrNull(generators_by_option_name_, name);
-      if (generator_info == NULL) {
-        std::cerr << "Unknown flag: " << name << std::endl;
-        return PARSE_ARGUMENT_FAIL;
-      } else {
+      if (generator_info != NULL) {
         string* parameters = &generator_parameters_[generator_info->flag_name];
         if (!parameters->empty()) {
           parameters->append(",");
         }
         parameters->append(value);
+      } else if (HasPrefixString(name, "--") && HasSuffixString(name, "_opt")) {
+        string* parameters =
+            &plugin_parameters_[PluginName(plugin_prefix_, name)];
+        if (!parameters->empty()) {
+          parameters->append(",");
+        }
+        parameters->append(value);
+      } else {
+        std::cerr << "Unknown flag: " << name << std::endl;
+        return PARSE_ARGUMENT_FAIL;
       }
     } else {
       // It's an output flag.  Add it to the output directives.
@@ -1332,7 +1683,7 @@
 
 void CommandLineInterface::PrintHelpText() {
   // Sorry for indentation here; line wrapping would be uglier.
-  std::cerr <<
+  std::cout <<
 "Usage: " << executable_name_ << " [OPTION] PROTO_FILES\n"
 "Parse PROTO_FILES and generate output based on the options given:\n"
 "  -IPATH, --proto_path=PATH   Specify the directory in which to search for\n"
@@ -1354,6 +1705,14 @@
 "                              pairs in text format to standard output.  No\n"
 "                              PROTO_FILES should be given when using this\n"
 "                              flag.\n"
+"  --descriptor_set_in=FILES   Specifies a delimited list of FILES\n"
+"                              each containing a FileDescriptorSet (a\n"
+"                              protocol buffer defined in descriptor.proto).\n"
+"                              The FileDescriptor for each of the PROTO_FILES\n"
+"                              provided will be loaded from these\n"
+"                              FileDescriptorSets. If a FileDescriptor\n"
+"                              appears multiple times, the first occurrence\n"
+"                              will be used.\n"
 "  -oFILE,                     Writes a FileDescriptorSet (a protocol buffer,\n"
 "    --descriptor_set_out=FILE defined in descriptor.proto) containing all of\n"
 "                              the input files to FILE.\n"
@@ -1379,7 +1738,7 @@
 "                              occupied fields numbers.\n"
       << std::endl;
   if (!plugin_prefix_.empty()) {
-    std::cerr <<
+    std::cout <<
 "  --plugin=EXECUTABLE         Specifies a plugin executable to use.\n"
 "                              Normally, protoc searches the PATH for\n"
 "                              plugins, but you may specify additional\n"
@@ -1395,14 +1754,28 @@
     // FIXME(kenton):  If the text is long enough it will wrap, which is ugly,
     //   but fixing this nicely (e.g. splitting on spaces) is probably more
     //   trouble than it's worth.
-    std::cerr << "  " << iter->first << "=OUT_DIR "
+    std::cout << "  " << iter->first << "=OUT_DIR "
               << string(19 - iter->first.size(), ' ')  // Spaces for alignment.
               << iter->second.help_text << std::endl;
   }
+  std::cerr <<
+"  @<filename>                 Read options and filenames from file. If a\n"
+"                              relative file path is specified, the file\n"
+"                              will be searched in the working directory.\n"
+"                              The --proto_path option will not affect how\n"
+"                              this argument file is searched. Content of\n"
+"                              the file will be expanded in the position of\n"
+"                              @<filename> as in the argument list. Note\n"
+"                              that shell expansion is not applied to the\n"
+"                              content of the file (i.e., you cannot use\n"
+"                              quotes, wildcards, escapes, commands, etc.).\n"
+"                              Each line corresponds to a single argument,\n"
+"                              even if it contains spaces."
+      << std::endl;
 }
 
 bool CommandLineInterface::GenerateOutput(
-    const vector<const FileDescriptor*>& parsed_files,
+    const std::vector<const FileDescriptor*>& parsed_files,
     const OutputDirective& output_directive,
     GeneratorContext* generator_context) {
   // Call the generator.
@@ -1413,12 +1786,16 @@
           HasSuffixString(output_directive.name, "_out"))
         << "Bad name for plugin generator: " << output_directive.name;
 
-    // Strip the "--" and "_out" and add the plugin prefix.
-    string plugin_name = plugin_prefix_ + "gen-" +
-        output_directive.name.substr(2, output_directive.name.size() - 6);
-
+    string plugin_name = PluginName(plugin_prefix_ , output_directive.name);
+    string parameters = output_directive.parameter;
+    if (!plugin_parameters_[plugin_name].empty()) {
+      if (!parameters.empty()) {
+        parameters.append(",");
+      }
+      parameters.append(plugin_parameters_[plugin_name]);
+    }
     if (!GeneratePluginOutput(parsed_files, plugin_name,
-                              output_directive.parameter,
+                              parameters,
                               generator_context, &error)) {
       std::cerr << output_directive.name << ": " << error << std::endl;
       return false;
@@ -1432,24 +1809,11 @@
       }
       parameters.append(generator_parameters_[output_directive.name]);
     }
-    if (output_directive.generator->HasGenerateAll()) {
-      if (!output_directive.generator->GenerateAll(
-          parsed_files, parameters, generator_context, &error)) {
-          // Generator returned an error.
-          std::cerr << output_directive.name << ": "
-                    << ": " << error << std::endl;
-          return false;
-      }
-    } else {
-      for (int i = 0; i < parsed_files.size(); i++) {
-        if (!output_directive.generator->Generate(parsed_files[i], parameters,
-                                                  generator_context, &error)) {
-          // Generator returned an error.
-          std::cerr << output_directive.name << ": " << parsed_files[i]->name()
-                    << ": " << error << std::endl;
-          return false;
-        }
-      }
+    if (!output_directive.generator->GenerateAll(
+        parsed_files, parameters, generator_context, &error)) {
+      // Generator returned an error.
+      std::cerr << output_directive.name << ": " << error << std::endl;
+      return false;
     }
   }
 
@@ -1457,12 +1821,12 @@
 }
 
 bool CommandLineInterface::GenerateDependencyManifestFile(
-    const vector<const FileDescriptor*>& parsed_files,
+    const std::vector<const FileDescriptor*>& parsed_files,
     const GeneratorContextMap& output_directories,
     DiskSourceTree* source_tree) {
   FileDescriptorSet file_set;
 
-  set<const FileDescriptor*> already_seen;
+  std::set<const FileDescriptor*> already_seen;
   for (int i = 0; i < parsed_files.size(); i++) {
     GetTransitiveDependencies(parsed_files[i],
                               false,
@@ -1471,12 +1835,12 @@
                               file_set.mutable_file());
   }
 
-  vector<string> output_filenames;
+  std::vector<string> output_filenames;
   for (GeneratorContextMap::const_iterator iter = output_directories.begin();
        iter != output_directories.end(); ++iter) {
     const string& location = iter->first;
     GeneratorContextImpl* directory = iter->second;
-    vector<string> relative_output_filenames;
+    std::vector<string> relative_output_filenames;
     directory->GetOutputFilenames(&relative_output_filenames);
     for (int i = 0; i < relative_output_filenames.size(); i++) {
       string output_filename = location + relative_output_filenames[i];
@@ -1529,20 +1893,23 @@
 }
 
 bool CommandLineInterface::GeneratePluginOutput(
-    const vector<const FileDescriptor*>& parsed_files,
+    const std::vector<const FileDescriptor*>& parsed_files,
     const string& plugin_name,
     const string& parameter,
     GeneratorContext* generator_context,
     string* error) {
   CodeGeneratorRequest request;
   CodeGeneratorResponse response;
+  string processed_parameter = parameter;
+
 
   // Build the request.
-  if (!parameter.empty()) {
-    request.set_parameter(parameter);
+  if (!processed_parameter.empty()) {
+    request.set_parameter(processed_parameter);
   }
 
-  set<const FileDescriptor*> already_seen;
+
+  std::set<const FileDescriptor*> already_seen;
   for (int i = 0; i < parsed_files.size(); i++) {
     request.add_file_to_generate(parsed_files[i]->name());
     GetTransitiveDependencies(parsed_files[i],
@@ -1551,6 +1918,13 @@
                               &already_seen, request.mutable_proto_file());
   }
 
+  google::protobuf::compiler::Version* version =
+      request.mutable_compiler_version();
+  version->set_major(GOOGLE_PROTOBUF_VERSION / 1000000);
+  version->set_minor(GOOGLE_PROTOBUF_VERSION / 1000 % 1000);
+  version->set_patch(GOOGLE_PROTOBUF_VERSION % 1000);
+  version->set_suffix(GOOGLE_PROTOBUF_VERSION_SUFFIX);
+
   // Invoke the plugin.
   Subprocess subprocess;
 
@@ -1568,17 +1942,18 @@
 
   // Write the files.  We do this even if there was a generator error in order
   // to match the behavior of a compiled-in generator.
-  google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> current_output;
+  std::unique_ptr<io::ZeroCopyOutputStream> current_output;
   for (int i = 0; i < response.file_size(); i++) {
     const CodeGeneratorResponse::File& output_file = response.file(i);
 
     if (!output_file.insertion_point().empty()) {
+      string filename = output_file.name();
       // Open a file for insert.
       // 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(generator_context->OpenForInsert(
-          output_file.name(), output_file.insertion_point()));
+          filename, 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
@@ -1617,7 +1992,7 @@
   }
 
   DynamicMessageFactory dynamic_factory(pool);
-  google::protobuf::scoped_ptr<Message> message(dynamic_factory.GetPrototype(type)->New());
+  std::unique_ptr<Message> message(dynamic_factory.GetPrototype(type)->New());
 
   if (mode_ == MODE_ENCODE) {
     SetFdToTextMode(STDIN_FILENO);
@@ -1672,52 +2047,55 @@
 }
 
 bool CommandLineInterface::WriteDescriptorSet(
-    const vector<const FileDescriptor*> parsed_files) {
+    const std::vector<const FileDescriptor*>& parsed_files) {
   FileDescriptorSet file_set;
 
-  if (imports_in_descriptor_set_) {
-    set<const FileDescriptor*> already_seen;
+  std::set<const FileDescriptor*> already_seen;
+  if (!imports_in_descriptor_set_) {
+    // Since we don't want to output transitive dependencies, but we do want
+    // things to be in dependency order, add all dependencies that aren't in
+    // parsed_files to already_seen.  This will short circuit the recursion
+    // in GetTransitiveDependencies.
+    std::set<const FileDescriptor*> to_output;
+    to_output.insert(parsed_files.begin(), parsed_files.end());
     for (int i = 0; i < parsed_files.size(); i++) {
-      GetTransitiveDependencies(parsed_files[i],
-                                true,  // Include json_name
-                                source_info_in_descriptor_set_,
-                                &already_seen, file_set.mutable_file());
-    }
-  } else {
-    set<const FileDescriptor*> already_seen;
-    for (int i = 0; i < parsed_files.size(); i++) {
-      if (!already_seen.insert(parsed_files[i]).second) {
-        continue;
-      }
-      FileDescriptorProto* file_proto = file_set.add_file();
-      parsed_files[i]->CopyTo(file_proto);
-      parsed_files[i]->CopyJsonNameTo(file_proto);
-      if (source_info_in_descriptor_set_) {
-        parsed_files[i]->CopySourceCodeInfoTo(file_proto);
+      const FileDescriptor* file = parsed_files[i];
+      for (int i = 0; i < file->dependency_count(); i++) {
+        const FileDescriptor* dependency = file->dependency(i);
+        // if the dependency isn't in parsed files, mark it as already seen
+        if (to_output.find(dependency) == to_output.end()) {
+          already_seen.insert(dependency);
+        }
       }
     }
   }
+  for (int i = 0; i < parsed_files.size(); i++) {
+    GetTransitiveDependencies(parsed_files[i],
+                              true,  // Include json_name
+                              source_info_in_descriptor_set_,
+                              &already_seen, file_set.mutable_file());
+  }
 
   int fd;
   do {
-    fd = open(descriptor_set_name_.c_str(),
+    fd = open(descriptor_set_out_name_.c_str(),
               O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
   } while (fd < 0 && errno == EINTR);
 
   if (fd < 0) {
-    perror(descriptor_set_name_.c_str());
+    perror(descriptor_set_out_name_.c_str());
     return false;
   }
 
   io::FileOutputStream out(fd);
   if (!file_set.SerializeToZeroCopyStream(&out)) {
-    std::cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno())
+    std::cerr << descriptor_set_out_name_ << ": " << strerror(out.GetErrno())
               << std::endl;
     out.Close();
     return false;
   }
   if (!out.Close()) {
-    std::cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno())
+    std::cerr << descriptor_set_out_name_ << ": " << strerror(out.GetErrno())
               << std::endl;
     return false;
   }
@@ -1729,7 +2107,7 @@
     const FileDescriptor* file,
     bool include_json_name,
     bool include_source_code_info,
-    set<const FileDescriptor*>* already_seen,
+    std::set<const FileDescriptor*>* already_seen,
     RepeatedPtrField<FileDescriptorProto>* output) {
   if (!already_seen->insert(file).second) {
     // Already saw this file.  Skip.
@@ -1788,11 +2166,11 @@
 // parameter will contain the direct children (when groups are ignored in the
 // tree) of the given descriptor for the caller to traverse. The declaration
 // order of the nested messages is also preserved.
-typedef pair<int, int> FieldRange;
-void GatherOccupiedFieldRanges(const Descriptor* descriptor,
-                               set<FieldRange>* ranges,
-                               vector<const Descriptor*>* nested_messages) {
-  set<const Descriptor*> groups;
+typedef std::pair<int, int> FieldRange;
+void GatherOccupiedFieldRanges(
+    const Descriptor* descriptor, std::set<FieldRange>* ranges,
+    std::vector<const Descriptor*>* nested_messages) {
+  std::set<const Descriptor*> groups;
   for (int i = 0; i < descriptor->field_count(); ++i) {
     const FieldDescriptor* fd = descriptor->field(i);
     ranges->insert(FieldRange(fd->number(), fd->number() + 1));
@@ -1824,11 +2202,11 @@
 // Actually prints the formatted free field numbers for given message name and
 // occupied ranges.
 void FormatFreeFieldNumbers(const string& name,
-                            const set<FieldRange>& ranges) {
+                            const std::set<FieldRange>& ranges) {
   string output;
   StringAppendF(&output, "%-35s free:", name.c_str());
   int next_free_number = 1;
-  for (set<FieldRange>::const_iterator i = ranges.begin();
+  for (std::set<FieldRange>::const_iterator i = ranges.begin();
        i != ranges.end(); ++i) {
     // This happens when groups re-use parent field numbers, in which
     // case we skip the FieldRange entirely.
@@ -1855,8 +2233,8 @@
 
 void CommandLineInterface::PrintFreeFieldNumbers(
     const Descriptor* descriptor) {
-  set<FieldRange> ranges;
-  vector<const Descriptor*> nested_messages;
+  std::set<FieldRange> ranges;
+  std::vector<const Descriptor*> nested_messages;
   GatherOccupiedFieldRanges(descriptor, &ranges, &nested_messages);
 
   for (int i = 0; i < nested_messages.size(); ++i) {
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index f196ffc..7d3037a 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -52,14 +52,16 @@
 class Descriptor;            // descriptor.h
 class DescriptorPool;        // descriptor.h
 class FileDescriptor;        // descriptor.h
+class FileDescriptorSet;     // descriptor.h
 class FileDescriptorProto;   // descriptor.pb.h
 template<typename T> class RepeatedPtrField;  // repeated_field.h
+class SimpleDescriptorDatabase;               // descriptor_database.h
 
 namespace compiler {
 
-class CodeGenerator;        // code_generator.h
-class GeneratorContext;      // code_generator.h
-class DiskSourceTree;       // importer.h
+class CodeGenerator;     // code_generator.h
+class GeneratorContext;  // code_generator.h
+class DiskSourceTree;    // importer.h
 
 // This class implements the command-line interface to the protocol compiler.
 // It is designed to make it very easy to create a custom protocol compiler
@@ -88,9 +90,21 @@
 // The compiler is invoked with syntax like:
 //   protoc --cpp_out=outdir --foo_out=outdir --proto_path=src src/foo.proto
 //
+// The .proto file to compile can be specified on the command line using either
+// its physical file path, or a virtual path relative to a diretory specified
+// in --proto_path. For example, for src/foo.proto, the following two protoc
+// invocations work the same way:
+//   1. protoc --proto_path=src src/foo.proto (physical file path)
+//   2. protoc --proto_path=src foo.proto (virtual path relative to src)
+//
+// If a file path can be interpreted both as a physical file path and as a
+// relative virtual path, the physical file path takes precendence.
+//
 // For a full description of the command-line syntax, invoke it with --help.
 class LIBPROTOC_EXPORT CommandLineInterface {
  public:
+  static const char* const kPathSeparator;
+
   CommandLineInterface();
   ~CommandLineInterface();
 
@@ -141,14 +155,14 @@
   //   plugin [--out=OUTDIR] [--parameter=PARAMETER] PROTO_FILES < DESCRIPTORS
   // --out indicates the output directory (as passed to the --foo_out
   // parameter); if omitted, the current directory should be used.  --parameter
-  // gives the generator parameter, if any was provided.  The PROTO_FILES list
-  // the .proto files which were given on the compiler command-line; these are
-  // the files for which the plugin is expected to generate output code.
-  // Finally, DESCRIPTORS is an encoded FileDescriptorSet (as defined in
-  // descriptor.proto).  This is piped to the plugin's stdin.  The set will
-  // include descriptors for all the files listed in PROTO_FILES as well as
-  // all files that they import.  The plugin MUST NOT attempt to read the
-  // PROTO_FILES directly -- it must use the FileDescriptorSet.
+  // gives the generator parameter, if any was provided (see below).  The
+  // PROTO_FILES list the .proto files which were given on the compiler
+  // command-line; these are the files for which the plugin is expected to
+  // generate output code.  Finally, DESCRIPTORS is an encoded FileDescriptorSet
+  // (as defined in descriptor.proto).  This is piped to the plugin's stdin.
+  // The set will include descriptors for all the files listed in PROTO_FILES as
+  // well as all files that they import.  The plugin MUST NOT attempt to read
+  // the PROTO_FILES directly -- it must use the FileDescriptorSet.
   //
   // The plugin should generate whatever files are necessary, as code generators
   // normally do.  It should write the names of all files it generates to
@@ -156,6 +170,13 @@
   // names or relative to the current directory.  If any errors occur, error
   // messages should be written to stderr.  If an error is fatal, the plugin
   // should exit with a non-zero exit code.
+  //
+  // Plugins can have generator parameters similar to normal built-in
+  // generators. Extra generator parameters can be passed in via a matching
+  // "_opt" parameter. For example:
+  //   protoc --plug_out=enable_bar:outdir --plug_opt=enable_baz
+  // This will pass "enable_bar,enable_baz" as the parameter to the plugin.
+  //
   void AllowPlugins(const string& exe_name_prefix);
 
   // Run the Protocol Compiler with the given command-line parameters.
@@ -165,17 +186,11 @@
   // it calls strerror().  I'm not sure why you'd want to do this anyway.
   int Run(int argc, const char* const argv[]);
 
-  // Call SetInputsAreCwdRelative(true) if the input files given on the command
-  // line should be interpreted relative to the proto import path specified
-  // using --proto_path or -I flags.  Otherwise, input file names will be
-  // interpreted relative to the current working directory (or as absolute
-  // paths if they start with '/'), though they must still reside inside
-  // a directory given by --proto_path or the compiler will fail.  The latter
-  // mode is generally more intuitive and easier to use, especially e.g. when
-  // defining implicit rules in Makefiles.
-  void SetInputsAreProtoPathRelative(bool enable) {
-    inputs_are_proto_path_relative_ = enable;
-  }
+  // DEPRECATED. Calling this method has no effect. Protocol compiler now
+  // always try to find the .proto file relative to the current directory
+  // first and if the file is not found, it will then treat the input path
+  // as a virutal path.
+  void SetInputsAreProtoPathRelative(bool /* enable */) {}
 
   // Provides some text which will be printed when the --version flag is
   // used.  The version of libprotoc will also be printed on the next line
@@ -212,6 +227,10 @@
   // Parse all command-line arguments.
   ParseArgumentStatus ParseArguments(int argc, const char* const argv[]);
 
+  // Read an argument file and append the file's content to the list of
+  // arguments. Return false if the file cannot be read.
+  bool ExpandArgumentFile(const string& file, std::vector<string>* arguments);
+
   // Parses a command-line argument into a name/value pair.  Returns
   // true if the next argument in the argv should be used as the value,
   // false otherwise.
@@ -232,26 +251,36 @@
   // Print the --help text to stderr.
   void PrintHelpText();
 
+  // Loads proto_path_ into the provided source_tree.
+  bool InitializeDiskSourceTree(DiskSourceTree* source_tree);
+
+  // Loads descriptor_set_in into the provided database
+  bool PopulateSimpleDescriptorDatabase(SimpleDescriptorDatabase* database);
+
+  // Parses input_files_ into parsed_files
+  bool ParseInputFiles(DescriptorPool* descriptor_pool,
+                       std::vector<const FileDescriptor*>* parsed_files);
+
   // Generate the given output file from the given input.
   struct OutputDirective;  // see below
-  bool GenerateOutput(const vector<const FileDescriptor*>& parsed_files,
+  bool GenerateOutput(const std::vector<const FileDescriptor*>& parsed_files,
                       const OutputDirective& output_directive,
                       GeneratorContext* generator_context);
-  bool GeneratePluginOutput(const vector<const FileDescriptor*>& parsed_files,
-                            const string& plugin_name,
-                            const string& parameter,
-                            GeneratorContext* generator_context,
-                            string* error);
+  bool GeneratePluginOutput(
+      const std::vector<const FileDescriptor*>& parsed_files,
+      const string& plugin_name, const string& parameter,
+      GeneratorContext* generator_context, string* error);
 
   // Implements --encode and --decode.
   bool EncodeOrDecode(const DescriptorPool* pool);
 
   // Implements the --descriptor_set_out option.
-  bool WriteDescriptorSet(const vector<const FileDescriptor*> parsed_files);
+  bool WriteDescriptorSet(
+      const std::vector<const FileDescriptor*>& parsed_files);
 
   // Implements the --dependency_out option
   bool GenerateDependencyManifestFile(
-      const vector<const FileDescriptor*>& parsed_files,
+      const std::vector<const FileDescriptor*>& parsed_files,
       const GeneratorContextMap& output_directories,
       DiskSourceTree* source_tree);
 
@@ -268,7 +297,7 @@
       const FileDescriptor* file,
       bool include_json_name,
       bool include_source_code_info,
-      set<const FileDescriptor*>* already_seen,
+      std::set<const FileDescriptor*>* already_seen,
       RepeatedPtrField<FileDescriptorProto>* output);
 
   // Implements the --print_free_field_numbers. This function prints free field
@@ -302,14 +331,16 @@
     CodeGenerator* generator;
     string help_text;
   };
-  typedef map<string, GeneratorInfo> GeneratorMap;
+  typedef std::map<string, GeneratorInfo> GeneratorMap;
   GeneratorMap generators_by_flag_name_;
   GeneratorMap generators_by_option_name_;
   // A map from generator names to the parameters specified using the option
   // flag. For example, if the user invokes the compiler with:
   //   protoc --foo_out=outputdir --foo_opt=enable_bar ...
   // Then there will be an entry ("--foo_out", "enable_bar") in this map.
-  map<string, string> generator_parameters_;
+  std::map<string, string> generator_parameters_;
+  // Similar to generator_parameters_, but stores the parameters for plugins.
+  std::map<string, string> plugin_parameters_;
 
   // See AllowPlugins().  If this is empty, plugins aren't allowed.
   string plugin_prefix_;
@@ -317,7 +348,7 @@
   // Maps specific plugin names to files.  When executing a plugin, this map
   // is searched first to find the plugin executable.  If not found here, the
   // PATH (or other OS-specific search strategy) is searched.
-  map<string, string> plugins_;
+  std::map<string, string> plugins_;
 
   // Stuff parsed from command line.
   enum Mode {
@@ -343,8 +374,18 @@
 
   ErrorFormat error_format_;
 
-  vector<pair<string, string> > proto_path_;  // Search path for proto files.
-  vector<string> input_files_;                // Names of the input proto files.
+  std::vector<std::pair<string, string> >
+      proto_path_;                   // Search path for proto files.
+  std::vector<string> input_files_;  // Names of the input proto files.
+
+  // Names of proto files which are allowed to be imported. Used by build
+  // systems to enforce depend-on-what-you-import.
+  std::set<string> direct_dependencies_;
+  bool direct_dependencies_explicitly_set_;
+
+  // If there's a violation of depend-on-what-you-import, this string will be
+  // presented to the user. "%s" will be replaced with the violating import.
+  string direct_dependencies_violation_msg_;
 
   // output_directives_ lists all the files we are supposed to output and what
   // generator to use for each.
@@ -354,15 +395,19 @@
     string parameter;
     string output_location;
   };
-  vector<OutputDirective> output_directives_;
+  std::vector<OutputDirective> output_directives_;
 
   // When using --encode or --decode, this names the type we are encoding or
   // decoding.  (Empty string indicates --decode_raw.)
   string codec_type_;
 
+  // If --descriptor_set_in was given, these are filenames containing
+  // parsed FileDescriptorSets to be used for loading protos.  Otherwise, empty.
+  std::vector<string> descriptor_set_in_names_;
+
   // If --descriptor_set_out was given, this is the filename to which the
   // FileDescriptorSet should be written.  Otherwise, empty.
-  string descriptor_set_name_;
+  string descriptor_set_out_name_;
 
   // If --dependency_out was given, this is the path to the file where the
   // dependency file will be written. Otherwise, empty.
@@ -380,9 +425,6 @@
   // Was the --disallow_services flag used?
   bool disallow_services_;
 
-  // See SetInputsAreProtoPathRelative().
-  bool inputs_are_proto_path_relative_;
-
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CommandLineInterface);
 };
 
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index dda007d..41eb244 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -32,56 +32,56 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <sys/types.h>
-#include <sys/stat.h>
 #include <fcntl.h>
-#ifdef _MSC_VER
-#include <io.h>
-#else
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#ifndef _MSC_VER
 #include <unistd.h>
 #endif
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 #include <vector>
 
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/compiler/command_line_interface.h>
-#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/file.h>
 #include <google/protobuf/compiler/mock_code_generator.h>
 #include <google/protobuf/compiler/subprocess.h>
-#include <google/protobuf/io/printer.h>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
 #include <google/protobuf/stubs/substitute.h>
 
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/io_win32.h>
+
 namespace google {
 namespace protobuf {
 namespace compiler {
 
+#if defined(_WIN32)
+// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
+// them like we do below.
+using google::protobuf::internal::win32::access;
+using google::protobuf::internal::win32::dup;
+using google::protobuf::internal::win32::dup2;
+using google::protobuf::internal::win32::close;
+using google::protobuf::internal::win32::open;
+using google::protobuf::internal::win32::write;
+#endif
+
 // Disable the whole test when we use tcmalloc for "draconian" heap checks, in
 // which case tcmalloc will print warnings that fail the plugin tests.
 #if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
 
-#if defined(_WIN32)
-#ifndef STDIN_FILENO
-#define STDIN_FILENO 0
-#endif
-#ifndef STDOUT_FILENO
-#define STDOUT_FILENO 1
-#endif
-#ifndef F_OK
-#define F_OK 00  // not defined by MSVC for whatever reason
-#endif
-#endif
 
 namespace {
 
@@ -98,6 +98,7 @@
   // command is automatically split on spaces, and the string "$tmpdir"
   // is replaced with TestTempDir().
   void Run(const string& command);
+  void RunWithArgs(std::vector<string> args);
 
   // -----------------------------------------------------------------
   // Methods to set up the test (called before Run()).
@@ -125,10 +126,6 @@
   // google3.
 #endif  // !PROTOBUF_OPENSOURCE
 
-  void SetInputsAreProtoPathRelative(bool enable) {
-    cli_.SetInputsAreProtoPathRelative(enable);
-  }
-
   // -----------------------------------------------------------------
   // Methods to check the test results (called after Run()).
 
@@ -152,6 +149,11 @@
   // Checks that the captured stdout is the same as the expected_text.
   void ExpectCapturedStdout(const string& expected_text);
 
+  // Checks that Run() returned zero and the stdout contains the given
+  // substring.
+  void ExpectCapturedStdoutSubstringWithZeroReturnCode(
+      const string& expected_substring);
+
   // Returns true if ExpectErrorSubstring(expected_substring) would pass, but
   // does not fail otherwise.
   bool HasAlternateErrorSubstring(const string& expected_substring);
@@ -183,12 +185,17 @@
                                      const string& insertions,
                                      const string& proto_name,
                                      const string& message_name);
+  void CheckGeneratedAnnotations(const string& name, const string& file);
 
   void ExpectNullCodeGeneratorCalled(const string& parameter);
 
+
   void ReadDescriptorSet(const string& filename,
                          FileDescriptorSet* descriptor_set);
 
+  void WriteDescriptorSet(const string& filename,
+                          const FileDescriptorSet* descriptor_set);
+
   void ExpectFileContent(const string& filename,
                          const string& content);
 
@@ -215,7 +222,7 @@
   string captured_stdout_;
 
   // Pointers which need to be deleted later.
-  vector<CodeGenerator*> mock_generators_to_delete_;
+  std::vector<CodeGenerator*> mock_generators_to_delete_;
 
   NullCodeGenerator* null_generator_;
 };
@@ -242,11 +249,6 @@
 // ===================================================================
 
 void CommandLineInterfaceTest::SetUp() {
-  // Most of these tests were written before this option was added, so we
-  // run with the option on (which used to be the only way) except in certain
-  // tests where we turn it off.
-  cli_.SetInputsAreProtoPathRelative(true);
-
   temp_directory_ = TestTempDir() + "/proto2_cli_test_temp";
 
   // If the temp directory already exists, it must be left over from a
@@ -272,6 +274,7 @@
   mock_generators_to_delete_.push_back(generator);
   cli_.RegisterGenerator("--null_out", generator, "Null output.");
 
+
   disallow_plugins_ = false;
 }
 
@@ -289,8 +292,10 @@
 }
 
 void CommandLineInterfaceTest::Run(const string& command) {
-  vector<string> args = Split(command, " ", true);
+  RunWithArgs(Split(command, " ", true));
+}
 
+void CommandLineInterfaceTest::RunWithArgs(std::vector<string> args) {
   if (!disallow_plugins_) {
     cli_.AllowPlugins("prefix-");
 #ifndef GOOGLE_THIRD_PARTY_PROTOBUF
@@ -336,7 +341,7 @@
     }
   }
 
-  google::protobuf::scoped_array<const char * > argv(new const char* [args.size()]);
+  std::unique_ptr<const char * []> argv(new const char* [args.size()]);
 
   for (int i = 0; i < args.size(); i++) {
     args[i] = StringReplace(args[i], "$tmpdir", temp_directory_, true);
@@ -376,7 +381,9 @@
 
   // Write file.
   string full_name = temp_directory_ + "/" + name;
-  GOOGLE_CHECK_OK(File::SetContents(full_name, contents, true));
+  GOOGLE_CHECK_OK(File::SetContents(
+      full_name, StringReplace(contents, "$tmpdir", temp_directory_, true),
+      true));
 }
 
 void CommandLineInterfaceTest::CreateTempDir(const string& name) {
@@ -458,12 +465,18 @@
       proto_name, temp_directory_);
 }
 
+void CommandLineInterfaceTest::CheckGeneratedAnnotations(const string& name,
+                                                         const string& file) {
+  MockCodeGenerator::CheckGeneratedAnnotations(name, file, temp_directory_);
+}
+
 void CommandLineInterfaceTest::ExpectNullCodeGeneratorCalled(
     const string& parameter) {
   EXPECT_TRUE(null_generator_->called_);
   EXPECT_EQ(parameter, null_generator_->parameter_);
 }
 
+
 void CommandLineInterfaceTest::ReadDescriptorSet(
     const string& filename, FileDescriptorSet* descriptor_set) {
   string path = temp_directory_ + "/" + filename;
@@ -475,11 +488,24 @@
   }
 }
 
+void CommandLineInterfaceTest::WriteDescriptorSet(
+    const string& filename, const FileDescriptorSet* descriptor_set) {
+  string binary_proto;
+  GOOGLE_CHECK(descriptor_set->SerializeToString(&binary_proto));
+  CreateTempFile(filename, binary_proto);
+}
+
 void CommandLineInterfaceTest::ExpectCapturedStdout(
     const string& expected_text) {
   EXPECT_EQ(expected_text, captured_stdout_);
 }
 
+void CommandLineInterfaceTest::ExpectCapturedStdoutSubstringWithZeroReturnCode(
+    const string& expected_substring) {
+  EXPECT_EQ(0, return_code_);
+  EXPECT_PRED_FORMAT2(
+      testing::IsSubstring, expected_substring, captured_stdout_);
+}
 
 void CommandLineInterfaceTest::ExpectFileContent(
     const string& filename, const string& content) {
@@ -507,6 +533,22 @@
   ExpectGenerated("test_generator", "", "foo.proto", "Foo");
 }
 
+TEST_F(CommandLineInterfaceTest, BasicOutput_DescriptorSetIn) {
+  // Test that the common case works.
+  FileDescriptorSet file_descriptor_set;
+  FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("foo.proto");
+  file_descriptor_proto->add_message_type()->set_name("Foo");
+
+  WriteDescriptorSet("foo.bin", &file_descriptor_set);
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
 TEST_F(CommandLineInterfaceTest, BasicPlugin) {
   // Test that basic plugins work.
 
@@ -521,6 +563,23 @@
   ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
 }
 
+TEST_F(CommandLineInterfaceTest, BasicPlugin_DescriptorSetIn) {
+  // Test that basic plugins work.
+
+  FileDescriptorSet file_descriptor_set;
+  FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("foo.proto");
+  file_descriptor_proto->add_message_type()->set_name("Foo");
+
+  WriteDescriptorSet("foo.bin", &file_descriptor_set);
+
+  Run("protocol_compiler --plug_out=$tmpdir "
+      "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
+}
+
 TEST_F(CommandLineInterfaceTest, GeneratorAndPlugin) {
   // Invoke a generator and a plugin at the same time.
 
@@ -536,6 +595,24 @@
   ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
 }
 
+TEST_F(CommandLineInterfaceTest, GeneratorAndPlugin_DescriptorSetIn) {
+  // Invoke a generator and a plugin at the same time.
+
+  FileDescriptorSet file_descriptor_set;
+  FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("foo.proto");
+  file_descriptor_proto->add_message_type()->set_name("Foo");
+
+  WriteDescriptorSet("foo.bin", &file_descriptor_set);
+
+  Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+      "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+  ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
+}
+
 TEST_F(CommandLineInterfaceTest, MultipleInputs) {
   // Test parsing multiple input files.
 
@@ -560,6 +637,34 @@
                                     "bar.proto", "Bar");
 }
 
+TEST_F(CommandLineInterfaceTest, MultipleInputs_DescriptorSetIn) {
+  // Test parsing multiple input files.
+  FileDescriptorSet file_descriptor_set;
+
+  FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("foo.proto");
+  file_descriptor_proto->add_message_type()->set_name("Foo");
+
+  file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("bar.proto");
+  file_descriptor_proto->add_message_type()->set_name("Bar");
+
+  WriteDescriptorSet("foo.bin", &file_descriptor_set);
+
+  Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+      "--descriptor_set_in=$tmpdir/foo.bin 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, MultipleInputsWithImport) {
   // Test parsing multiple input files with an import of a separate file.
 
@@ -590,6 +695,165 @@
                                     "bar.proto", "Bar");
 }
 
+TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport_DescriptorSetIn) {
+  // Test parsing multiple input files with an import of a separate file.
+  FileDescriptorSet file_descriptor_set;
+
+  FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("foo.proto");
+  file_descriptor_proto->add_message_type()->set_name("Foo");
+
+  file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("bar.proto");
+  file_descriptor_proto->add_dependency("baz.proto");
+  DescriptorProto* message = file_descriptor_proto->add_message_type();
+  message->set_name("Bar");
+  FieldDescriptorProto* field = message->add_field();
+  field->set_type_name("Baz");
+  field->set_name("a");
+  field->set_number(1);
+
+  WriteDescriptorSet("foo_and_bar.bin", &file_descriptor_set);
+
+  file_descriptor_set.clear_file();
+  file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("baz.proto");
+  file_descriptor_proto->add_message_type()->set_name("Baz");
+
+  file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("bat.proto");
+  file_descriptor_proto->add_dependency("baz.proto");
+  message = file_descriptor_proto->add_message_type();
+  message->set_name("Bat");
+  field = message->add_field();
+  field->set_type_name("Baz");
+  field->set_name("a");
+  field->set_number(1);
+
+  WriteDescriptorSet("baz_and_bat.bin", &file_descriptor_set);
+  Run(strings::Substitute(
+      "protocol_compiler --test_out=$$tmpdir --plug_out=$$tmpdir "
+      "--descriptor_set_in=$0 foo.proto bar.proto",
+      string("$tmpdir/foo_and_bar.bin") +
+      CommandLineInterface::kPathSeparator +
+      "$tmpdir/baz_and_bat.bin"));
+
+  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");
+
+  Run(strings::Substitute(
+      "protocol_compiler --test_out=$$tmpdir --plug_out=$$tmpdir "
+      "--descriptor_set_in=$0 baz.proto bat.proto",
+      string("$tmpdir/foo_and_bar.bin") +
+      CommandLineInterface::kPathSeparator +
+      "$tmpdir/baz_and_bat.bin"));
+
+  ExpectNoErrors();
+  ExpectGeneratedWithMultipleInputs("test_generator", "baz.proto,bat.proto",
+                                    "baz.proto", "Baz");
+  ExpectGeneratedWithMultipleInputs("test_generator", "baz.proto,bat.proto",
+                                    "bat.proto", "Bat");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "baz.proto,bat.proto",
+                                    "baz.proto", "Baz");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "baz.proto,bat.proto",
+                                    "bat.proto", "Bat");
+}
+
+TEST_F(CommandLineInterfaceTest,
+       MultipleInputsWithImport_DescriptorSetIn_DuplicateFileDescriptor) {
+  // Test parsing multiple input files with an import of a separate file.
+  FileDescriptorSet file_descriptor_set;
+
+  FileDescriptorProto foo_file_descriptor_proto;
+  foo_file_descriptor_proto.set_name("foo.proto");
+  foo_file_descriptor_proto.add_message_type()->set_name("Foo");
+
+  file_descriptor_set.add_file()->CopyFrom(foo_file_descriptor_proto);
+
+  FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("bar.proto");
+  file_descriptor_proto->add_dependency("baz.proto");
+  file_descriptor_proto->add_dependency("foo.proto");
+  DescriptorProto* message = file_descriptor_proto->add_message_type();
+  message->set_name("Bar");
+  FieldDescriptorProto* field = message->add_field();
+  field->set_type_name("Baz");
+  field->set_name("a");
+  field->set_number(1);
+  field = message->add_field();
+  field->set_type_name("Foo");
+  field->set_name("f");
+  field->set_number(2);
+  WriteDescriptorSet("foo_and_bar.bin", &file_descriptor_set);
+
+  file_descriptor_set.clear_file();
+  file_descriptor_set.add_file()->CopyFrom(foo_file_descriptor_proto);
+
+  file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("baz.proto");
+  file_descriptor_proto->add_dependency("foo.proto");
+  message = file_descriptor_proto->add_message_type();
+  message->set_name("Baz");
+  field = message->add_field();
+  field->set_type_name("Foo");
+  field->set_name("f");
+  field->set_number(1);
+  WriteDescriptorSet("foo_and_baz.bin", &file_descriptor_set);
+
+  Run(strings::Substitute(
+      "protocol_compiler --test_out=$$tmpdir --plug_out=$$tmpdir "
+      "--descriptor_set_in=$0 bar.proto",
+      string("$tmpdir/foo_and_bar.bin") +
+      CommandLineInterface::kPathSeparator +
+      "$tmpdir/foo_and_baz.bin"));
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "bar.proto", "Bar");
+  ExpectGenerated("test_plugin", "", "bar.proto", "Bar");
+}
+
+TEST_F(CommandLineInterfaceTest,
+       MultipleInputsWithImport_DescriptorSetIn_MissingImport) {
+  // Test parsing multiple input files with an import of a separate file.
+  FileDescriptorSet file_descriptor_set;
+
+  FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("foo.proto");
+  file_descriptor_proto->add_message_type()->set_name("Foo");
+
+  file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("bar.proto");
+  file_descriptor_proto->add_dependency("baz.proto");
+  DescriptorProto* message = file_descriptor_proto->add_message_type();
+  message->set_name("Bar");
+  FieldDescriptorProto* field = message->add_field();
+  field->set_type_name("Baz");
+  field->set_name("a");
+  field->set_number(1);
+
+  WriteDescriptorSet("foo_and_bar.bin", &file_descriptor_set);
+
+  file_descriptor_set.clear_file();
+  file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("baz.proto");
+  file_descriptor_proto->add_message_type()->set_name("Baz");
+
+  WriteDescriptorSet("baz.bin", &file_descriptor_set);
+  Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+      "--descriptor_set_in=$tmpdir/foo_and_bar.bin "
+      "foo.proto bar.proto");
+  ExpectErrorSubstring(
+      "bar.proto: Import \"baz.proto\" was not found or had errors.");
+  ExpectErrorSubstring("bar.proto: \"Baz\" is not defined.");
+}
+
 TEST_F(CommandLineInterfaceTest, CreateDirectory) {
   // Test that when we output to a sub-directory, it is created.
 
@@ -649,6 +913,70 @@
       "test_generator", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b");
 }
 
+TEST_F(CommandLineInterfaceTest, ExtraPluginParameters) {
+  // Test that generator parameters specified with the option flag are
+  // correctly passed to the code generator.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  // Create the "a" and "b" sub-directories.
+  CreateTempDir("a");
+  CreateTempDir("b");
+
+  Run("protocol_compiler "
+      "--plug_opt=foo1 "
+      "--plug_out=bar:$tmpdir/a "
+      "--plug_opt=foo2 "
+      "--plug_out=baz:$tmpdir/b "
+      "--plug_opt=foo3 "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated(
+      "test_plugin", "bar,foo1,foo2,foo3", "foo.proto", "Foo", "a");
+  ExpectGenerated(
+      "test_plugin", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b");
+}
+
+TEST_F(CommandLineInterfaceTest, UnrecognizedExtraParameters) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+      "--unknown_plug_a_opt=Foo "
+      "--unknown_plug_b_opt=Bar "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectErrorSubstring("Unknown flag: --unknown_plug_a_opt");
+  ExpectErrorSubstring("Unknown flag: --unknown_plug_b_opt");
+}
+
+TEST_F(CommandLineInterfaceTest, ExtraPluginParametersForOutParameters) {
+  // This doesn't rely on the plugin having been registred and instead that
+  // the existence of --[name]_out is enough to make the --[name]_opt valid.
+  // However, running out of process plugins found via the search path (i.e. -
+  // not pre registered with --plugin) isn't support in this test suite, so we
+  // list the options pre/post the _out directive, and then include _opt that
+  // will be unknown, and confirm the failure output is about the expected
+  // unknown directive, which means the other were accepted.
+  // NOTE: UnrecognizedExtraParameters confirms that if two unknown _opt
+  // directives appear, they both are reported.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+      "--xyz_opt=foo=bar --xyz_out=$tmpdir "
+      "--abc_out=$tmpdir --abc_opt=foo=bar "
+      "--unknown_plug_opt=Foo "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectErrorText("Unknown flag: --unknown_plug_opt\n");
+}
+
 TEST_F(CommandLineInterfaceTest, Insert) {
   // Test running a generator that inserts code into another's output.
 
@@ -672,6 +1000,25 @@
       "foo.proto", "Foo");
 }
 
+TEST_F(CommandLineInterfaceTest, InsertWithAnnotationFixup) {
+  // Check that annotation spans are updated after insertions.
+
+  CreateTempFile("foo.proto",
+                 "syntax = \"proto2\";\n"
+                 "message MockCodeGenerator_Annotate {}\n");
+
+  Run("protocol_compiler "
+      "--test_out=TestParameter:$tmpdir "
+      "--plug_out=TestPluginParameter:$tmpdir "
+      "--test_out=insert=test_generator,test_plugin:$tmpdir "
+      "--plug_out=insert=test_generator,test_plugin:$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  CheckGeneratedAnnotations("test_generator", "foo.proto");
+  CheckGeneratedAnnotations("test_plugin", "foo.proto");
+}
+
 #if defined(_WIN32)
 
 TEST_F(CommandLineInterfaceTest, WindowsOutputPath) {
@@ -715,6 +1062,11 @@
   ExpectGenerated("test_generator", "", "foo.proto", "Foo");
 }
 
+TEST_F(CommandLineInterfaceTest, Win32ErrorMessage) {
+  EXPECT_EQ("The system cannot find the file specified.\r\n",
+            Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND));
+}
+
 #endif  // defined(_WIN32) || defined(__CYGWIN__)
 
 TEST_F(CommandLineInterfaceTest, PathLookup) {
@@ -752,17 +1104,11 @@
     "}\n");
   CreateTempFile("b/foo.proto", "this should not be parsed\n");
 
-#undef PATH_SEPARATOR
-#if defined(_WIN32)
-#define PATH_SEPARATOR ";"
-#else
-#define PATH_SEPARATOR ":"
-#endif
-
-  Run("protocol_compiler --test_out=$tmpdir "
-      "--proto_path=$tmpdir/a" PATH_SEPARATOR "$tmpdir/b foo.proto");
-
-#undef PATH_SEPARATOR
+  Run(strings::Substitute(
+      "protocol_compiler --test_out=$$tmpdir --proto_path=$0 foo.proto",
+      string("$tmpdir/a") +
+      CommandLineInterface::kPathSeparator +
+      "$tmpdir/b"));
 
   ExpectNoErrors();
   ExpectGenerated("test_generator", "", "foo.proto", "Foo");
@@ -782,6 +1128,21 @@
   ExpectGenerated("test_generator", "", "bar/foo.proto", "Foo");
 }
 
+TEST_F(CommandLineInterfaceTest, PathWithEqualsSign) {
+  // Test setting up a search path which happens to have '=' in it.
+
+  CreateTempDir("with=sign");
+  CreateTempFile("with=sign/foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir/with=sign foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
 TEST_F(CommandLineInterfaceTest, MultipleGenerators) {
   // Test that we can have multiple generators and use both in one invocation,
   // each with a different output directory.
@@ -847,11 +1208,116 @@
   ExpectGenerated("test_generator", "", "foo.proto", "Foo");
 }
 
+TEST_F(CommandLineInterfaceTest, DirectDependencies_Missing_EmptyList) {
+  CreateTempFile("foo.proto",
+                 "syntax = \"proto2\";\n"
+                 "import \"bar.proto\";\n"
+                 "message Foo { optional Bar bar = 1; }");
+  CreateTempFile("bar.proto",
+                 "syntax = \"proto2\";\n"
+                 "message Bar { optional string text = 1; }");
+
+  Run("protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
+      "--direct_dependencies= foo.proto");
+
+  ExpectErrorText(
+      "foo.proto: File is imported but not declared in --direct_dependencies: "
+      "bar.proto\n");
+}
+
+TEST_F(CommandLineInterfaceTest, DirectDependencies_Missing) {
+  CreateTempFile("foo.proto",
+                 "syntax = \"proto2\";\n"
+                 "import \"bar.proto\";\n"
+                 "import \"bla.proto\";\n"
+                 "message Foo { optional Bar bar = 1; optional Bla bla = 2; }");
+  CreateTempFile("bar.proto",
+                 "syntax = \"proto2\";\n"
+                 "message Bar { optional string text = 1; }");
+  CreateTempFile("bla.proto",
+                 "syntax = \"proto2\";\n"
+                 "message Bla { optional int64 number = 1; }");
+
+  Run("protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
+      "--direct_dependencies=bla.proto foo.proto");
+
+  ExpectErrorText(
+      "foo.proto: File is imported but not declared in --direct_dependencies: "
+      "bar.proto\n");
+}
+
+TEST_F(CommandLineInterfaceTest, DirectDependencies_NoViolation) {
+  CreateTempFile("foo.proto",
+                 "syntax = \"proto2\";\n"
+                 "import \"bar.proto\";\n"
+                 "message Foo { optional Bar bar = 1; }");
+  CreateTempFile("bar.proto",
+                 "syntax = \"proto2\";\n"
+                 "message Bar { optional string text = 1; }");
+
+  Run("protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
+      "--direct_dependencies=bar.proto foo.proto");
+
+  ExpectNoErrors();
+}
+
+TEST_F(CommandLineInterfaceTest, DirectDependencies_NoViolation_MultiImports) {
+  CreateTempFile("foo.proto",
+                 "syntax = \"proto2\";\n"
+                 "import \"bar.proto\";\n"
+                 "import \"bla.proto\";\n"
+                 "message Foo { optional Bar bar = 1; optional Bla bla = 2; }");
+  CreateTempFile("bar.proto",
+                 "syntax = \"proto2\";\n"
+                 "message Bar { optional string text = 1; }");
+  CreateTempFile("bla.proto",
+                 "syntax = \"proto2\";\n"
+                 "message Bla { optional int64 number = 1; }");
+
+  Run("protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
+      "--direct_dependencies=bar.proto:bla.proto foo.proto");
+
+  ExpectNoErrors();
+}
+
+TEST_F(CommandLineInterfaceTest, DirectDependencies_ProvidedMultipleTimes) {
+  CreateTempFile("foo.proto",
+                 "syntax = \"proto2\";\n");
+
+  Run("protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
+      "--direct_dependencies=bar.proto --direct_dependencies=bla.proto "
+      "foo.proto");
+
+  ExpectErrorText(
+      "--direct_dependencies may only be passed once. To specify multiple "
+      "direct dependencies, pass them all as a single parameter separated by "
+      "':'.\n");
+}
+
+TEST_F(CommandLineInterfaceTest, DirectDependencies_CustomErrorMessage) {
+  CreateTempFile("foo.proto",
+                 "syntax = \"proto2\";\n"
+                 "import \"bar.proto\";\n"
+                 "message Foo { optional Bar bar = 1; }");
+  CreateTempFile("bar.proto",
+                 "syntax = \"proto2\";\n"
+                 "message Bar { optional string text = 1; }");
+
+  std::vector<string> commands;
+  commands.push_back("protocol_compiler");
+  commands.push_back("--test_out=$tmpdir");
+  commands.push_back("--proto_path=$tmpdir");
+  commands.push_back("--direct_dependencies=");
+  commands.push_back("--direct_dependencies_violation_msg=Bla \"%s\" Bla");
+  commands.push_back("foo.proto");
+  RunWithArgs(commands);
+
+  ExpectErrorText("foo.proto: Bla \"bar.proto\" Bla\n");
+}
+
 TEST_F(CommandLineInterfaceTest, CwdRelativeInputs) {
   // Test that we can accept working-directory-relative input files.
 
-  SetInputsAreProtoPathRelative(false);
-
   CreateTempFile("foo.proto",
     "syntax = \"proto2\";\n"
     "message Foo {}\n");
@@ -918,15 +1384,17 @@
   ReadDescriptorSet("descriptor_set", &descriptor_set);
   if (HasFatalFailure()) return;
   EXPECT_EQ(3, descriptor_set.file_size());
-  EXPECT_EQ("bar.proto", descriptor_set.file(0).name());
-  EXPECT_EQ("foo.proto", descriptor_set.file(1).name());
+  // foo should come first since the output is in dependency order.
+  // since bar and baz are unordered, they should be in command line order.
+  EXPECT_EQ("foo.proto", descriptor_set.file(0).name());
+  EXPECT_EQ("bar.proto", descriptor_set.file(1).name());
   EXPECT_EQ("baz.proto", descriptor_set.file(2).name());
   // Descriptor set should not have source code info.
   EXPECT_FALSE(descriptor_set.file(0).has_source_code_info());
   // Descriptor set should have json_name.
-  EXPECT_EQ("Bar", descriptor_set.file(0).message_type(0).name());
-  EXPECT_EQ("foo", descriptor_set.file(0).message_type(0).field(0).name());
-  EXPECT_TRUE(descriptor_set.file(0).message_type(0).field(0).has_json_name());
+  EXPECT_EQ("Bar", descriptor_set.file(1).message_type(0).name());
+  EXPECT_EQ("foo", descriptor_set.file(1).message_type(0).field(0).name());
+  EXPECT_TRUE(descriptor_set.file(1).message_type(0).field(0).has_json_name());
 }
 
 TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) {
@@ -1090,6 +1558,37 @@
 }
 #endif  // !_WIN32
 
+TEST_F(CommandLineInterfaceTest, TestArgumentFile) {
+  // Test parsing multiple input files using an argument file.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  CreateTempFile("bar.proto",
+    "syntax = \"proto2\";\n"
+    "message Bar {}\n");
+  CreateTempFile("arguments.txt",
+                 "--test_out=$tmpdir\n"
+                 "--plug_out=$tmpdir\n"
+                 "--proto_path=$tmpdir\n"
+                 "--direct_dependencies_violation_msg=%s is not imported\n"
+                 "foo.proto\n"
+                 "bar.proto");
+
+  Run("protocol_compiler @$tmpdir/arguments.txt");
+
+  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, ParseErrors) {
@@ -1106,6 +1605,17 @@
     "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n");
 }
 
+TEST_F(CommandLineInterfaceTest, ParseErrors_DescriptorSetIn) {
+  // Test that parse errors are reported.
+  CreateTempFile("foo.bin", "not a FileDescriptorSet");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
+
+  ExpectErrorText(
+    "$tmpdir/foo.bin: Unable to parse.\n");
+}
+
 TEST_F(CommandLineInterfaceTest, ParseErrorsMultipleFiles) {
   // Test that parse errors are reported from multiple files.
 
@@ -1133,22 +1643,42 @@
     "foo.proto: Import \"baz.proto\" was not found or had errors.\n");
 }
 
+TEST_F(CommandLineInterfaceTest, RecursiveImportFails) {
+  // Create a proto file that imports itself.
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "import \"foo.proto\";\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectErrorSubstring(
+    "foo.proto: File recursively imports itself: foo.proto -> foo.proto\n");
+}
+
 TEST_F(CommandLineInterfaceTest, InputNotFoundError) {
   // Test what happens if the input file is not found.
 
   Run("protocol_compiler --test_out=$tmpdir "
       "--proto_path=$tmpdir foo.proto");
 
+  ExpectErrorText("foo.proto: No such file or directory\n");
+}
+
+TEST_F(CommandLineInterfaceTest, InputNotFoundError_DescriptorSetIn) {
+  // Test what happens if the input file is not found.
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
+
   ExpectErrorText(
-    "foo.proto: File not found.\n");
+    "$tmpdir/foo.bin: No such file or directory\n");
 }
 
 TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundError) {
   // Test what happens when a working-directory-relative input file is not
   // found.
 
-  SetInputsAreProtoPathRelative(false);
-
   Run("protocol_compiler --test_out=$tmpdir "
       "--proto_path=$tmpdir $tmpdir/foo.proto");
 
@@ -1160,8 +1690,6 @@
   // Test what happens when a working-directory-relative input file is not
   // mapped to a virtual path.
 
-  SetInputsAreProtoPathRelative(false);
-
   CreateTempFile("foo.proto",
     "syntax = \"proto2\";\n"
     "message Foo {}\n");
@@ -1186,8 +1714,6 @@
   // Check what happens if the input file is not found *and* is not mapped
   // in the proto_path.
 
-  SetInputsAreProtoPathRelative(false);
-
   // Create a directory called "bar" so that we can point --proto_path at it.
   CreateTempFile("bar/dummy", "");
 
@@ -1202,8 +1728,6 @@
   // Test what happens when a working-directory-relative input file is shadowed
   // by another file in the virtual path.
 
-  SetInputsAreProtoPathRelative(false);
-
   CreateTempFile("foo/foo.proto",
     "syntax = \"proto2\";\n"
     "message Foo {}\n");
@@ -1229,8 +1753,34 @@
       "--proto_path=$tmpdir/foo foo.proto");
 
   ExpectErrorText(
-    "$tmpdir/foo: warning: directory does not exist.\n"
-    "foo.proto: File not found.\n");
+      "$tmpdir/foo: warning: directory does not exist.\n"
+      "foo.proto: No such file or directory\n");
+}
+
+TEST_F(CommandLineInterfaceTest, ProtoPathAndDescriptorSetIn) {
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir --descriptor_set_in=$tmpdir/foo.bin foo.proto");
+  ExpectErrorText(
+      "Only one of --descriptor_set_in and --proto_path can be specified.\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--descriptor_set_in=$tmpdir/foo.bin --proto_path=$tmpdir foo.proto");
+  ExpectErrorText(
+      "Only one of --proto_path and --descriptor_set_in can be specified.\n");
+}
+
+TEST_F(CommandLineInterfaceTest, ProtoPathAndDependencyOut) {
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--dependency_out=$tmpdir/manifest "
+      "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
+  ExpectErrorText(
+      "--descriptor_set_in cannot be used with --dependency_out.\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--descriptor_set_in=$tmpdir/foo.bin "
+      "--dependency_out=$tmpdir/manifest foo.proto");
+  ExpectErrorText(
+      "--dependency_out cannot be used with --descriptor_set_in.\n");
 }
 
 TEST_F(CommandLineInterfaceTest, MissingInputError) {
@@ -1433,6 +1983,21 @@
   ExpectErrorSubstring("Saw json_name: 1");
 }
 
+TEST_F(CommandLineInterfaceTest, PluginReceivesCompilerVersion) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message MockCodeGenerator_ShowVersionNumber {\n"
+    "  optional int32 value = 1;\n"
+    "}\n");
+
+  Run("protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto");
+
+  ExpectErrorSubstring(
+      StringPrintf("Saw compiler_version: %d %s",
+                   GOOGLE_PROTOBUF_VERSION,
+                   GOOGLE_PROTOBUF_VERSION_SUFFIX));
+}
+
 TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) {
   // Test what happens if the plugin isn't found.
 
@@ -1475,11 +2040,11 @@
 TEST_F(CommandLineInterfaceTest, HelpText) {
   Run("test_exec_name --help");
 
-  ExpectErrorSubstringWithZeroReturnCode("Usage: test_exec_name ");
-  ExpectErrorSubstringWithZeroReturnCode("--test_out=OUT_DIR");
-  ExpectErrorSubstringWithZeroReturnCode("Test output.");
-  ExpectErrorSubstringWithZeroReturnCode("--alt_out=OUT_DIR");
-  ExpectErrorSubstringWithZeroReturnCode("Alt output.");
+  ExpectCapturedStdoutSubstringWithZeroReturnCode("Usage: test_exec_name ");
+  ExpectCapturedStdoutSubstringWithZeroReturnCode("--test_out=OUT_DIR");
+  ExpectCapturedStdoutSubstringWithZeroReturnCode("Test output.");
+  ExpectCapturedStdoutSubstringWithZeroReturnCode("--alt_out=OUT_DIR");
+  ExpectCapturedStdoutSubstringWithZeroReturnCode("Alt output.");
 }
 
 TEST_F(CommandLineInterfaceTest, GccFormatErrors) {
@@ -1665,9 +2230,16 @@
 // test as a shell script, but we'd like to be able to run the test on
 // platforms that don't have a Bourne-compatible shell available (especially
 // Windows/MSVC).
-class EncodeDecodeTest : public testing::Test {
+
+enum EncodeDecodeTestMode {
+  PROTO_PATH,
+  DESCRIPTOR_SET_IN
+};
+
+class EncodeDecodeTest : public testing::TestWithParam<EncodeDecodeTestMode> {
  protected:
   virtual void SetUp() {
+    WriteUnittestProtoDescriptorSet();
     duped_stdin_ = dup(STDIN_FILENO);
   }
 
@@ -1707,18 +2279,28 @@
   enum ReturnCode { SUCCESS, ERROR };
 
   bool Run(const string& command) {
-    vector<string> args;
+    std::vector<string> args;
     args.push_back("protoc");
     SplitStringUsing(command, " ", &args);
-    args.push_back("--proto_path=" + TestSourceDir());
+    switch (GetParam()) {
+      case PROTO_PATH:
+        args.push_back("--proto_path=" + TestSourceDir());
+        break;
+      case DESCRIPTOR_SET_IN:
+        args.push_back(StrCat(
+            "--descriptor_set_in=",
+            unittest_proto_descriptor_set_filename_));
+        break;
+      default:
+        ADD_FAILURE() << "unexpected EncodeDecodeTestMode: " << GetParam();
+    }
 
-    google::protobuf::scoped_array<const char * > argv(new const char* [args.size()]);
+    std::unique_ptr<const char * []> argv(new const char* [args.size()]);
     for (int i = 0; i < args.size(); i++) {
       argv[i] = args[i].c_str();
     }
 
     CommandLineInterface cli;
-    cli.SetInputsAreProtoPathRelative(true);
 
     CaptureTestStdout();
     CaptureTestStderr();
@@ -1756,12 +2338,37 @@
   }
 
  private:
+  void WriteUnittestProtoDescriptorSet() {
+    unittest_proto_descriptor_set_filename_ =
+        TestTempDir() + "/unittest_proto_descriptor_set.bin";
+    FileDescriptorSet file_descriptor_set;
+    protobuf_unittest::TestAllTypes test_all_types;
+    test_all_types.descriptor()->file()->CopyTo(file_descriptor_set.add_file());
+
+    protobuf_unittest_import::ImportMessage import_message;
+    import_message.descriptor()->file()->CopyTo(file_descriptor_set.add_file());
+
+
+    protobuf_unittest_import::PublicImportMessage public_import_message;
+    public_import_message.descriptor()->file()->CopyTo(
+        file_descriptor_set.add_file());
+    GOOGLE_DCHECK(file_descriptor_set.IsInitialized());
+
+    string binary_proto;
+    GOOGLE_CHECK(file_descriptor_set.SerializeToString(&binary_proto));
+    GOOGLE_CHECK_OK(File::SetContents(
+        unittest_proto_descriptor_set_filename_,
+        binary_proto,
+        true));
+  }
+
   int duped_stdin_;
   string captured_stdout_;
   string captured_stderr_;
+  string unittest_proto_descriptor_set_filename_;
 };
 
-TEST_F(EncodeDecodeTest, Encode) {
+TEST_P(EncodeDecodeTest, Encode) {
   RedirectStdinFromFile(TestSourceDir() + "/google/protobuf/"
     "testdata/text_format_unittest_data_oneof_implemented.txt");
   EXPECT_TRUE(Run("google/protobuf/unittest.proto "
@@ -1771,7 +2378,7 @@
   ExpectStderrMatchesText("");
 }
 
-TEST_F(EncodeDecodeTest, Decode) {
+TEST_P(EncodeDecodeTest, Decode) {
   RedirectStdinFromFile(TestSourceDir() +
     "/google/protobuf/testdata/golden_message_oneof_implemented");
   EXPECT_TRUE(Run("google/protobuf/unittest.proto "
@@ -1782,7 +2389,7 @@
   ExpectStderrMatchesText("");
 }
 
-TEST_F(EncodeDecodeTest, Partial) {
+TEST_P(EncodeDecodeTest, Partial) {
   RedirectStdinFromText("");
   EXPECT_TRUE(Run("google/protobuf/unittest.proto "
                   "--encode=protobuf_unittest.TestRequired"));
@@ -1791,7 +2398,7 @@
     "warning:  Input message is missing required fields:  a, b, c\n");
 }
 
-TEST_F(EncodeDecodeTest, DecodeRaw) {
+TEST_P(EncodeDecodeTest, DecodeRaw) {
   protobuf_unittest::TestAllTypes message;
   message.set_optional_int32(123);
   message.set_optional_string("foo");
@@ -1805,21 +2412,24 @@
   ExpectStderrMatchesText("");
 }
 
-TEST_F(EncodeDecodeTest, UnknownType) {
+TEST_P(EncodeDecodeTest, UnknownType) {
   EXPECT_FALSE(Run("google/protobuf/unittest.proto "
                    "--encode=NoSuchType"));
   ExpectStdoutMatchesText("");
   ExpectStderrMatchesText("Type not defined: NoSuchType\n");
 }
 
-TEST_F(EncodeDecodeTest, ProtoParseError) {
+TEST_P(EncodeDecodeTest, ProtoParseError) {
   EXPECT_FALSE(Run("google/protobuf/no_such_file.proto "
                    "--encode=NoSuchType"));
   ExpectStdoutMatchesText("");
   ExpectStderrMatchesText(
-    "google/protobuf/no_such_file.proto: File not found.\n");
+      "google/protobuf/no_such_file.proto: No such file or directory\n");
 }
 
+INSTANTIATE_TEST_CASE_P(FileDescriptorSetSource,
+                        EncodeDecodeTest,
+                        testing::Values(PROTO_PATH, DESCRIPTOR_SET_IN));
 }  // anonymous namespace
 
 #endif  // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
index c3e9fe7..4e150fe 100644
--- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -44,16 +44,17 @@
 
 #include <map>
 
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_generator.h>
 #include <google/protobuf/compiler/importer.h>
-#include <google/protobuf/descriptor.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/stubs/map_util.h>
 #include <google/protobuf/stubs/stl_util.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
 
 #include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 
@@ -97,57 +98,70 @@
         File::GetContents(TestSourceDir() + "/" + physical_filename,
                           &actual_contents, true));
     EXPECT_TRUE(actual_contents == *expected_contents)
-      << physical_filename << " needs to be regenerated.  Please run "
-         "google/protobuf/compiler/release_compiler.sh and "
-         "generate_descriptor_proto.sh. Then add this file "
-         "to your CL.";
+        << physical_filename
+        << " needs to be regenerated.  Please run "
+           "generate_descriptor_proto.sh. "
+           "Then add this file to your CL.";
   }
 
   // implements GeneratorContext --------------------------------------
 
   virtual io::ZeroCopyOutputStream* Open(const string& filename) {
     string** map_slot = &files_[filename];
-    if (*map_slot != NULL) delete *map_slot;
+    delete *map_slot;
     *map_slot = new string;
 
     return new io::StringOutputStream(*map_slot);
   }
 
  private:
-  map<string, string*> files_;
+  std::map<string, string*> files_;
 };
 
-TEST(BootstrapTest, GeneratedDescriptorMatches) {
-  MockErrorCollector error_collector;
+const char kDescriptorParameter[] = "dllexport_decl=LIBPROTOBUF_EXPORT";
+const char kPluginParameter[] = "dllexport_decl=LIBPROTOC_EXPORT";
+const char kNormalParameter[] = "";
+
+const char* test_protos[][2] = {
+    {"google/protobuf/descriptor", kDescriptorParameter},
+    {"google/protobuf/compiler/plugin", kPluginParameter},
+};
+
+TEST(BootstrapTest, GeneratedFilesMatch) {
+  // We need a mapping from the actual file to virtual and actual path
+  // of the data to compare to.
+  std::map<string, string> vpath_map;
+  std::map<string, string> rpath_map;
+  rpath_map["third_party/protobuf/src/google/protobuf/test_messages_proto2"] =
+      "net/proto2/z_generated_example/test_messages_proto2";
+  rpath_map["third_party/protobuf/src/google/protobuf/test_messages_proto3"] =
+      "net/proto2/z_generated_example/test_messages_proto3";
+  rpath_map["google/protobuf/proto2_weak"] =
+      "net/proto2/z_generated_example/proto2_weak";
+
   DiskSourceTree source_tree;
   source_tree.MapPath("", TestSourceDir());
-  Importer importer(&source_tree, &error_collector);
-  const FileDescriptor* proto_file =
-    importer.Import("google/protobuf/descriptor.proto");
-  const FileDescriptor* plugin_proto_file =
-    importer.Import("google/protobuf/compiler/plugin.proto");
-  EXPECT_EQ("", error_collector.text_);
-  ASSERT_TRUE(proto_file != NULL);
-  ASSERT_TRUE(plugin_proto_file != NULL);
 
-  CppGenerator generator;
-  MockGeneratorContext context;
-  string error;
-  string parameter = "dllexport_decl=LIBPROTOBUF_EXPORT";
-  ASSERT_TRUE(generator.Generate(proto_file, parameter,
-                                 &context, &error));
-  parameter = "dllexport_decl=LIBPROTOC_EXPORT";
-  ASSERT_TRUE(generator.Generate(plugin_proto_file, parameter,
-                                 &context, &error));
+  for (auto file_parameter : test_protos) {
+    MockErrorCollector error_collector;
+    Importer importer(&source_tree, &error_collector);
+    const FileDescriptor* file =
+        importer.Import(file_parameter[0] + string(".proto"));
+    ASSERT_TRUE(file != nullptr)
+        << "Can't import file " << file_parameter[0] + string(".proto") << "\n";
+    EXPECT_EQ("", error_collector.text_);
+    CppGenerator generator;
+    MockGeneratorContext context;
+    string error;
+    ASSERT_TRUE(generator.Generate(file, file_parameter[1], &context, &error));
 
-  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");
+    string vpath =
+        FindWithDefault(vpath_map, file_parameter[0], file_parameter[0]);
+    string rpath =
+        FindWithDefault(rpath_map, file_parameter[0], file_parameter[0]);
+    context.ExpectFileMatches(vpath + ".pb.cc", rpath + ".pb.cc");
+    context.ExpectFileMatches(vpath + ".pb.h", rpath + ".pb.h");
+  }
 }
 
 }  // namespace
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 1a11bce..0d6a9e2 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -69,20 +69,28 @@
 
 EnumGenerator::~EnumGenerator() {}
 
-void EnumGenerator::FillForwardDeclaration(set<string>* enum_names) {
+void EnumGenerator::FillForwardDeclaration(
+    std::map<string, const EnumDescriptor*>* enum_names) {
   if (!options_.proto_h) {
     return;
   }
-  enum_names->insert(classname_);
+  (*enum_names)[classname_] = descriptor_;
 }
 
 void EnumGenerator::GenerateDefinition(io::Printer* printer) {
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["classname"] = classname_;
   vars["short_name"] = descriptor_->name();
-  vars["enumbase"] = classname_ + (options_.proto_h ? " : int" : "");
+  vars["enumbase"] = options_.proto_h ? " : int" : "";
+  // These variables are placeholders to pick out the beginning and ends of
+  // identifiers for annotations (when doing so with existing variables would
+  // be ambiguous or impossible). They should never be set to anything but the
+  // empty string.
+  vars["{"] = "";
+  vars["}"] = "";
 
-  printer->Print(vars, "enum $enumbase$ {\n");
+  printer->Print(vars, "enum $classname$$enumbase$ {\n");
+  printer->Annotate("classname", descriptor_);
   printer->Indent();
 
   const EnumValueDescriptor* min_value = descriptor_->value(0);
@@ -96,9 +104,12 @@
     vars["number"] = Int32ToString(descriptor_->value(i)->number());
     vars["prefix"] = (descriptor_->containing_type() == NULL) ?
       "" : classname_ + "_";
+    vars["deprecation"] = descriptor_->value(i)->options().deprecated() ?
+        " PROTOBUF_DEPRECATED" : "";
 
     if (i > 0) printer->Print(",\n");
-    printer->Print(vars, "$prefix$$name$ = $number$");
+    printer->Print(vars, "${$$prefix$$name$$}$$deprecation$ = $number$");
+    printer->Annotate("{", "}", descriptor_->value(i));
 
     if (descriptor_->value(i)->number() < min_value->number()) {
       min_value = descriptor_->value(i);
@@ -130,25 +141,32 @@
   }
 
   printer->Print(vars,
-    "$dllexport$bool $classname$_IsValid(int value);\n"
-    "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n"
-    "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n");
+                 "$dllexport$bool $classname$_IsValid(int value);\n"
+                 "const $classname$ ${$$prefix$$short_name$_MIN$}$ = "
+                 "$prefix$$min_name$;\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(vars,
+                 "const $classname$ ${$$prefix$$short_name$_MAX$}$ = "
+                 "$prefix$$max_name$;\n");
+  printer->Annotate("{", "}", descriptor_);
 
   if (generate_array_size_) {
     printer->Print(vars,
-      "const int $prefix$$short_name$_ARRAYSIZE = "
-      "$prefix$$short_name$_MAX + 1;\n\n");
+                   "const int ${$$prefix$$short_name$_ARRAYSIZE$}$ = "
+                   "$prefix$$short_name$_MAX + 1;\n\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
-  if (HasDescriptorMethods(descriptor_->file())) {
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
     printer->Print(vars,
       "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n");
     // The _Name and _Parse methods
-    printer->Print(vars,
-      "inline const ::std::string& $classname$_Name($classname$ value) {\n"
-      "  return ::google::protobuf::internal::NameOfEnum(\n"
-      "    $classname$_descriptor(), value);\n"
-      "}\n");
+    printer->Print(
+        vars,
+        "inline const ::std::string& $classname$_Name($classname$ value) {\n"
+        "  return ::google::protobuf::internal::NameOfEnum(\n"
+        "    $classname$_descriptor(), value);\n"
+        "}\n");
     printer->Print(vars,
       "inline bool $classname$_Parse(\n"
       "    const ::std::string& name, $classname$* value) {\n"
@@ -161,10 +179,10 @@
 void EnumGenerator::
 GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
   printer->Print(
-      "template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type "
+      "template <> struct is_proto_enum< $classname$> : ::std::true_type "
       "{};\n",
       "classname", ClassName(descriptor_, true));
-  if (HasDescriptorMethods(descriptor_->file())) {
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
     printer->Print(
       "template <>\n"
       "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n"
@@ -175,41 +193,54 @@
 }
 
 void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["nested_name"] = descriptor_->name();
   vars["classname"] = classname_;
+  vars["constexpr"] = options_.proto_h ? "constexpr " : "";
+  vars["{"] = "";
+  vars["}"] = "";
   printer->Print(vars, "typedef $classname$ $nested_name$;\n");
 
   for (int j = 0; j < descriptor_->value_count(); j++) {
     vars["tag"] = EnumValueName(descriptor_->value(j));
+    vars["deprecated_attr"] = descriptor_->value(j)->options().deprecated() ?
+      "GOOGLE_PROTOBUF_DEPRECATED_ATTR " : "";
     printer->Print(vars,
-      "static const $nested_name$ $tag$ = $classname$_$tag$;\n");
+      "$deprecated_attr$static $constexpr$const $nested_name$ ${$$tag$$}$ =\n"
+      "  $classname$_$tag$;\n");
+    printer->Annotate("{", "}", descriptor_->value(j));
   }
 
   printer->Print(vars,
     "static inline bool $nested_name$_IsValid(int value) {\n"
     "  return $classname$_IsValid(value);\n"
     "}\n"
-    "static const $nested_name$ $nested_name$_MIN =\n"
-    "  $classname$_$nested_name$_MIN;\n"
-    "static const $nested_name$ $nested_name$_MAX =\n"
+    "static const $nested_name$ ${$$nested_name$_MIN$}$ =\n"
+    "  $classname$_$nested_name$_MIN;\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(vars,
+    "static const $nested_name$ ${$$nested_name$_MAX$}$ =\n"
     "  $classname$_$nested_name$_MAX;\n");
+  printer->Annotate("{", "}", descriptor_);
   if (generate_array_size_) {
     printer->Print(vars,
-      "static const int $nested_name$_ARRAYSIZE =\n"
+      "static const int ${$$nested_name$_ARRAYSIZE$}$ =\n"
       "  $classname$_$nested_name$_ARRAYSIZE;\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
-  if (HasDescriptorMethods(descriptor_->file())) {
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
     printer->Print(vars,
       "static inline const ::google::protobuf::EnumDescriptor*\n"
       "$nested_name$_descriptor() {\n"
       "  return $classname$_descriptor();\n"
       "}\n");
     printer->Print(vars,
-      "static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n"
-      "  return $classname$_Name(value);\n"
-      "}\n");
+                   "static inline const ::std::string& "
+                   "$nested_name$_Name($nested_name$ value) {"
+                   "\n"
+                   "  return $classname$_Name(value);\n"
+                   "}\n");
     printer->Print(vars,
       "static inline bool $nested_name$_Parse(const ::std::string& name,\n"
       "    $nested_name$* value) {\n"
@@ -218,49 +249,38 @@
   }
 }
 
-void EnumGenerator::GenerateDescriptorInitializer(
-    io::Printer* printer, int index) {
-  map<string, string> vars;
+void EnumGenerator::GenerateMethods(int idx, io::Printer* printer) {
+  std::map<string, string> vars;
   vars["classname"] = classname_;
-  vars["index"] = SimpleItoa(index);
+  vars["index_in_metadata"] = SimpleItoa(idx);
+  vars["constexpr"] = options_.proto_h ? "constexpr " : "";
+  vars["file_namespace"] = FileLevelNamespace(descriptor_->file()->name());
 
-  if (descriptor_->containing_type() == NULL) {
-    printer->Print(vars,
-      "$classname$_descriptor_ = file->enum_type($index$);\n");
-  } else {
-    vars["parent"] = ClassName(descriptor_->containing_type(), false);
-    printer->Print(vars,
-      "$classname$_descriptor_ = $parent$_descriptor_->enum_type($index$);\n");
-  }
-}
-
-void EnumGenerator::GenerateMethods(io::Printer* printer) {
-  map<string, string> vars;
-  vars["classname"] = classname_;
-
-  if (HasDescriptorMethods(descriptor_->file())) {
-    printer->Print(vars,
-      "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
-      "  protobuf_AssignDescriptorsOnce();\n"
-      "  return $classname$_descriptor_;\n"
-      "}\n");
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
+    printer->Print(
+        vars,
+        "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
+        "  $file_namespace$::protobuf_AssignDescriptorsOnce();\n"
+        "  return "
+        "$file_namespace$::file_level_enum_descriptors[$index_in_metadata$];\n"
+        "}\n");
   }
 
   printer->Print(vars,
     "bool $classname$_IsValid(int value) {\n"
-    "  switch(value) {\n");
+    "  switch (value) {\n");
 
   // Multiple values may have the same number.  Make sure we only cover
   // each number once by first constructing a set containing all valid
   // numbers, then printing a case statement for each element.
 
-  set<int> numbers;
+  std::set<int> numbers;
   for (int j = 0; j < descriptor_->value_count(); j++) {
     const EnumValueDescriptor* value = descriptor_->value(j);
     numbers.insert(value->number());
   }
 
-  for (set<int>::iterator iter = numbers.begin();
+  for (std::set<int>::iterator iter = numbers.begin();
        iter != numbers.end(); ++iter) {
     printer->Print(
       "    case $number$:\n",
@@ -287,7 +307,7 @@
     for (int i = 0; i < descriptor_->value_count(); i++) {
       vars["value"] = EnumValueName(descriptor_->value(i));
       printer->Print(vars,
-        "const $classname$ $parent$::$value$;\n");
+        "$constexpr$const $classname$ $parent$::$value$;\n");
     }
     printer->Print(vars,
       "const $classname$ $parent$::$nested_name$_MIN;\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h
index f3aa72e..0d2488a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.h
@@ -35,12 +35,12 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
 #define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
 
+#include <map>
 #include <set>
 #include <string>
 #include <google/protobuf/compiler/cpp/cpp_options.h>
 #include <google/protobuf/descriptor.h>
 
-
 namespace google {
 namespace protobuf {
   namespace io {
@@ -55,8 +55,7 @@
 class EnumGenerator {
  public:
   // See generator.cc for the meaning of dllexport_decl.
-  explicit EnumGenerator(const EnumDescriptor* descriptor,
-                         const Options& options);
+  EnumGenerator(const EnumDescriptor* descriptor, const Options& options);
   ~EnumGenerator();
 
   // Header stuff.
@@ -64,8 +63,11 @@
   // Fills the name to use when declaring the enum. This is for use when
   // generating other .proto.h files. This code should be placed within the
   // enum's package namespace, but NOT within any class, even for nested
-  // enums.
-  void FillForwardDeclaration(set<string>* enum_names);
+  // enums. A given key in enum_names will map from an enum class name to the
+  // EnumDescriptor that was responsible for its inclusion in the map. This can
+  // be used to associate the descriptor with the code generated for it.
+  void FillForwardDeclaration(
+      std::map<string, const EnumDescriptor*>* enum_names);
 
   // Generate header code defining the enum.  This code should be placed
   // within the enum's package namespace, but NOT within any class, even for
@@ -84,21 +86,19 @@
 
   // Source file stuff.
 
-  // Generate code that initializes the global variable storing the enum's
-  // descriptor.
-  void GenerateDescriptorInitializer(io::Printer* printer, int index);
-
   // Generate non-inline methods related to the enum, such as IsValidValue().
-  // Goes in the .cc file.
-  void GenerateMethods(io::Printer* printer);
+  // Goes in the .cc file. EnumDescriptors are stored in an array, idx is
+  // the index in this array that corresponds with this enum.
+  void GenerateMethods(int idx, io::Printer* printer);
 
  private:
   const EnumDescriptor* descriptor_;
-  string classname_;
-  Options options_;
+  const string classname_;
+  const Options& options_;
   // whether to generate the *_ARRAYSIZE constant.
-  bool generate_array_size_;
+  const bool generate_array_size_;
 
+  friend class FileGenerator;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
 };
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index 824e220..50c7b5f 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -35,6 +35,7 @@
 #include <google/protobuf/compiler/cpp/cpp_enum_field.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
 
 namespace google {
@@ -45,7 +46,7 @@
 namespace {
 
 void SetEnumVariables(const FieldDescriptor* descriptor,
-                      map<string, string>* variables,
+                      std::map<string, string>* variables,
                       const Options& options) {
   SetCommonFieldVariables(descriptor, variables, options);
   const EnumValueDescriptor* default_value = descriptor->default_value_enum();
@@ -58,10 +59,9 @@
 
 // ===================================================================
 
-EnumFieldGenerator::
-EnumFieldGenerator(const FieldDescriptor* descriptor,
-                   const Options& options)
-  : descriptor_(descriptor) {
+EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
+                                       const Options& options)
+    : FieldGenerator(options), descriptor_(descriptor) {
   SetEnumVariables(descriptor, &variables_, options);
 }
 
@@ -74,27 +74,26 @@
 
 void EnumFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
+  printer->Print(variables_, "$deprecated_attr$$type$ $name$() const;\n");
+  printer->Annotate("name", descriptor_);
   printer->Print(variables_,
-    "$type$ $name$() const$deprecation$;\n"
-    "void set_$name$($type$ value)$deprecation$;\n");
+                 "$deprecated_attr$void ${$set_$name$$}$($type$ value);\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void EnumFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                  bool is_inline) const {
-  map<string, string> variables(variables_);
-  variables["inline"] = is_inline ? "inline" : "";
-  printer->Print(variables,
-    "$inline$ $type$ $classname$::$name$() const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+  printer->Print(variables_,
+    "inline $type$ $classname$::$name$() const {\n"
     "  // @@protoc_insertion_point(field_get:$full_name$)\n"
     "  return static_cast< $type$ >($name$_);\n"
     "}\n"
-    "$inline$ void $classname$::set_$name$($type$ value) {\n");
+    "inline void $classname$::set_$name$($type$ value) {\n");
   if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
-    printer->Print(variables,
+    printer->Print(variables_,
     "  assert($type$_IsValid(value));\n");
   }
-  printer->Print(variables,
+  printer->Print(variables_,
     "  $set_hasbit$\n"
     "  $name$_ = value;\n"
     "  // @@protoc_insertion_point(field_set:$full_name$)\n"
@@ -113,7 +112,7 @@
 
 void EnumFieldGenerator::
 GenerateSwappingCode(io::Printer* printer) const {
-  printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
+  printer->Print(variables_, "swap($name$_, other->$name$_);\n");
 }
 
 void EnumFieldGenerator::
@@ -122,6 +121,11 @@
 }
 
 void EnumFieldGenerator::
+GenerateCopyConstructorCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = from.$name$_;\n");
+}
+
+void EnumFieldGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) const {
   printer->Print(variables_,
     "int value;\n"
@@ -135,15 +139,18 @@
     printer->Print(variables_,
       "if ($type$_IsValid(value)) {\n"
       "  set_$name$(static_cast< $type$ >(value));\n");
-    if (UseUnknownFieldSet(descriptor_->file())) {
+    if (UseUnknownFieldSet(descriptor_->file(), options_)) {
       printer->Print(variables_,
         "} else {\n"
-        "  mutable_unknown_fields()->AddVarint($number$, value);\n");
+        "  mutable_unknown_fields()->AddVarint(\n"
+        "      $number$, static_cast< ::google::protobuf::uint64>(value));\n");
     } else {
       printer->Print(
         "} else {\n"
-        "  unknown_fields_stream.WriteVarint32(tag);\n"
-        "  unknown_fields_stream.WriteVarint32(value);\n");
+        "  unknown_fields_stream.WriteVarint32($tag$u);\n"
+        "  unknown_fields_stream.WriteVarint32(\n"
+        "      static_cast< ::google::protobuf::uint32>(value));\n",
+        "tag", SimpleItoa(internal::WireFormat::MakeTag(descriptor_)));
     }
     printer->Print(variables_,
       "}\n");
@@ -183,36 +190,33 @@
 EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {}
 
 void EnumOneofFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                  bool is_inline) const {
-  map<string, string> variables(variables_);
-  variables["inline"] = is_inline ? "inline" : "";
-  printer->Print(variables,
-    "$inline$ $type$ $classname$::$name$() const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+  printer->Print(variables_,
+    "inline $type$ $classname$::$name$() const {\n"
     "  // @@protoc_insertion_point(field_get:$full_name$)\n"
     "  if (has_$name$()) {\n"
-    "    return static_cast< $type$ >($oneof_prefix$$name$_);\n"
+    "    return static_cast< $type$ >($field_member$);\n"
     "  }\n"
     "  return static_cast< $type$ >($default$);\n"
     "}\n"
-    "$inline$ void $classname$::set_$name$($type$ value) {\n");
+    "inline void $classname$::set_$name$($type$ value) {\n");
   if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
-    printer->Print(variables,
+    printer->Print(variables_,
     "  assert($type$_IsValid(value));\n");
   }
-  printer->Print(variables,
+  printer->Print(variables_,
     "  if (!has_$name$()) {\n"
     "    clear_$oneof_name$();\n"
     "    set_has_$name$();\n"
     "  }\n"
-    "  $oneof_prefix$$name$_ = value;\n"
+    "  $field_member$ = value;\n"
     "  // @@protoc_insertion_point(field_set:$full_name$)\n"
     "}\n");
 }
 
 void EnumOneofFieldGenerator::
 GenerateClearingCode(io::Printer* printer) const {
-  printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n");
+  printer->Print(variables_, "$field_member$ = $default$;\n");
 }
 
 void EnumOneofFieldGenerator::
@@ -223,15 +227,14 @@
 void EnumOneofFieldGenerator::
 GenerateConstructorCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "  $classname$_default_oneof_instance_->$name$_ = $default$;\n");
+                 "$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
 }
 
 // ===================================================================
 
-RepeatedEnumFieldGenerator::
-RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
-                           const Options& options)
-  : descriptor_(descriptor) {
+RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
+    const FieldDescriptor* descriptor, const Options& options)
+    : FieldGenerator(options), descriptor_(descriptor) {
   SetEnumVariables(descriptor, &variables_, options);
 }
 
@@ -241,8 +244,8 @@
 GeneratePrivateMembers(io::Printer* printer) const {
   printer->Print(variables_,
     "::google::protobuf::RepeatedField<int> $name$_;\n");
-  if (descriptor_->is_packed()
-      && HasGeneratedMethods(descriptor_->file())) {
+  if (descriptor_->is_packed() &&
+      HasGeneratedMethods(descriptor_->file(), options_)) {
     printer->Print(variables_,
       "mutable int _$name$_cached_byte_size_;\n");
   }
@@ -251,49 +254,56 @@
 void RepeatedEnumFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
-    "$type$ $name$(int index) const$deprecation$;\n"
-    "void set_$name$(int index, $type$ value)$deprecation$;\n"
-    "void add_$name$($type$ value)$deprecation$;\n");
+                 "$deprecated_attr$$type$ $name$(int index) const;\n");
+  printer->Annotate("name", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecated_attr$void ${$set_$name$$}$(int index, $type$ value);\n");
+  printer->Annotate("{", "}", descriptor_);
   printer->Print(variables_,
-    "const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
-    "::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n");
+                 "$deprecated_attr$void ${$add_$name$$}$($type$ value);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecated_attr$const ::google::protobuf::RepeatedField<int>& $name$() const;\n");
+  printer->Annotate("name", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$::google::protobuf::RepeatedField<int>* "
+                 "${$mutable_$name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedEnumFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                  bool is_inline) const {
-  map<string, string> variables(variables_);
-  variables["inline"] = is_inline ? "inline" : "";
-  printer->Print(variables,
-    "$inline$ $type$ $classname$::$name$(int index) const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+  printer->Print(variables_,
+    "inline $type$ $classname$::$name$(int index) const {\n"
     "  // @@protoc_insertion_point(field_get:$full_name$)\n"
     "  return static_cast< $type$ >($name$_.Get(index));\n"
     "}\n"
-    "$inline$ void $classname$::set_$name$(int index, $type$ value) {\n");
+    "inline void $classname$::set_$name$(int index, $type$ value) {\n");
   if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
-    printer->Print(variables,
+    printer->Print(variables_,
     "  assert($type$_IsValid(value));\n");
   }
-  printer->Print(variables,
+  printer->Print(variables_,
     "  $name$_.Set(index, value);\n"
     "  // @@protoc_insertion_point(field_set:$full_name$)\n"
     "}\n"
-    "$inline$ void $classname$::add_$name$($type$ value) {\n");
+    "inline void $classname$::add_$name$($type$ value) {\n");
   if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
-    printer->Print(variables,
+    printer->Print(variables_,
     "  assert($type$_IsValid(value));\n");
   }
-  printer->Print(variables,
+  printer->Print(variables_,
     "  $name$_.Add(value);\n"
     "  // @@protoc_insertion_point(field_add:$full_name$)\n"
-    "}\n");
-  printer->Print(variables,
-    "$inline$ const ::google::protobuf::RepeatedField<int>&\n"
+    "}\n"
+    "inline const ::google::protobuf::RepeatedField<int>&\n"
     "$classname$::$name$() const {\n"
     "  // @@protoc_insertion_point(field_list:$full_name$)\n"
     "  return $name$_;\n"
     "}\n"
-    "$inline$ ::google::protobuf::RepeatedField<int>*\n"
+    "inline ::google::protobuf::RepeatedField<int>*\n"
     "$classname$::mutable_$name$() {\n"
     "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
     "  return &$name$_;\n"
@@ -312,7 +322,7 @@
 
 void RepeatedEnumFieldGenerator::
 GenerateSwappingCode(io::Printer* printer) const {
-  printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
+  printer->Print(variables_, "$name$_.InternalSwap(&other->$name$_);\n");
 }
 
 void RepeatedEnumFieldGenerator::
@@ -335,15 +345,17 @@
     printer->Print(variables_,
       "if ($type$_IsValid(value)) {\n"
       "  add_$name$(static_cast< $type$ >(value));\n");
-    if (UseUnknownFieldSet(descriptor_->file())) {
+    if (UseUnknownFieldSet(descriptor_->file(), options_)) {
       printer->Print(variables_,
         "} else {\n"
-        "  mutable_unknown_fields()->AddVarint($number$, value);\n");
+        "  mutable_unknown_fields()->AddVarint(\n"
+        "      $number$, static_cast< ::google::protobuf::uint64>(value));\n");
     } else {
       printer->Print(
         "} else {\n"
         "  unknown_fields_stream.WriteVarint32(tag);\n"
-        "  unknown_fields_stream.WriteVarint32(value);\n");
+        "  unknown_fields_stream.WriteVarint32(\n"
+        "      static_cast< ::google::protobuf::uint32>(value));\n");
     }
     printer->Print("}\n");
   }
@@ -362,7 +374,7 @@
         "       NULL,\n"
         "       NULL,\n"
         "       this->mutable_$name$())));\n");
-    } else if (UseUnknownFieldSet(descriptor_->file())) {
+    } else if (UseUnknownFieldSet(descriptor_->file(), options_)) {
       printer->Print(variables_,
         "DO_((::google::protobuf::internal::WireFormat::ReadPackedEnumPreserveUnknowns(\n"
         "       input,\n"
@@ -385,7 +397,7 @@
       "::google::protobuf::uint32 length;\n"
       "DO_(input->ReadVarint32(&length));\n"
       "::google::protobuf::io::CodedInputStream::Limit limit = "
-          "input->PushLimit(length);\n"
+          "input->PushLimit(static_cast<int>(length));\n"
       "while (input->BytesUntilLimit() > 0) {\n"
       "  int value;\n"
       "  DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
@@ -399,13 +411,15 @@
       "  if ($type$_IsValid(value)) {\n"
       "    add_$name$(static_cast< $type$ >(value));\n"
       "  } else {\n");
-      if (UseUnknownFieldSet(descriptor_->file())) {
+      if (UseUnknownFieldSet(descriptor_->file(), options_)) {
         printer->Print(variables_,
-        "    mutable_unknown_fields()->AddVarint($number$, value);\n");
+        "  mutable_unknown_fields()->AddVarint(\n"
+        "      $number$, static_cast< ::google::protobuf::uint64>(value));\n");
       } else {
         printer->Print(variables_,
         "    unknown_fields_stream.WriteVarint32(tag);\n"
-        "    unknown_fields_stream.WriteVarint32(value);\n");
+        "    unknown_fields_stream.WriteVarint32(\n"
+        "        static_cast< ::google::protobuf::uint32>(value));\n");
       }
       printer->Print(
       "  }\n");
@@ -426,11 +440,12 @@
       "    $number$,\n"
       "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
       "    output);\n"
-      "  output->WriteVarint32(_$name$_cached_byte_size_);\n"
+      "  output->WriteVarint32(\n"
+      "      static_cast< ::google::protobuf::uint32>(_$name$_cached_byte_size_));\n"
       "}\n");
   }
   printer->Print(variables_,
-      "for (int i = 0; i < this->$name$_size(); i++) {\n");
+      "for (int i = 0, n = this->$name$_size(); i < n; i++) {\n");
   if (descriptor_->is_packed()) {
     printer->Print(variables_,
       "  ::google::protobuf::internal::WireFormatLite::WriteEnumNoTag(\n"
@@ -454,48 +469,46 @@
       "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
       "    target);\n"
       "  target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray("
-      "    _$name$_cached_byte_size_, target);\n"
-      "}\n");
-  }
-  printer->Print(variables_,
-      "for (int i = 0; i < this->$name$_size(); i++) {\n");
-  if (descriptor_->is_packed()) {
-    printer->Print(variables_,
+      "      static_cast< ::google::protobuf::uint32>(\n"
+      "          _$name$_cached_byte_size_), target);\n"
       "  target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n"
-      "    this->$name$(i), target);\n");
+      "    this->$name$_, target);\n"
+      "}\n");
   } else {
     printer->Print(variables_,
-      "  target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n"
-      "    $number$, this->$name$(i), target);\n");
+      "target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n"
+      "  $number$, this->$name$_, target);\n");
   }
-  printer->Print("}\n");
 }
 
 void RepeatedEnumFieldGenerator::
 GenerateByteSize(io::Printer* printer) const {
   printer->Print(variables_,
     "{\n"
-    "  int data_size = 0;\n");
+    "  size_t data_size = 0;\n"
+    "  unsigned int count = static_cast<unsigned int>(this->$name$_size());");
   printer->Indent();
   printer->Print(variables_,
-      "for (int i = 0; i < this->$name$_size(); i++) {\n"
+      "for (unsigned int i = 0; i < count; i++) {\n"
       "  data_size += ::google::protobuf::internal::WireFormatLite::EnumSize(\n"
-      "    this->$name$(i));\n"
+      "    this->$name$(static_cast<int>(i)));\n"
       "}\n");
 
   if (descriptor_->is_packed()) {
     printer->Print(variables_,
       "if (data_size > 0) {\n"
       "  total_size += $tag_size$ +\n"
-      "    ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
+      "    ::google::protobuf::internal::WireFormatLite::Int32Size(\n"
+      "        static_cast< ::google::protobuf::int32>(data_size));\n"
       "}\n"
+      "int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);\n"
       "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
-      "_$name$_cached_byte_size_ = data_size;\n"
+      "_$name$_cached_byte_size_ = cached_size;\n"
       "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
       "total_size += data_size;\n");
   } else {
     printer->Print(variables_,
-      "total_size += $tag_size$ * this->$name$_size() + data_size;\n");
+      "total_size += ($tag_size$UL * count) + data_size;\n");
   }
   printer->Outdent();
   printer->Print("}\n");
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
index 5b1d01e..d0e87b7 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
@@ -46,19 +46,18 @@
 
 class EnumFieldGenerator : public FieldGenerator {
  public:
-  explicit EnumFieldGenerator(const FieldDescriptor* descriptor,
-                              const Options& options);
+  EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
   ~EnumFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
   void GeneratePrivateMembers(io::Printer* printer) const;
   void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                         bool is_inline) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
@@ -66,7 +65,7 @@
 
  protected:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
@@ -74,13 +73,12 @@
 
 class EnumOneofFieldGenerator : public EnumFieldGenerator {
  public:
-  explicit EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
-                                   const Options& options);
+  EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
+                          const Options& options);
   ~EnumOneofFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                         bool is_inline) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
@@ -91,19 +89,19 @@
 
 class RepeatedEnumFieldGenerator : public FieldGenerator {
  public:
-  explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
-                                      const Options& options);
+  RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+                             const Options& options);
   ~RepeatedEnumFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
   void GeneratePrivateMembers(io::Printer* printer) const;
   void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                         bool is_inline) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateCopyConstructorCode(io::Printer* printer) const {}
   void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
@@ -112,7 +110,7 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
 };
diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc
index c42f162..c416ba1 100644
--- a/src/google/protobuf/compiler/cpp/cpp_extension.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_extension.cc
@@ -35,9 +35,10 @@
 #include <google/protobuf/compiler/cpp/cpp_extension.h>
 #include <map>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/io/printer.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
 
 namespace google {
 namespace protobuf {
@@ -92,7 +93,7 @@
 ExtensionGenerator::~ExtensionGenerator() {}
 
 void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["extendee"     ] = ExtendeeClassName(descriptor_);
   vars["number"       ] = SimpleItoa(descriptor_->number());
   vars["type_traits"  ] = type_traits_;
@@ -119,7 +120,6 @@
     "    ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
     "  $name$;\n"
     );
-
 }
 
 void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
@@ -128,7 +128,7 @@
     ClassName(descriptor_->extension_scope(), false) + "::";
   string name = scope + descriptor_->name();
 
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["extendee"     ] = ExtendeeClassName(descriptor_);
   vars["type_traits"  ] = type_traits_;
   vars["name"         ] = name;
@@ -166,44 +166,6 @@
     "  $name$($constant_name$, $default$);\n");
 }
 
-void ExtensionGenerator::GenerateRegistration(io::Printer* printer) {
-  map<string, string> vars;
-  vars["extendee"   ] = ExtendeeClassName(descriptor_);
-  vars["number"     ] = SimpleItoa(descriptor_->number());
-  vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
-  vars["is_repeated"] = descriptor_->is_repeated() ? "true" : "false";
-  vars["is_packed"  ] = (descriptor_->is_repeated() &&
-                         descriptor_->options().packed())
-                        ? "true" : "false";
-
-  switch (descriptor_->cpp_type()) {
-    case FieldDescriptor::CPPTYPE_ENUM:
-      printer->Print(vars,
-        "::google::protobuf::internal::ExtensionSet::RegisterEnumExtension(\n"
-        "  &$extendee$::default_instance(),\n"
-        "  $number$, $field_type$, $is_repeated$, $is_packed$,\n");
-      printer->Print(
-        "  &$type$_IsValid);\n",
-        "type", ClassName(descriptor_->enum_type(), true));
-      break;
-    case FieldDescriptor::CPPTYPE_MESSAGE:
-      printer->Print(vars,
-        "::google::protobuf::internal::ExtensionSet::RegisterMessageExtension(\n"
-        "  &$extendee$::default_instance(),\n"
-        "  $number$, $field_type$, $is_repeated$, $is_packed$,\n");
-      printer->Print(
-        "  &$type$::default_instance());\n",
-        "type", ClassName(descriptor_->message_type(), true));
-      break;
-    default:
-      printer->Print(vars,
-        "::google::protobuf::internal::ExtensionSet::RegisterExtension(\n"
-        "  &$extendee$::default_instance(),\n"
-        "  $number$, $field_type$, $is_repeated$, $is_packed$);\n");
-      break;
-  }
-}
-
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.h b/src/google/protobuf/compiler/cpp/cpp_extension.h
index 1c1caf1..30236d7 100644
--- a/src/google/protobuf/compiler/cpp/cpp_extension.h
+++ b/src/google/protobuf/compiler/cpp/cpp_extension.h
@@ -67,9 +67,6 @@
   // Source file stuff.
   void GenerateDefinition(io::Printer* printer);
 
-  // Generate code to register the extension.
-  void GenerateRegistration(io::Printer* printer);
-
  private:
   const FieldDescriptor* descriptor_;
   string type_traits_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc
index 8d47d4e..0de20f8 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -34,21 +34,18 @@
 
 #include <google/protobuf/compiler/cpp/cpp_field.h>
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
 #include <google/protobuf/compiler/cpp/cpp_string_field.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/cpp/cpp_enum_field.h>
 #include <google/protobuf/compiler/cpp/cpp_map_field.h>
 #include <google/protobuf/compiler/cpp/cpp_message_field.h>
 #include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/wire_format.h>
 #include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
 
 namespace google {
@@ -59,26 +56,22 @@
 using internal::WireFormat;
 
 void SetCommonFieldVariables(const FieldDescriptor* descriptor,
-                             map<string, string>* variables,
+                             std::map<string, string>* variables,
                              const Options& options) {
+  (*variables)["ns"] = Namespace(descriptor);
   (*variables)["name"] = FieldName(descriptor);
   (*variables)["index"] = SimpleItoa(descriptor->index());
   (*variables)["number"] = SimpleItoa(descriptor->number());
   (*variables)["classname"] = ClassName(FieldScope(descriptor), false);
   (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
-
-  // non_null_ptr_to_name is usable only if has_$name$ is true.  It yields a
-  // pointer that will not be NULL.  Subclasses of FieldGenerator may set
-  // (*variables)["non_null_ptr_to_name"] differently.
-  (*variables)["non_null_ptr_to_name"] =
-      StrCat("&this->", FieldName(descriptor), "()");
+  (*variables)["field_member"] = FieldName(descriptor) + "_";
 
   (*variables)["tag_size"] = SimpleItoa(
     WireFormat::TagSize(descriptor->number(), descriptor->type()));
   (*variables)["deprecation"] = descriptor->options().deprecated()
       ? " PROTOBUF_DEPRECATED" : "";
-
-  (*variables)["cppget"] = "Get";
+  (*variables)["deprecated_attr"] = descriptor->options().deprecated()
+      ? "GOOGLE_PROTOBUF_DEPRECATED_ATTR " : "";
 
   if (HasFieldPresence(descriptor->file())) {
     (*variables)["set_hasbit"] =
@@ -90,18 +83,19 @@
     (*variables)["clear_hasbit"] = "";
   }
 
-  // By default, empty string, so that generic code used for both oneofs and
-  // singular fields can be written.
-  (*variables)["oneof_prefix"] = "";
+  // These variables are placeholders to pick out the beginning and ends of
+  // identifiers for annotations (when doing so with existing variables would
+  // be ambiguous or impossible). They should never be set to anything but the
+  // empty string.
+  (*variables)["{"] = "";
+  (*variables)["}"] = "";
 }
 
 void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
-                                  map<string, string>* variables) {
+                                  std::map<string, string>* variables) {
   const string prefix = descriptor->containing_oneof()->name() + "_.";
-  (*variables)["oneof_prefix"] = prefix;
   (*variables)["oneof_name"] = descriptor->containing_oneof()->name();
-  (*variables)["non_null_ptr_to_name"] =
-      StrCat(prefix, (*variables)["name"], "_");
+  (*variables)["field_member"] = StrCat(prefix, (*variables)["name"], "_");
 }
 
 FieldGenerator::~FieldGenerator() {}
@@ -119,25 +113,29 @@
 }
 
 FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
-                                     const Options& options)
+                                     const Options& options,
+                                     SCCAnalyzer* scc_analyzer)
     : descriptor_(descriptor),
-      field_generators_(
-          new google::protobuf::scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
+      options_(options),
+      field_generators_(descriptor->field_count()) {
   // Construct all the FieldGenerators.
   for (int i = 0; i < descriptor->field_count(); i++) {
-    field_generators_[i].reset(MakeGenerator(descriptor->field(i), options));
+    field_generators_[i].reset(
+        MakeGenerator(descriptor->field(i), options, scc_analyzer));
   }
 }
 
 FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
-                                                 const Options& options) {
+                                                 const Options& options,
+                                                 SCCAnalyzer* scc_analyzer) {
   if (field->is_repeated()) {
     switch (field->cpp_type()) {
       case FieldDescriptor::CPPTYPE_MESSAGE:
         if (field->is_map()) {
           return new MapFieldGenerator(field, options);
         } else {
-          return new RepeatedMessageFieldGenerator(field, options);
+          return new RepeatedMessageFieldGenerator(field, options,
+                                                   scc_analyzer);
         }
       case FieldDescriptor::CPPTYPE_STRING:
         switch (field->options().ctype()) {
@@ -153,7 +151,7 @@
   } else if (field->containing_oneof()) {
     switch (field->cpp_type()) {
       case FieldDescriptor::CPPTYPE_MESSAGE:
-        return new MessageOneofFieldGenerator(field, options);
+        return new MessageOneofFieldGenerator(field, options, scc_analyzer);
       case FieldDescriptor::CPPTYPE_STRING:
         switch (field->options().ctype()) {
           default:  // StringOneofFieldGenerator handles unknown ctypes.
@@ -168,7 +166,7 @@
   } else {
     switch (field->cpp_type()) {
       case FieldDescriptor::CPPTYPE_MESSAGE:
-        return new MessageFieldGenerator(field, options);
+        return new MessageFieldGenerator(field, options, scc_analyzer);
       case FieldDescriptor::CPPTYPE_STRING:
         switch (field->options().ctype()) {
           default:  // StringFieldGenerator handles unknown ctypes.
@@ -191,7 +189,6 @@
   return *field_generators_[field->index()];
 }
 
-
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index 1d7f823..8cdbe88 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -37,13 +37,11 @@
 
 #include <map>
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 #include <string>
 
-#include <google/protobuf/descriptor.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/descriptor.h>
 
 namespace google {
 namespace protobuf {
@@ -61,15 +59,15 @@
 // ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size',
 // 'deprecation'].
 void SetCommonFieldVariables(const FieldDescriptor* descriptor,
-                             map<string, string>* variables,
+                             std::map<string, string>* variables,
                              const Options& options);
 
 void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
-                                  map<string, string>* variables);
+                                  std::map<string, string>* variables);
 
 class FieldGenerator {
  public:
-  FieldGenerator() {}
+  explicit FieldGenerator(const Options& options) : options_(options) {}
   virtual ~FieldGenerator();
 
   // Generate lines of code declaring members fields of the message class
@@ -82,52 +80,36 @@
   // implementation is empty.
   virtual void GenerateStaticMembers(io::Printer* /*printer*/) const {}
 
-  // Generate prototypes for accessors that will manipulate imported
-  // messages inline.  These are for .proto.h headers.
-  //
-  // In .proto.h mode, the headers of imports are not #included. However,
-  // functions that manipulate the imported message types need access to
-  // the class definition of the imported message, meaning that the headers
-  // must be #included. To get around this, functions that manipulate
-  // imported message objects are defined as dependent functions in a base
-  // template class. By making them dependent template functions, the
-  // function templates will not be instantiated until they are called, so
-  // we can defer to those translation units to #include the necessary
-  // generated headers.
-  //
-  // See:
-  // http://en.cppreference.com/w/cpp/language/class_template#Implicit_instantiation
-  //
-  // Most field types don't need this, so the default implementation is empty.
-  virtual void GenerateDependentAccessorDeclarations(
-      io::Printer* printer) const {}
-
   // Generate prototypes for all of the accessor functions related to this
   // field.  These are placed inside the class definition.
   virtual void GenerateAccessorDeclarations(io::Printer* printer) const = 0;
 
-  // Generate inline definitions of depenent accessor functions for this field.
-  // These are placed inside the header after all class definitions.
-  virtual void GenerateDependentInlineAccessorDefinitions(
-    io::Printer* printer) const {}
-
   // Generate inline definitions of accessor functions for this field.
   // These are placed inside the header after all class definitions.
-  // In non-.proto.h mode, this generates dependent accessor functions as well.
   virtual void GenerateInlineAccessorDefinitions(
-    io::Printer* printer, bool is_inline) const = 0;
+      io::Printer* printer) const = 0;
 
   // Generate definitions of accessors that aren't inlined.  These are
   // placed somewhere in the .cc file.
   // Most field types don't need this, so the default implementation is empty.
   virtual void GenerateNonInlineAccessorDefinitions(
-    io::Printer* /*printer*/) const {}
+      io::Printer* /*printer*/) const {}
 
   // Generate lines of code (statements, not declarations) which clear the
-  // field.  This is used to define the clear_$name$() method as well as
-  // the Clear() method for the whole message.
+  // field.  This is used to define the clear_$name$() method
   virtual void GenerateClearingCode(io::Printer* printer) const = 0;
 
+  // Generate lines of code (statements, not declarations) which clear the field
+  // as part of the Clear() method for the whole message.  For message types
+  // which have field presence bits, MessageGenerator::GenerateClear will have
+  // already checked the presence bits.
+  //
+  // Since most field types can re-use GenerateClearingCode, this method is not
+  // pure virtual.
+  virtual void GenerateMessageClearingCode(io::Printer* printer) const {
+    GenerateClearingCode(printer);
+  }
+
   // Generate lines of code (statements, not declarations) which merges the
   // contents of the field from the current message to the target message,
   // which is stored in the generated code variable "from".
@@ -136,6 +118,9 @@
   // GenerateMergeFrom method.
   virtual void GenerateMergingCode(io::Printer* printer) const = 0;
 
+  // Generates a copy constructor
+  virtual void GenerateCopyConstructorCode(io::Printer* printer) const = 0;
+
   // Generate lines of code (statements, not declarations) which swaps
   // this field and the corresponding field of another message, which
   // is stored in the generated code variable "other". This is used to
@@ -167,14 +152,14 @@
   virtual void GenerateDefaultInstanceAllocator(io::Printer* /*printer*/)
       const {}
 
-  // Generate code that should be run when ShutdownProtobufLibrary() is called,
-  // to delete all dynamically-allocated objects.
-  virtual void GenerateShutdownCode(io::Printer* /*printer*/) const {}
-
   // Generate lines to decode this field, which will be placed inside the
   // message's MergeFromCodedStream() method.
   virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0;
 
+  // Returns true if this field's "MergeFromCodedStream" code needs the arena
+  // to be defined as a variable.
+  virtual bool MergeFromCodedStreamNeedsArena() const { return false; }
+
   // Generate lines to decode this field from a packed value, which will be
   // placed inside the message's MergeFromCodedStream() method.
   virtual void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer)
@@ -194,6 +179,14 @@
   // are placed in the message's ByteSize() method.
   virtual void GenerateByteSize(io::Printer* printer) const = 0;
 
+  // Any tags about field layout decisions (such as inlining) to embed in the
+  // offset.
+  virtual uint32 CalculateFieldTag() const { return 0; }
+  virtual bool IsInlined() const { return false; }
+
+ protected:
+  const Options& options_;
+
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
 };
@@ -201,22 +194,24 @@
 // Convenience class which constructs FieldGenerators for a Descriptor.
 class FieldGeneratorMap {
  public:
-  explicit FieldGeneratorMap(const Descriptor* descriptor, const Options& options);
+  FieldGeneratorMap(const Descriptor* descriptor, const Options& options,
+                    SCCAnalyzer* scc_analyzer);
   ~FieldGeneratorMap();
 
   const FieldGenerator& get(const FieldDescriptor* field) const;
 
  private:
   const Descriptor* descriptor_;
-  google::protobuf::scoped_array<google::protobuf::scoped_ptr<FieldGenerator> > field_generators_;
+  const Options& options_;
+  std::vector<std::unique_ptr<FieldGenerator>> field_generators_;
 
   static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
-                                       const Options& options);
+                                       const Options& options,
+                                       SCCAnalyzer* scc_analyzer);
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
 };
 
-
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index 37e4bae..4252568 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -35,19 +35,17 @@
 #include <google/protobuf/compiler/cpp/cpp_file.h>
 #include <map>
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 #include <set>
+#include <vector>
 
 #include <google/protobuf/compiler/cpp/cpp_enum.h>
-#include <google/protobuf/compiler/cpp/cpp_service.h>
 #include <google/protobuf/compiler/cpp/cpp_extension.h>
+#include <google/protobuf/compiler/cpp/cpp_field.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_message.h>
-#include <google/protobuf/compiler/cpp/cpp_field.h>
-#include <google/protobuf/io/printer.h>
+#include <google/protobuf/compiler/cpp/cpp_service.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
 #include <google/protobuf/stubs/strutil.h>
 
 namespace google {
@@ -55,142 +53,102 @@
 namespace compiler {
 namespace cpp {
 
-// ===================================================================
-
 FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
     : file_(file),
-      message_generators_(
-          new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]),
-      enum_generators_(
-          new google::protobuf::scoped_ptr<EnumGenerator>[file->enum_type_count()]),
-      service_generators_(
-          new google::protobuf::scoped_ptr<ServiceGenerator>[file->service_count()]),
-      extension_generators_(
-          new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]),
-      options_(options) {
-
-  for (int i = 0; i < file->message_type_count(); i++) {
-    message_generators_[i].reset(
-      new MessageGenerator(file->message_type(i), options));
+      options_(options),
+      scc_analyzer_(options),
+      enum_generators_owner_(
+          new std::unique_ptr<EnumGenerator>[file->enum_type_count()]),
+      service_generators_owner_(
+          new std::unique_ptr<ServiceGenerator>[file->service_count()]),
+      extension_generators_owner_(
+          new std::unique_ptr<ExtensionGenerator>[file->extension_count()]) {
+  std::vector<const Descriptor*> msgs = FlattenMessagesInFile(file);
+  for (int i = 0; i < msgs.size(); i++) {
+    // Deleted in destructor
+    MessageGenerator* msg_gen =
+        new MessageGenerator(msgs[i], i, options, &scc_analyzer_);
+    message_generators_.push_back(msg_gen);
+    msg_gen->AddGenerators(&enum_generators_, &extension_generators_);
   }
 
   for (int i = 0; i < file->enum_type_count(); i++) {
-    enum_generators_[i].reset(
-      new EnumGenerator(file->enum_type(i), options));
+    enum_generators_owner_[i].reset(
+        new EnumGenerator(file->enum_type(i), options));
+    enum_generators_.push_back(enum_generators_owner_[i].get());
   }
 
   for (int i = 0; i < file->service_count(); i++) {
-    service_generators_[i].reset(
-      new ServiceGenerator(file->service(i), options));
+    service_generators_owner_[i].reset(
+        new ServiceGenerator(file->service(i), options));
+    service_generators_.push_back(service_generators_owner_[i].get());
+  }
+  if (HasGenericServices(file_, options_)) {
+    for (int i = 0; i < service_generators_.size(); i++) {
+      service_generators_[i]->index_in_metadata_ = i;
+    }
   }
 
   for (int i = 0; i < file->extension_count(); i++) {
-    extension_generators_[i].reset(
-      new ExtensionGenerator(file->extension(i), options));
+    extension_generators_owner_[i].reset(
+        new ExtensionGenerator(file->extension(i), options));
+    extension_generators_.push_back(extension_generators_owner_[i].get());
   }
 
-  SplitStringUsing(file_->package(), ".", &package_parts_);
+
+  package_parts_ = Split(file_->package(), ".", true);
 }
 
-FileGenerator::~FileGenerator() {}
+FileGenerator::~FileGenerator() {
+  for (int i = 0; i < message_generators_.size(); i++) {
+    delete message_generators_[i];
+  }
+}
 
-void FileGenerator::GenerateProtoHeader(io::Printer* printer) {
-  if (!options_.proto_h) {
+void FileGenerator::GenerateMacroUndefs(io::Printer* printer) {
+  // Only do this for protobuf's own types. There are some google3 protos using
+  // macros as field names and the generated code compiles after the macro
+  // expansion. Undefing these macros actually breaks such code.
+  if (file_->name() != "google/protobuf/compiler/plugin.proto") {
     return;
   }
-
-  string filename_identifier = FilenameIdentifier(file_->name());
-  GenerateTopHeaderGuard(printer, filename_identifier);
-
-
-  GenerateLibraryIncludes(printer);
-
-  for (int i = 0; i < file_->public_dependency_count(); i++) {
-    const FileDescriptor* dep = file_->public_dependency(i);
-    const char* extension = ".proto.h";
-    string dependency = StripProto(dep->name()) + extension;
-    printer->Print(
-      "#include \"$dependency$\"  // IWYU pragma: export\n",
-      "dependency", dependency);
+  std::vector<string> names_to_undef;
+  std::vector<const FieldDescriptor*> fields;
+  ListAllFields(file_, &fields);
+  for (int i = 0; i < fields.size(); i++) {
+    const string& name = fields[i]->name();
+    static const char* kMacroNames[] = {"major", "minor"};
+    for (int i = 0; i < GOOGLE_ARRAYSIZE(kMacroNames); ++i) {
+      if (name == kMacroNames[i]) {
+        names_to_undef.push_back(name);
+        break;
+      }
+    }
   }
+  for (int i = 0; i < names_to_undef.size(); ++i) {
+    printer->Print(
+        "#ifdef $name$\n"
+        "#undef $name$\n"
+        "#endif\n",
+        "name", names_to_undef[i]);
+  }
+}
 
+void FileGenerator::GenerateHeader(io::Printer* printer) {
   printer->Print(
     "// @@protoc_insertion_point(includes)\n");
 
-
-  GenerateForwardDeclarations(printer);
-
-  // Open namespace.
-  GenerateNamespaceOpeners(printer);
+  printer->Print("#define PROTOBUF_INTERNAL_EXPORT_$filename$ $export$\n",
+                 "filename", FileLevelNamespace(file_),
+                 "export", options_.dllexport_decl);
+  GenerateMacroUndefs(printer);
 
   GenerateGlobalStateFunctionDeclarations(printer);
 
-  printer->Print("\n");
+  GenerateForwardDeclarations(printer);
 
-  GenerateEnumDefinitions(printer);
-
-  printer->Print(kThickSeparator);
-  printer->Print("\n");
-
-  GenerateMessageDefinitions(printer);
-
-  printer->Print("\n");
-  printer->Print(kThickSeparator);
-  printer->Print("\n");
-
-  GenerateServiceDefinitions(printer);
-
-  GenerateExtensionIdentifiers(printer);
-
-  printer->Print("\n");
-  printer->Print(kThickSeparator);
-  printer->Print("\n");
-
-  GenerateInlineFunctionDefinitions(printer);
-
-  printer->Print(
-    "\n"
-    "// @@protoc_insertion_point(namespace_scope)\n"
-    "\n");
-
-  // Close up namespace.
-  GenerateNamespaceClosers(printer);
-
-  // We need to specialize some templates in the ::google::protobuf namespace:
-  GenerateProto2NamespaceEnumSpecializations(printer);
-
-  printer->Print(
-    "\n"
-    "// @@protoc_insertion_point(global_scope)\n"
-    "\n");
-
-  GenerateBottomHeaderGuard(printer, filename_identifier);
-}
-
-void FileGenerator::GeneratePBHeader(io::Printer* printer) {
-  string filename_identifier =
-      FilenameIdentifier(file_->name() + (options_.proto_h ? ".pb.h" : ""));
-  GenerateTopHeaderGuard(printer, filename_identifier);
-
-  if (options_.proto_h) {
-    printer->Print("#include \"$basename$.proto.h\"  // IWYU pragma: export\n",
-                   "basename", StripProto(file_->name()));
-  } else {
-    GenerateLibraryIncludes(printer);
-  }
-  GenerateDependencyIncludes(printer);
-
-  printer->Print(
-    "// @@protoc_insertion_point(includes)\n");
-
-
-
-  // Open namespace.
-  GenerateNamespaceOpeners(printer);
-
-  if (!options_.proto_h) {
-    GenerateGlobalStateFunctionDeclarations(printer);
-    GenerateMessageForwardDeclarations(printer);
+  {
+    NamespaceOpener ns(Namespace(file_), printer);
 
     printer->Print("\n");
 
@@ -214,60 +172,119 @@
     printer->Print("\n");
 
     GenerateInlineFunctionDefinitions(printer);
+
+    printer->Print(
+      "\n"
+      "// @@protoc_insertion_point(namespace_scope)\n"
+      "\n");
   }
 
-  printer->Print(
-    "\n"
-    "// @@protoc_insertion_point(namespace_scope)\n");
-
-  // Close up namespace.
-  GenerateNamespaceClosers(printer);
-
-  if (!options_.proto_h) {
-    // We need to specialize some templates in the ::google::protobuf namespace:
-    GenerateProto2NamespaceEnumSpecializations(printer);
-  }
+  // We need to specialize some templates in the ::google::protobuf namespace:
+  GenerateProto2NamespaceEnumSpecializations(printer);
 
   printer->Print(
     "\n"
     "// @@protoc_insertion_point(global_scope)\n"
     "\n");
+}
+
+void FileGenerator::GenerateProtoHeader(io::Printer* printer,
+                                        const string& info_path) {
+  if (!options_.proto_h) {
+    return;
+  }
+
+  string filename_identifier = FilenameIdentifier(file_->name());
+  GenerateTopHeaderGuard(printer, filename_identifier);
+
+
+  GenerateLibraryIncludes(printer);
+
+  for (int i = 0; i < file_->public_dependency_count(); i++) {
+    const FileDescriptor* dep = file_->public_dependency(i);
+    const char* extension = ".proto.h";
+    string dependency = StripProto(dep->name()) + extension;
+    printer->Print(
+      "#include \"$dependency$\"  // IWYU pragma: export\n",
+      "dependency", dependency);
+  }
+
+  GenerateMetadataPragma(printer, info_path);
+
+  GenerateHeader(printer);
 
   GenerateBottomHeaderGuard(printer, filename_identifier);
 }
 
-void FileGenerator::GenerateSource(io::Printer* printer) {
-  bool well_known = IsWellKnownMessage(file_);
-  string header =
-      StripProto(file_->name()) + (options_.proto_h ? ".proto.h" : ".pb.h");
+void FileGenerator::GeneratePBHeader(io::Printer* printer,
+                                     const string& info_path) {
+  string filename_identifier =
+      FilenameIdentifier(file_->name() + (options_.proto_h ? ".pb.h" : ""));
+  GenerateTopHeaderGuard(printer, filename_identifier);
+
+  if (options_.proto_h) {
+    string target_basename = StripProto(file_->name());
+    printer->Print("#include \"$basename$.proto.h\"  // IWYU pragma: export\n",
+                   "basename", target_basename);
+  } else {
+    GenerateLibraryIncludes(printer);
+  }
+
+  GenerateDependencyIncludes(printer);
+  GenerateMetadataPragma(printer, info_path);
+
+  if (!options_.proto_h) {
+    GenerateHeader(printer);
+  } else {
+    // This is unfortunately necessary for some plugins. I don't see why we
+    // need two of the same insertion points.
+    // TODO(gerbens) remove this.
+    printer->Print(
+      "// @@protoc_insertion_point(includes)\n");
+    {
+      NamespaceOpener ns(Namespace(file_), printer);
+      printer->Print(
+        "\n"
+        "// @@protoc_insertion_point(namespace_scope)\n");
+    }
+    printer->Print(
+      "\n"
+      "// @@protoc_insertion_point(global_scope)\n"
+      "\n");
+  }
+
+  GenerateBottomHeaderGuard(printer, filename_identifier);
+}
+
+void FileGenerator::GenerateSourceIncludes(io::Printer* printer) {
+  string target_basename = StripProto(file_->name());
+  const bool use_system_include = IsWellKnownMessage(file_);
+
+  string header = target_basename + (options_.proto_h ? ".proto.h" : ".pb.h");
   printer->Print(
     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
     "// source: $filename$\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"
     "#include $left$$header$$right$\n"
     "\n"
     "#include <algorithm>\n"    // for swap()
     "\n"
     "#include <google/protobuf/stubs/common.h>\n"
     "#include <google/protobuf/stubs/port.h>\n"
-    "#include <google/protobuf/stubs/once.h>\n"
     "#include <google/protobuf/io/coded_stream.h>\n"
     "#include <google/protobuf/wire_format_lite_inl.h>\n",
     "filename", file_->name(),
     "header", header,
-    "left", well_known ? "<" : "\"",
-    "right", well_known ? ">" : "\"");
+    "left", use_system_include ? "<" : "\"",
+    "right", use_system_include ? ">" : "\"");
 
   // Unknown fields implementation in lite mode uses StringOutputStream
-  if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
+  if (!UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) {
     printer->Print(
       "#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n");
   }
 
-  if (HasDescriptorMethods(file_)) {
+  if (HasDescriptorMethods(file_, options_)) {
     printer->Print(
       "#include <google/protobuf/descriptor.h>\n"
       "#include <google/protobuf/generated_message_reflection.h>\n"
@@ -280,102 +297,286 @@
     for (int i = 0; i < file_->dependency_count(); i++) {
       const FileDescriptor* dep = file_->dependency(i);
       const char* extension = ".proto.h";
-      string dependency = StripProto(dep->name()) + extension;
+      string basename = StripProto(dep->name());
+      string dependency = basename + extension;
       printer->Print(
           "#include \"$dependency$\"\n",
           "dependency", dependency);
     }
   }
 
+  // TODO(gerbens) Remove this when all code in google is using the same
+  // proto library. This is a temporary hack to force build errors if
+  // the proto library is compiled with GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
+  // and is also linking internal proto2. This is to prevent regressions while
+  // we work cleaning up the code base. After this is completed and we have
+  // one proto lib all code uses this should be removed.
+  printer->Print(
+    "// This is a temporary google only hack\n"
+    "#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS\n"
+    "#include \"third_party/protobuf/version.h\"\n"
+    "#endif\n");
+
   printer->Print(
     "// @@protoc_insertion_point(includes)\n");
+}
 
-  GenerateNamespaceOpeners(printer);
+void FileGenerator::GenerateSourceDefaultInstance(int idx,
+                                                  io::Printer* printer) {
+  printer->Print(
+      "class $classname$DefaultTypeInternal {\n"
+      " public:\n"
+      "  ::google::protobuf::internal::ExplicitlyConstructed<$classname$>\n"
+      "      _instance;\n",
+      "classname", message_generators_[idx]->classname_);
+  printer->Indent();
+  message_generators_[idx]->GenerateExtraDefaultFields(printer);
+  printer->Outdent();
+  printer->Print("} _$classname$_default_instance_;\n", "classname",
+                 message_generators_[idx]->classname_);
+}
 
-  if (HasDescriptorMethods(file_)) {
-    printer->Print(
-      "\n"
-      "namespace {\n"
-      "\n");
-    for (int i = 0; i < file_->message_type_count(); i++) {
-      message_generators_[i]->GenerateDescriptorDeclarations(printer);
+namespace {
+
+// Generates weak symbol declarations for types that are to be considered weakly
+// referenced.
+void GenerateInternalForwardDeclarations(
+    const std::vector<const FieldDescriptor*>& fields, const Options& options,
+    SCCAnalyzer* scc_analyzer, io::Printer* printer) {
+  // To ensure determinism and minimize the number of namespace statements,
+  // we output the forward declarations sorted on namespace and type / function
+  // name.
+  std::set<std::pair<string, string> > messages;
+  std::set<std::pair<string, string> > sccs;
+  std::set<std::pair<string, string> > inits;
+  for (int i = 0; i < fields.size(); ++i) {
+    const FieldDescriptor* field = fields[i];
+    const Descriptor* msg = field->message_type();
+    if (msg == nullptr) continue;
+    bool is_weak = IsImplicitWeakField(field, options, scc_analyzer);
+    string flns = FileLevelNamespace(msg);
+    auto scc = scc_analyzer->GetSCC(msg);
+    string repr = ClassName(scc->GetRepresentative());
+    string weak_attr;
+    if (is_weak) {
+      inits.insert(std::make_pair(flns, "AddDescriptors"));
+      messages.insert(std::make_pair(Namespace(msg), ClassName(msg)));
+      weak_attr = " __attribute__((weak))";
     }
-    for (int i = 0; i < file_->enum_type_count(); i++) {
-      printer->Print(
-        "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
-        "name", ClassName(file_->enum_type(i), false));
-    }
-
-    if (HasGenericServices(file_)) {
-      for (int i = 0; i < file_->service_count(); i++) {
-        printer->Print(
-          "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
-          "name", file_->service(i)->name());
-      }
-    }
-
-    printer->Print(
-      "\n"
-      "}  // namespace\n"
-      "\n");
+    string dllexport = "PROTOBUF_INTERNAL_EXPORT_" + FileLevelNamespace(msg);
+    sccs.insert(std::make_pair(flns, "extern " + dllexport + weak_attr +
+                                     " ::google::protobuf::internal::SCCInfo<" +
+                                     SimpleItoa(scc->children.size()) +
+                                     "> scc_info_" + repr + ";\n"));
   }
 
-  // Define our externally-visible BuildDescriptors() function.  (For the lite
-  // library, all this does is initialize default instances.)
-  GenerateBuildDescriptors(printer);
+  printer->Print("\n");
+  NamespaceOpener ns(printer);
+  for (std::set<std::pair<string, string> >::const_iterator it =
+           messages.begin();
+       it != messages.end(); ++it) {
+    ns.ChangeTo(it->first);
+    printer->Print(
+        "extern __attribute__((weak)) $classname$DefaultTypeInternal "
+        "_$classname$_default_instance_;\n",
+        "classname", it->second);
+  }
+  for (std::set<std::pair<string, string> >::const_iterator it = inits.begin();
+       it != inits.end(); ++it) {
+    ns.ChangeTo(it->first);
+    printer->Print("void $name$() __attribute__((weak));\n",
+                   "name", it->second);
+  }
+  for (const auto& p : sccs) {
+    ns.ChangeTo(p.first);
+    printer->Print(p.second.c_str());
+  }
+}
+
+}  // namespace
+
+void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) {
+  GenerateSourceIncludes(printer);
+
+  // Generate weak declarations. We do this for the whole strongly-connected
+  // component (SCC), because we have a single InitDefaults* function for the
+  // SCC.
+  std::vector<const FieldDescriptor*> fields;
+  for (const Descriptor* message :
+       scc_analyzer_.GetSCC(message_generators_[idx]->descriptor_)
+           ->descriptors) {
+    ListAllFields(message, &fields);
+  }
+  GenerateInternalForwardDeclarations(fields, options_, &scc_analyzer_,
+                                      printer);
+
+  if (IsSCCRepresentative(message_generators_[idx]->descriptor_)) {
+    NamespaceOpener ns(FileLevelNamespace(file_), printer);
+    GenerateInitForSCC(GetSCC(message_generators_[idx]->descriptor_), printer);
+  }
+
+  {  // package namespace
+    NamespaceOpener ns(Namespace(file_), printer);
+
+    // Define default instances
+    GenerateSourceDefaultInstance(idx, printer);
+    if (options_.lite_implicit_weak_fields) {
+      printer->Print("void $classname$_ReferenceStrong() {}\n", "classname",
+                     message_generators_[idx]->classname_);
+    }
+
+    // Generate classes.
+    printer->Print("\n");
+    message_generators_[idx]->GenerateClassMethods(printer);
+
+    printer->Print(
+        "\n"
+        "// @@protoc_insertion_point(namespace_scope)\n");
+  }  // end package namespace
+
+  printer->Print(
+      "namespace google {\nnamespace protobuf {\n");
+  message_generators_[idx]->GenerateSourceInProto2Namespace(printer);
+  printer->Print(
+      "}  // namespace protobuf\n}  // namespace google\n");
+
+  printer->Print(
+      "\n"
+      "// @@protoc_insertion_point(global_scope)\n");
+}
+
+void FileGenerator::GenerateGlobalSource(io::Printer* printer) {
+  GenerateSourceIncludes(printer);
+
+  {
+    NamespaceOpener ns(FileLevelNamespace(file_), printer);
+    GenerateTables(printer);
+
+    // Define the code to initialize reflection. This code uses a global
+    // constructor to register reflection data with the runtime pre-main.
+    if (HasDescriptorMethods(file_, options_)) {
+      GenerateReflectionInitializationCode(printer);
+    }
+  }
+
+  NamespaceOpener ns(Namespace(file_), printer);
 
   // Generate enums.
-  for (int i = 0; i < file_->enum_type_count(); i++) {
-    enum_generators_[i]->GenerateMethods(printer);
+  for (int i = 0; i < enum_generators_.size(); i++) {
+    enum_generators_[i]->GenerateMethods(i, printer);
   }
 
-  // Generate classes.
-  for (int i = 0; i < file_->message_type_count(); i++) {
-    if (i == 0 && HasGeneratedMethods(file_)) {
-      printer->Print(
-          "\n"
-          "namespace {\n"
-          "\n"
-          "static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;\n"
-          "static void MergeFromFail(int line) {\n"
-          "  GOOGLE_CHECK(false) << __FILE__ << \":\" << line;\n"
-          "}\n"
-          "\n"
-          "}  // namespace\n"
-          "\n");
-    }
-    printer->Print("\n");
-    printer->Print(kThickSeparator);
-    printer->Print("\n");
-    message_generators_[i]->GenerateClassMethods(printer);
-
-    printer->Print("#if PROTOBUF_INLINE_NOT_IN_HEADERS\n");
-    // Generate class inline methods.
-    message_generators_[i]->GenerateInlineMethods(printer,
-                                                  /* is_inline = */ false);
-    printer->Print("#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS\n");
+  // Define extensions.
+  for (int i = 0; i < extension_generators_.size(); i++) {
+    extension_generators_[i]->GenerateDefinition(printer);
   }
 
-  if (HasGenericServices(file_)) {
+  if (HasGenericServices(file_, options_)) {
     // Generate services.
-    for (int i = 0; i < file_->service_count(); i++) {
+    for (int i = 0; i < service_generators_.size(); i++) {
       if (i == 0) printer->Print("\n");
       printer->Print(kThickSeparator);
       printer->Print("\n");
       service_generators_[i]->GenerateImplementation(printer);
     }
   }
+}
 
-  // Define extensions.
-  for (int i = 0; i < file_->extension_count(); i++) {
-    extension_generators_[i]->GenerateDefinition(printer);
+void FileGenerator::GenerateSource(io::Printer* printer) {
+  GenerateSourceIncludes(printer);
+  std::vector<const FieldDescriptor*> fields;
+  ListAllFields(file_, &fields);
+  GenerateInternalForwardDeclarations(fields, options_, &scc_analyzer_,
+                                      printer);
+
+  {
+    NamespaceOpener ns(Namespace(file_), printer);
+
+    // Define default instances
+    for (int i = 0; i < message_generators_.size(); i++) {
+      GenerateSourceDefaultInstance(i, printer);
+      if (options_.lite_implicit_weak_fields) {
+        printer->Print("void $classname$_ReferenceStrong() {}\n", "classname",
+                       message_generators_[i]->classname_);
+      }
+    }
+  }
+
+  {
+    NamespaceOpener ns(FileLevelNamespace(file_), printer);
+    GenerateTables(printer);
+
+    // Now generate the InitDefaults for each SCC.
+    for (int i = 0; i < message_generators_.size(); i++) {
+      if (IsSCCRepresentative(message_generators_[i]->descriptor_)) {
+        GenerateInitForSCC(GetSCC(message_generators_[i]->descriptor_),
+                           printer);
+      }
+    }
+
+    printer->Print("void InitDefaults() {\n");
+    for (int i = 0; i < message_generators_.size(); i++) {
+      if (!IsSCCRepresentative(message_generators_[i]->descriptor_)) continue;
+      string scc_name = ClassName(message_generators_[i]->descriptor_);
+      printer->Print(
+          "  ::google::protobuf::internal::InitSCC(&scc_info_$scc_name$.base);\n",
+          "scc_name", scc_name);
+    }
+    printer->Print("}\n\n");
+
+    // Define the code to initialize reflection. This code uses a global
+    // constructor to register reflection data with the runtime pre-main.
+    if (HasDescriptorMethods(file_, options_)) {
+      GenerateReflectionInitializationCode(printer);
+    }
+  }
+
+
+  {
+    NamespaceOpener ns(Namespace(file_), printer);
+
+    // Actually implement the protos
+
+    // Generate enums.
+    for (int i = 0; i < enum_generators_.size(); i++) {
+      enum_generators_[i]->GenerateMethods(i, printer);
+    }
+
+    // Generate classes.
+    for (int i = 0; i < message_generators_.size(); i++) {
+      printer->Print("\n");
+      printer->Print(kThickSeparator);
+      printer->Print("\n");
+      message_generators_[i]->GenerateClassMethods(printer);
+    }
+
+    if (HasGenericServices(file_, options_)) {
+      // Generate services.
+      for (int i = 0; i < service_generators_.size(); i++) {
+        if (i == 0) printer->Print("\n");
+        printer->Print(kThickSeparator);
+        printer->Print("\n");
+        service_generators_[i]->GenerateImplementation(printer);
+      }
+    }
+
+    // Define extensions.
+    for (int i = 0; i < extension_generators_.size(); i++) {
+      extension_generators_[i]->GenerateDefinition(printer);
+    }
+
+    printer->Print(
+      "\n"
+      "// @@protoc_insertion_point(namespace_scope)\n");
   }
 
   printer->Print(
-    "\n"
-    "// @@protoc_insertion_point(namespace_scope)\n");
-
-  GenerateNamespaceClosers(printer);
+      "namespace google {\nnamespace protobuf {\n");
+  for (int i = 0; i < message_generators_.size(); i++) {
+    message_generators_[i]->GenerateSourceInProto2Namespace(printer);
+  }
+  printer->Print(
+      "}  // namespace protobuf\n}  // namespace google\n");
 
   printer->Print(
     "\n"
@@ -385,8 +586,9 @@
 class FileGenerator::ForwardDeclarations {
  public:
   ~ForwardDeclarations() {
-    for (map<string, ForwardDeclarations *>::iterator it = namespaces_.begin(),
-                                                      end = namespaces_.end();
+    for (std::map<string, ForwardDeclarations*>::iterator
+             it = namespaces_.begin(),
+             end = namespaces_.end();
          it != end; ++it) {
       delete it->second;
     }
@@ -395,54 +597,116 @@
 
   ForwardDeclarations* AddOrGetNamespace(const string& ns_name) {
     ForwardDeclarations*& ns = namespaces_[ns_name];
-    if (ns == NULL) {
+    if (ns == nullptr) {
       ns = new ForwardDeclarations;
     }
     return ns;
   }
 
-  set<string>& classes() { return classes_; }
-  set<string>& enums() { return enums_; }
+  std::map<string, const Descriptor*>& classes() { return classes_; }
+  std::map<string, const EnumDescriptor*>& enums() { return enums_; }
 
-  void Print(io::Printer* printer) const {
-    for (set<string>::const_iterator it = enums_.begin(), end = enums_.end();
-         it != end; ++it) {
-      printer->Print("enum $enumname$ : int;\n"
-                     "bool $enumname$_IsValid(int value);\n",
-                     "enumname", it->c_str());
-    }
-    for (set<string>::const_iterator it = classes_.begin(),
-                                     end = classes_.end();
-         it != end; ++it) {
-      printer->Print("class $classname$;\n", "classname", it->c_str());
-    }
-    for (map<string, ForwardDeclarations *>::const_iterator
+  void PrintForwardDeclarations(io::Printer* printer,
+                                const Options& options) const {
+    PrintNestedDeclarations(printer, options);
+    PrintTopLevelDeclarations(printer, options);
+  }
+
+
+ private:
+  void PrintNestedDeclarations(io::Printer* printer,
+                               const Options& options) const {
+    PrintDeclarationsInsideNamespace(printer, options);
+    for (std::map<string, ForwardDeclarations *>::const_iterator
              it = namespaces_.begin(),
              end = namespaces_.end();
          it != end; ++it) {
       printer->Print("namespace $nsname$ {\n",
                      "nsname", it->first);
-      it->second->Print(printer);
+      it->second->PrintNestedDeclarations(printer, options);
       printer->Print("}  // namespace $nsname$\n",
                      "nsname", it->first);
     }
   }
 
+  void PrintTopLevelDeclarations(io::Printer* printer,
+                                 const Options& options) const {
+    PrintDeclarationsOutsideNamespace(printer, options);
+    for (std::map<string, ForwardDeclarations *>::const_iterator
+             it = namespaces_.begin(),
+             end = namespaces_.end();
+         it != end; ++it) {
+      it->second->PrintTopLevelDeclarations(printer, options);
+    }
+  }
 
- private:
-  map<string, ForwardDeclarations*> namespaces_;
-  set<string> classes_;
-  set<string> enums_;
+  void PrintDeclarationsInsideNamespace(io::Printer* printer,
+                                        const Options& options) const {
+    for (std::map<string, const EnumDescriptor *>::const_iterator
+             it = enums_.begin(),
+             end = enums_.end();
+         it != end; ++it) {
+      printer->Print("enum $enumname$ : int;\n", "enumname", it->first);
+      printer->Annotate("enumname", it->second);
+      printer->Print("bool $enumname$_IsValid(int value);\n", "enumname",
+                     it->first);
+    }
+    for (std::map<string, const Descriptor*>::const_iterator
+             it = classes_.begin(),
+             end = classes_.end();
+         it != end; ++it) {
+      printer->Print("class $classname$;\n", "classname", it->first);
+      printer->Annotate("classname", it->second);
+
+      printer->Print(
+          "class $classname$DefaultTypeInternal;\n"
+          "$dllexport_decl$"
+          "extern $classname$DefaultTypeInternal "
+          "_$classname$_default_instance_;\n",  // NOLINT
+          "dllexport_decl",
+          options.dllexport_decl.empty() ? "" : options.dllexport_decl + " ",
+          "classname",
+          it->first);
+      if (options.lite_implicit_weak_fields) {
+        printer->Print("void $classname$_ReferenceStrong();\n",
+                       "classname", it->first);
+      }
+    }
+  }
+
+  void PrintDeclarationsOutsideNamespace(io::Printer* printer,
+                                         const Options& options) const {
+    if (classes_.size() == 0) return;
+
+    printer->Print(
+        "namespace google {\nnamespace protobuf {\n");
+    for (std::map<string, const Descriptor*>::const_iterator
+             it = classes_.begin(),
+             end = classes_.end();
+         it != end; ++it) {
+      const Descriptor* d = it->second;
+      printer->Print(
+          "template<> "
+          "$dllexport_decl$"
+          "$classname$* Arena::CreateMaybeMessage<$classname$>"
+          "(Arena*);\n",
+          "classname", QualifiedClassName(d), "dllexport_decl",
+          options.dllexport_decl.empty() ? "" : options.dllexport_decl + " ");
+    }
+    printer->Print(
+        "}  // namespace protobuf\n}  // namespace google\n");
+  }
+
+  std::map<string, ForwardDeclarations*> namespaces_;
+  std::map<string, const Descriptor*> classes_;
+  std::map<string, const EnumDescriptor*> enums_;
 };
 
-void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
+void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) {
   // AddDescriptors() is a file-level procedure which adds the encoded
   // FileDescriptorProto for this .proto file to the global DescriptorPool for
-  // generated files (DescriptorPool::generated_pool()). It either runs at
-  // static initialization time (by default) or when default_instance() is
-  // called for the first time (in LITE_RUNTIME mode with
-  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER flag enabled). This procedure also
-  // constructs default instances and registers extensions.
+  // generated files (DescriptorPool::generated_pool()). It ordinarily runs at
+  // static initialization time, but is not used at all in LITE_RUNTIME mode.
   //
   // Its sibling, AssignDescriptors(), actually pulls the compiled
   // FileDescriptor from the DescriptorPool and uses it to populate all of
@@ -451,141 +715,147 @@
   // anyone calls descriptor() or GetReflection() on one of the types defined
   // in the file.
 
-  // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
-  // and we only use AddDescriptors() to allocate default instances.
-  if (HasDescriptorMethods(file_)) {
+  if (!message_generators_.empty()) {
+    printer->Print("::google::protobuf::Metadata file_level_metadata[$size$];\n", "size",
+                   SimpleItoa(message_generators_.size()));
+  }
+  if (!enum_generators_.empty()) {
     printer->Print(
-      "\n"
-      "void $assigndescriptorsname$() {\n",
-      "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
+        "const ::google::protobuf::EnumDescriptor* "
+        "file_level_enum_descriptors[$size$];\n",
+        "size", SimpleItoa(enum_generators_.size()));
+  }
+  if (HasGenericServices(file_, options_) && file_->service_count() > 0) {
+    printer->Print(
+        "const ::google::protobuf::ServiceDescriptor* "
+        "file_level_service_descriptors[$size$];\n",
+        "size", SimpleItoa(file_->service_count()));
+  }
+
+  if (!message_generators_.empty()) {
+    printer->Print(
+        "\n"
+        "const ::google::protobuf::uint32 TableStruct::offsets[] "
+        "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
     printer->Indent();
-
-    // Make sure the file has found its way into the pool.  If a descriptor
-    // is requested *during* static init then AddDescriptors() may not have
-    // been called yet, so we call it manually.  Note that it's fine if
-    // AddDescriptors() is called multiple times.
-    printer->Print(
-      "$adddescriptorsname$();\n",
-      "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
-
-    // Get the file's descriptor from the pool.
-    printer->Print(
-      "const ::google::protobuf::FileDescriptor* file =\n"
-      "  ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
-      "    \"$filename$\");\n"
-      // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
-      // being unused when compiling an empty .proto file.
-      "GOOGLE_CHECK(file != NULL);\n",
-      "filename", file_->name());
-
-    // Go through all the stuff defined in this file and generated code to
-    // assign the global descriptor pointers based on the file descriptor.
-    for (int i = 0; i < file_->message_type_count(); i++) {
-      message_generators_[i]->GenerateDescriptorInitializer(printer, i);
+    std::vector<std::pair<size_t, size_t> > pairs;
+    pairs.reserve(message_generators_.size());
+    for (int i = 0; i < message_generators_.size(); i++) {
+      pairs.push_back(message_generators_[i]->GenerateOffsets(printer));
     }
-    for (int i = 0; i < file_->enum_type_count(); i++) {
-      enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
-    }
-    if (HasGenericServices(file_)) {
-      for (int i = 0; i < file_->service_count(); i++) {
-        service_generators_[i]->GenerateDescriptorInitializer(printer, i);
+    printer->Outdent();
+    printer->Print(
+        "};\n"
+        "static const ::google::protobuf::internal::MigrationSchema schemas[] "
+        "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
+    printer->Indent();
+    {
+      int offset = 0;
+      for (int i = 0; i < message_generators_.size(); i++) {
+        message_generators_[i]->GenerateSchema(printer, offset,
+                                               pairs[i].second);
+        offset += pairs[i].first;
       }
     }
-
     printer->Outdent();
     printer->Print(
-      "}\n"
-      "\n");
-
-    // ---------------------------------------------------------------
-
-    // protobuf_AssignDescriptorsOnce():  The first time it is called, calls
-    // AssignDescriptors().  All later times, waits for the first call to
-    // complete and then returns.
+        "};\n"
+        "\nstatic "
+        "::google::protobuf::Message const * const file_default_instances[] = {\n");
+    printer->Indent();
+    for (int i = 0; i < message_generators_.size(); i++) {
+      const Descriptor* descriptor = message_generators_[i]->descriptor_;
+      printer->Print(
+          "reinterpret_cast<const "
+          "::google::protobuf::Message*>(&$ns$::_$classname$_default_instance_),\n",
+          "classname", ClassName(descriptor), "ns", Namespace(descriptor));
+    }
+    printer->Outdent();
     printer->Print(
-      "namespace {\n"
-      "\n"
-      "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
-      "inline void protobuf_AssignDescriptorsOnce() {\n"
-      "  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
-      "                 &$assigndescriptorsname$);\n"
-      "}\n"
-      "\n",
-      "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
-
-    // protobuf_RegisterTypes():  Calls
-    // MessageFactory::InternalRegisterGeneratedType() for each message type.
+        "};\n"
+        "\n");
+  } else {
+    // we still need these symbols to exist
     printer->Print(
-      "void protobuf_RegisterTypes(const ::std::string&) {\n"
-      "  protobuf_AssignDescriptorsOnce();\n");
+        // MSVC doesn't like empty arrays, so we add a dummy.
+        "const ::google::protobuf::uint32 TableStruct::offsets[1] = {};\n"
+        "static const ::google::protobuf::internal::MigrationSchema* schemas = NULL;\n"
+        "static const ::google::protobuf::Message* const* "
+        "file_default_instances = NULL;\n"
+        "\n");
+  }
+
+  // ---------------------------------------------------------------
+
+  // protobuf_AssignDescriptorsOnce():  The first time it is called, calls
+  // AssignDescriptors().  All later times, waits for the first call to
+  // complete and then returns.
+    printer->Print(
+        "void protobuf_AssignDescriptors() {\n"
+        // Make sure the file has found its way into the pool.  If a descriptor
+        // is requested *during* static init then AddDescriptors() may not have
+        // been called yet, so we call it manually.  Note that it's fine if
+        // AddDescriptors() is called multiple times.
+        "  AddDescriptors();\n"
+        "  AssignDescriptors(\n"
+        "      \"$filename$\", schemas, file_default_instances, "
+        "TableStruct::offsets,\n"
+        "      $metadata$, $enum_descriptors$, $service_descriptors$);\n",
+        "filename", file_->name(), "metadata",
+        !message_generators_.empty() ? "file_level_metadata" : "NULL",
+        "enum_descriptors",
+        !enum_generators_.empty() ? "file_level_enum_descriptors" : "NULL",
+        "service_descriptors",
+        HasGenericServices(file_, options_) && file_->service_count() > 0
+            ? "file_level_service_descriptors"
+            : "NULL");
+    printer->Print(
+        "}\n"
+        "\n"
+        "void protobuf_AssignDescriptorsOnce() {\n"
+        "  static ::google::protobuf::internal::once_flag once;\n"
+        "  ::google::protobuf::internal::call_once(once, protobuf_AssignDescriptors);\n"
+        "}\n"
+        "\n",
+        "filename", file_->name(), "metadata",
+        !message_generators_.empty() ? "file_level_metadata" : "NULL",
+        "enum_descriptors",
+        !enum_generators_.empty() ? "file_level_enum_descriptors" : "NULL",
+        "service_descriptors",
+        HasGenericServices(file_, options_) && file_->service_count() > 0
+            ? "file_level_service_descriptors"
+            : "NULL");
+
+    // Only here because of useless string reference that we don't want in
+    // protobuf_AssignDescriptorsOnce, because that is called from all the
+    // GetMetadata member methods.
+    printer->Print(
+        "void protobuf_RegisterTypes(const ::std::string&) "
+        "GOOGLE_PROTOBUF_ATTRIBUTE_COLD;\n"
+        "void protobuf_RegisterTypes(const ::std::string&) {\n"
+        "  protobuf_AssignDescriptorsOnce();\n");
     printer->Indent();
 
-    for (int i = 0; i < file_->message_type_count(); i++) {
-      message_generators_[i]->GenerateTypeRegistrations(printer);
+    // All normal messages can be done generically
+    if (!message_generators_.empty()) {
+      printer->Print(
+        "::google::protobuf::internal::RegisterAllTypes(file_level_metadata, $size$);\n",
+        "size", SimpleItoa(message_generators_.size()));
     }
 
     printer->Outdent();
     printer->Print(
-      "}\n"
-      "\n"
-      "}  // namespace\n");
-  }
+        "}\n"
+        "\n");
 
-  // -----------------------------------------------------------------
-
-  // ShutdownFile():  Deletes descriptors, default instances, etc. on shutdown.
-  printer->Print(
-    "\n"
-    "void $shutdownfilename$() {\n",
-    "shutdownfilename", GlobalShutdownFileName(file_->name()));
-  printer->Indent();
-
-  for (int i = 0; i < file_->message_type_count(); i++) {
-    message_generators_[i]->GenerateShutdownCode(printer);
-  }
-
-  printer->Outdent();
-  printer->Print(
-    "}\n\n");
-
-  // -----------------------------------------------------------------
-
-  // Now generate the AddDescriptors() function.
-  PrintHandlingOptionalStaticInitializers(
-    file_, printer,
-    // With static initializers.
-    // Note that we don't need any special synchronization in the following code
-    // because it is called at static init time before any threads exist.
-    "void $adddescriptorsname$() {\n"
-    "  static bool already_here = false;\n"
-    "  if (already_here) return;\n"
-    "  already_here = true;\n"
-    "  GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
-    "\n",
-    // Without.
-    "void $adddescriptorsname$_impl() {\n"
-    "  GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
-    "\n",
-    // Vars.
-    "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
-
-  printer->Indent();
-
-  // Call the AddDescriptors() methods for all of our dependencies, to make
-  // sure they get added first.
-  for (int i = 0; i < file_->dependency_count(); i++) {
-    const FileDescriptor* dependency = file_->dependency(i);
-    // Print the namespace prefix for the dependency.
-    string add_desc_name = QualifiedFileLevelSymbol(
-        dependency->package(), GlobalAddDescriptorsName(dependency->name()));
-    // Call its AddDescriptors function.
+    // Now generate the AddDescriptors() function.
     printer->Print(
-      "$name$();\n",
-      "name", add_desc_name);
-  }
+        "void AddDescriptorsImpl() {\n"
+        "  InitDefaults();\n");
+    printer->Indent();
 
-  if (HasDescriptorMethods(file_)) {
-    // Embed the descriptor.  We simply serialize the entire FileDescriptorProto
+    // Embed the descriptor.  We simply serialize the entire
+    // FileDescriptorProto
     // and embed it as a string literal, which is parsed and built into real
     // descriptors at initialization time.
     FileDescriptorProto file_proto;
@@ -593,155 +863,264 @@
     string file_data;
     file_proto.SerializeToString(&file_data);
 
-#ifdef _MSC_VER
-    bool breakdown_large_file = true;
-#else
-    bool breakdown_large_file = false;
-#endif
-    // Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535
-    // bytes in length". Declare a static array of characters rather than use a
-    // string literal.
-    if (breakdown_large_file && file_data.size() > 65535) {
-      // This has to be explicitly marked as a signed char because the generated
-      // code puts negative values in the array, and sometimes plain char is
-      // unsigned. That implicit narrowing conversion is not allowed in C++11.
-      // <http://stackoverflow.com/questions/4434140/narrowing-conversions-in-c0x-is-it-just-me-or-does-this-sound-like-a-breakin>
-      // has details on why.
-      printer->Print(
-          "static const signed char descriptor[] = {\n");
-      printer->Indent();
+    printer->Print("static const char descriptor[] "
+                   "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) "
+                   "= {\n");
+    printer->Indent();
 
-      // Only write 25 bytes per line.
+    if (file_data.size() > 65535) {
+      // Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535
+      // bytes in length". Declare a static array of characters rather than use
+      // a string literal. Only write 25 bytes per line.
       static const int kBytesPerLine = 25;
       for (int i = 0; i < file_data.size();) {
-          for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) {
-            printer->Print(
-                "$char$, ",
-                "char", SimpleItoa(file_data[i]));
-          }
-          printer->Print(
-              "\n");
+        for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) {
+          printer->Print("'$char$', ", "char",
+                         CEscape(file_data.substr(i, 1)));
+        }
+        printer->Print("\n");
       }
-
-      printer->Outdent();
-      printer->Print(
-          "};\n");
-
-      printer->Print(
-          "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n",
-          "size", SimpleItoa(file_data.size()));
-
     } else {
-      printer->Print(
-        "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
-
       // Only write 40 bytes per line.
       static const int kBytesPerLine = 40;
       for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
-        printer->Print("\n  \"$data$\"",
-                       "data",
-                       EscapeTrigraphs(
-                           CEscape(file_data.substr(i, kBytesPerLine))));
+        printer->Print("  \"$data$\"\n", "data",
+                       EscapeTrigraphs(CEscape(
+                           file_data.substr(i, kBytesPerLine))));
+      }
     }
+
+    printer->Outdent();
+    printer->Print("};\n");
     printer->Print(
-        ", $size$);\n",
+        "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(\n"
+        "    descriptor, $size$);\n",
         "size", SimpleItoa(file_data.size()));
-    }
 
     // Call MessageFactory::InternalRegisterGeneratedFile().
     printer->Print(
       "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
       "  \"$filename$\", &protobuf_RegisterTypes);\n",
       "filename", file_->name());
-  }
 
-  // Allocate and initialize default instances.  This can't be done lazily
-  // since default instances are returned by simple accessors and are used with
-  // extensions.  Speaking of which, we also register extensions at this time.
-  for (int i = 0; i < file_->message_type_count(); i++) {
-    message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
+  // Call the AddDescriptors() methods for all of our dependencies, to make
+  // sure they get added first.
+  for (int i = 0; i < file_->dependency_count(); i++) {
+    const FileDescriptor* dependency = file_->dependency(i);
+    // Print the namespace prefix for the dependency.
+    string file_namespace = FileLevelNamespace(dependency);
+    // Call its AddDescriptors function.
+    printer->Print("::$file_namespace$::AddDescriptors();\n", "file_namespace",
+                   file_namespace);
   }
-  for (int i = 0; i < file_->extension_count(); i++) {
-    extension_generators_[i]->GenerateRegistration(printer);
-  }
-  for (int i = 0; i < file_->message_type_count(); i++) {
-    message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
-  }
-
-  printer->Print(
-    "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n",
-    "shutdownfilename", GlobalShutdownFileName(file_->name()));
 
   printer->Outdent();
   printer->Print(
-    "}\n"
-    "\n");
+      "}\n"
+      "\n"
+      "void AddDescriptors() {\n"
+        "  static ::google::protobuf::internal::once_flag once;\n"
+        "  ::google::protobuf::internal::call_once(once, AddDescriptorsImpl);\n"
+      "}\n");
 
-  PrintHandlingOptionalStaticInitializers(
-    file_, printer,
-    // With static initializers.
-    "// Force AddDescriptors() to be called at static initialization time.\n"
-    "struct StaticDescriptorInitializer_$filename$ {\n"
-    "  StaticDescriptorInitializer_$filename$() {\n"
-    "    $adddescriptorsname$();\n"
-    "  }\n"
-    "} static_descriptor_initializer_$filename$_;\n",
-    // Without.
-    "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n"
-    "void $adddescriptorsname$() {\n"
-    "  ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n"
-    "                 &$adddescriptorsname$_impl);\n"
-    "}\n",
-    // Vars.
-    "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
-    "filename", FilenameIdentifier(file_->name()));
+    printer->Print(
+        "// Force AddDescriptors() to be called at dynamic initialization "
+        "time.\n"
+        "struct StaticDescriptorInitializer {\n"
+        "  StaticDescriptorInitializer() {\n"
+        "    AddDescriptors();\n"
+        "  }\n"
+        "} static_descriptor_initializer;\n");
 }
 
-void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) {
-  if (package_parts_.size() > 0) printer->Print("\n");
+void FileGenerator::GenerateInitForSCC(const SCC* scc, io::Printer* printer) {
+  const string scc_name = ClassName(scc->GetRepresentative());
+  // We use static and not anonymous namespace because symbol names are
+  // substantially shorter.
+  printer->Print(
+      "static void InitDefaults$scc_name$() {\n"
+      "  GOOGLE_PROTOBUF_VERIFY_VERSION;\n\n"
+      ,  // awkward comma due to macro
+      "scc_name", scc_name);
 
-  for (int i = 0; i < package_parts_.size(); i++) {
-    printer->Print("namespace $part$ {\n",
-                   "part", package_parts_[i]);
+  printer->Indent();
+
+
+  // First construct all the necessary default instances.
+  for (int i = 0; i < message_generators_.size(); i++) {
+    if (scc_analyzer_.GetSCC(message_generators_[i]->descriptor_) != scc) {
+      continue;
+    }
+    // TODO(gerbens) This requires this function to be friend. Remove
+    // the need for this.
+    message_generators_[i]->GenerateFieldDefaultInstances(printer);
+    printer->Print(
+        "{\n"
+        "  void* ptr = &$ns$::_$classname$_default_instance_;\n"
+        "  new (ptr) $ns$::$classname$();\n",
+        "ns", Namespace(message_generators_[i]->descriptor_),
+        "classname", ClassName(message_generators_[i]->descriptor_));
+    if (!IsMapEntryMessage(message_generators_[i]->descriptor_)) {
+      printer->Print(
+          "  ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);\n");
+    }
+    printer->Print("}\n");
   }
+
+  // TODO(gerbens) make default instances be the same as normal instances.
+  // Default instances differ from normal instances because they have cross
+  // linked message fields.
+  for (int i = 0; i < message_generators_.size(); i++) {
+    if (scc_analyzer_.GetSCC(message_generators_[i]->descriptor_) != scc) {
+      continue;
+    }
+    printer->Print("$classname$::InitAsDefaultInstance();\n", "classname",
+                   QualifiedClassName(message_generators_[i]->descriptor_));
+  }
+  printer->Outdent();
+  printer->Print("}\n\n");
+
+  printer->Print(
+      "$dllexport_decl$::google::protobuf::internal::SCCInfo<$size$> "
+      "scc_info_$scc_name$ =\n"
+      "    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), "
+      "$size$, InitDefaults$scc_name$}, {",
+      "size", SimpleItoa(scc->children.size()), "scc_name",
+      ClassName(scc->GetRepresentative()), "dllexport_decl",
+      options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
+  for (const SCC* child : scc->children) {
+    auto repr = child->GetRepresentative();
+    printer->Print("\n      &$ns$::scc_info_$child$.base,", "ns",
+                   FileLevelNamespace(repr), "child", ClassName(repr));
+  }
+  printer->Print("}};\n\n");
 }
 
-void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
-  if (package_parts_.size() > 0) printer->Print("\n");
+void FileGenerator::GenerateTables(io::Printer* printer) {
+  if (options_.table_driven_parsing) {
+    // TODO(ckennelly): Gate this with the same options flag to enable
+    // table-driven parsing.
+    printer->Print(
+        "PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField\n"
+        "    const TableStruct::entries[] "
+        "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
+    printer->Indent();
 
-  for (int i = package_parts_.size() - 1; i >= 0; i--) {
-    printer->Print("}  // namespace $part$\n",
-                   "part", package_parts_[i]);
+    std::vector<size_t> entries;
+    size_t count = 0;
+    for (int i = 0; i < message_generators_.size(); i++) {
+      size_t value = message_generators_[i]->GenerateParseOffsets(printer);
+      entries.push_back(value);
+      count += value;
+    }
+
+    // We need these arrays to exist, and MSVC does not like empty arrays.
+    if (count == 0) {
+      printer->Print("{0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},\n");
+    }
+
+    printer->Outdent();
+    printer->Print(
+        "};\n"
+        "\n"
+        "PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField\n"
+        "    const TableStruct::aux[] "
+        "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
+    printer->Indent();
+
+    std::vector<size_t> aux_entries;
+    count = 0;
+    for (int i = 0; i < message_generators_.size(); i++) {
+      size_t value = message_generators_[i]->GenerateParseAuxTable(printer);
+      aux_entries.push_back(value);
+      count += value;
+    }
+
+    if (count == 0) {
+      printer->Print("::google::protobuf::internal::AuxillaryParseTableField(),\n");
+    }
+
+    printer->Outdent();
+    printer->Print(
+        "};\n"
+        "PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const\n"
+        "    TableStruct::schema[] "
+        "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
+    printer->Indent();
+
+    size_t offset = 0;
+    size_t aux_offset = 0;
+    for (int i = 0; i < message_generators_.size(); i++) {
+      message_generators_[i]->GenerateParseTable(printer, offset, aux_offset);
+      offset += entries[i];
+      aux_offset += aux_entries[i];
+    }
+
+    if (message_generators_.empty()) {
+      printer->Print("{ NULL, NULL, 0, -1, -1, false },\n");
+    }
+
+    printer->Outdent();
+    printer->Print(
+        "};\n"
+        "\n");
+  }
+
+  if (!message_generators_.empty() && options_.table_driven_serialization) {
+    printer->Print(
+        "const ::google::protobuf::internal::FieldMetadata TableStruct::field_metadata[] "
+        "= {\n");
+    printer->Indent();
+    std::vector<int> field_metadata_offsets;
+    int idx = 0;
+    for (int i = 0; i < message_generators_.size(); i++) {
+      field_metadata_offsets.push_back(idx);
+      idx += message_generators_[i]->GenerateFieldMetadata(printer);
+    }
+    field_metadata_offsets.push_back(idx);
+    printer->Outdent();
+    printer->Print(
+        "};\n"
+        "const ::google::protobuf::internal::SerializationTable "
+        "TableStruct::serialization_table[] = {\n");
+    printer->Indent();
+    // We rely on the order we layout the tables to match the order we
+    // calculate them with FlattenMessagesInFile, so we check here that
+    // these match exactly.
+    std::vector<const Descriptor*> calculated_order =
+        FlattenMessagesInFile(file_);
+    GOOGLE_CHECK_EQ(calculated_order.size(), message_generators_.size());
+    for (int i = 0; i < message_generators_.size(); i++) {
+      GOOGLE_CHECK_EQ(calculated_order[i], message_generators_[i]->descriptor_);
+      printer->Print(
+          "{$num_fields$, TableStruct::field_metadata + $index$},\n",
+          "classname", message_generators_[i]->classname_, "num_fields",
+          SimpleItoa(field_metadata_offsets[i + 1] - field_metadata_offsets[i]),
+          "index", SimpleItoa(field_metadata_offsets[i]));
+    }
+    printer->Outdent();
+    printer->Print(
+        "};\n"
+        "\n");
   }
 }
 
 void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) {
   ForwardDeclarations decls;
-  for (int i = 0; i < file_->dependency_count(); i++) {
-    FileGenerator dependency(file_->dependency(i), options_);
-    dependency.FillForwardDeclarations(&decls);
-  }
   FillForwardDeclarations(&decls);
-  decls.Print(printer);
+  decls.PrintForwardDeclarations(printer, options_);
 }
 
 void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) {
-  for (int i = 0; i < file_->public_dependency_count(); i++) {
-    FileGenerator dependency(file_->public_dependency(i), options_);
-    dependency.FillForwardDeclarations(decls);
-  }
   for (int i = 0; i < package_parts_.size(); i++) {
     decls = decls->AddOrGetNamespace(package_parts_[i]);
   }
   // Generate enum definitions.
-  for (int i = 0; i < file_->message_type_count(); i++) {
-    message_generators_[i]->FillEnumForwardDeclarations(&decls->enums());
-  }
-  for (int i = 0; i < file_->enum_type_count(); i++) {
+  for (int i = 0; i < enum_generators_.size(); i++) {
     enum_generators_[i]->FillForwardDeclaration(&decls->enums());
   }
   // Generate forward declarations of classes.
-  for (int i = 0; i < file_->message_type_count(); i++) {
+  for (int i = 0; i < message_generators_.size(); i++) {
     message_generators_[i]->FillMessageForwardDeclarations(
         &decls->classes());
   }
@@ -751,26 +1130,28 @@
                                            const string& filename_identifier) {
   // Generate top of header.
   printer->Print(
-    "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
-    "// source: $filename$\n"
-    "\n"
-    "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
-    "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
-    "\n"
-    "#include <string>\n"
-    "\n",
-    "filename", file_->name(),
-    "filename_identifier", filename_identifier);
+      "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+      "// source: $filename$\n"
+      "\n"
+      "#ifndef PROTOBUF_INCLUDED_$filename_identifier$\n"
+      "#define PROTOBUF_INCLUDED_$filename_identifier$\n"
+      "\n"
+      "#include <string>\n",
+      "filename", file_->name(), "filename_identifier", filename_identifier);
+  printer->Print("\n");
 }
 
 void FileGenerator::GenerateBottomHeaderGuard(
     io::Printer* printer, const string& filename_identifier) {
   printer->Print(
-    "#endif  // PROTOBUF_$filename_identifier$__INCLUDED\n",
+    "#endif  // PROTOBUF_INCLUDED_$filename_identifier$\n",
     "filename_identifier", filename_identifier);
 }
 
 void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
+  if (UsingImplicitWeakFields(file_, options_)) {
+    printer->Print("#include <google/protobuf/implicit_weak_message.h>\n");
+  }
 
   printer->Print(
     "#include <google/protobuf/stubs/common.h>\n"
@@ -796,15 +1177,24 @@
 
   // OK, it's now safe to #include other files.
   printer->Print(
-    "#include <google/protobuf/arena.h>\n"
-    "#include <google/protobuf/arenastring.h>\n"
-    "#include <google/protobuf/generated_message_util.h>\n");
-  if (UseUnknownFieldSet(file_)) {
+      "#include <google/protobuf/io/coded_stream.h>\n"
+      "#include <google/protobuf/arena.h>\n"
+      "#include <google/protobuf/arenastring.h>\n"
+      "#include <google/protobuf/generated_message_table_driven.h>\n"
+      "#include <google/protobuf/generated_message_util.h>\n"
+      "#include <google/protobuf/inlined_string_field.h>\n");
+
+
+  if (HasDescriptorMethods(file_, options_)) {
     printer->Print(
       "#include <google/protobuf/metadata.h>\n");
+  } else {
+    printer->Print(
+      "#include <google/protobuf/metadata_lite.h>\n");
   }
-  if (file_->message_type_count() > 0) {
-    if (HasDescriptorMethods(file_)) {
+
+  if (!message_generators_.empty()) {
+    if (HasDescriptorMethods(file_, options_)) {
       printer->Print(
         "#include <google/protobuf/message.h>\n");
     } else {
@@ -813,22 +1203,25 @@
     }
   }
   printer->Print(
-    "#include <google/protobuf/repeated_field.h>\n"
-    "#include <google/protobuf/extension_set.h>\n");
+    "#include <google/protobuf/repeated_field.h>"
+    "  // IWYU pragma: export\n"
+    "#include <google/protobuf/extension_set.h>"
+    "  // IWYU pragma: export\n");
   if (HasMapFields(file_)) {
     printer->Print(
-        "#include <google/protobuf/map.h>\n");
-    if (HasDescriptorMethods(file_)) {
-      printer->Print(
-          "#include <google/protobuf/map_field_inl.h>\n");
+        "#include <google/protobuf/map.h>"
+        "  // IWYU pragma: export\n");
+    if (HasDescriptorMethods(file_, options_)) {
+      printer->Print("#include <google/protobuf/map_entry.h>\n");
+      printer->Print("#include <google/protobuf/map_field_inl.h>\n");
     } else {
-      printer->Print(
-          "#include <google/protobuf/map_field_lite.h>\n");
+      printer->Print("#include <google/protobuf/map_entry_lite.h>\n");
+      printer->Print("#include <google/protobuf/map_field_lite.h>\n");
     }
   }
 
   if (HasEnumDefinitions(file_)) {
-    if (HasDescriptorMethods(file_)) {
+    if (HasDescriptorMethods(file_, options_)) {
       printer->Print(
           "#include <google/protobuf/generated_enum_reflection.h>\n");
     } else {
@@ -837,12 +1230,12 @@
     }
   }
 
-  if (HasGenericServices(file_)) {
+  if (HasGenericServices(file_, options_)) {
     printer->Print(
       "#include <google/protobuf/service.h>\n");
   }
 
-  if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
+  if (UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) {
     printer->Print(
       "#include <google/protobuf/unknown_field_set.h>\n");
   }
@@ -854,62 +1247,76 @@
   }
 }
 
+void FileGenerator::GenerateMetadataPragma(io::Printer* printer,
+                                           const string& info_path) {
+  if (!info_path.empty() && !options_.annotation_pragma_name.empty() &&
+      !options_.annotation_guard_name.empty()) {
+    printer->Print(
+        "#ifdef $guard$\n"
+        "#pragma $pragma$ \"$info_path$\"\n"
+        "#endif  // $guard$\n",
+        "guard", options_.annotation_guard_name, "pragma",
+        options_.annotation_pragma_name, "info_path", info_path);
+  }
+}
+
 void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
-  set<string> public_import_names;
+  std::set<string> public_import_names;
   for (int i = 0; i < file_->public_dependency_count(); i++) {
     public_import_names.insert(file_->public_dependency(i)->name());
   }
 
   for (int i = 0; i < file_->dependency_count(); i++) {
-    bool well_known = IsWellKnownMessage(file_->dependency(i));
+    const bool use_system_include = IsWellKnownMessage(file_->dependency(i));
     const string& name = file_->dependency(i)->name();
     bool public_import = (public_import_names.count(name) != 0);
+    string basename = StripProto(name);
+
 
     printer->Print(
       "#include $left$$dependency$.pb.h$right$$iwyu$\n",
-      "dependency", StripProto(name),
+      "dependency", basename,
       "iwyu", (public_import) ? "  // IWYU pragma: export" : "",
-      "left", well_known ? "<" : "\"",
-      "right", well_known ? ">" : "\"");
+      "left", use_system_include ? "<" : "\"",
+      "right", use_system_include ? ">" : "\"");
   }
 }
 
 void FileGenerator::GenerateGlobalStateFunctionDeclarations(
     io::Printer* printer) {
-  // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
-  // functions, so that we can declare them to be friends of each class.
+// Forward-declare the AddDescriptors, InitDefaults because these are called
+// by .pb.cc files depending on this file.
   printer->Print(
-    "\n"
-    "// Internal implementation detail -- do not call these.\n"
-    "void $dllexport_decl$$adddescriptorsname$();\n",
-    "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
-    "dllexport_decl",
-    options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
-
+      "\n"
+      "namespace $file_namespace$ {\n"
+      "// Internal implementation detail -- do not use these members.\n"
+      "struct $dllexport_decl$TableStruct {\n"
+      // These tables describe how to serialize and parse messages. Used
+      // for table driven code.
+      "  static const ::google::protobuf::internal::ParseTableField entries[];\n"
+      "  static const ::google::protobuf::internal::AuxillaryParseTableField aux[];\n"
+      "  static const ::google::protobuf::internal::ParseTable schema[$num$];\n"
+      "  static const ::google::protobuf::internal::FieldMetadata field_metadata[];\n"
+      "  static const ::google::protobuf::internal::SerializationTable "
+      "serialization_table[];\n"
+      "  static const ::google::protobuf::uint32 offsets[];\n"
+      "};\n",
+      "file_namespace", FileLevelNamespace(file_), "dllexport_decl",
+      options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ",
+      "num", SimpleItoa(std::max(size_t(1), message_generators_.size())));
+  if (HasDescriptorMethods(file_, options_)) {
+    printer->Print(
+        "void $dllexport_decl$AddDescriptors();\n", "dllexport_decl",
+        options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
+  }
   printer->Print(
-    // Note that we don't put dllexport_decl on these because they are only
-    // called by the .pb.cc file in which they are defined.
-    "void $assigndescriptorsname$();\n"
-    "void $shutdownfilename$();\n"
-    "\n",
-    "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
-    "shutdownfilename", GlobalShutdownFileName(file_->name()));
-}
-
-void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) {
-  set<string> classes;
-  for (int i = 0; i < file_->message_type_count(); i++) {
-    message_generators_[i]->FillMessageForwardDeclarations(&classes);
-  }
-  for (set<string>::const_iterator it = classes.begin(), end = classes.end();
-       it != end; ++it) {
-    printer->Print("class $classname$;\n", "classname", it->c_str());
-  }
+      "}  // namespace $file_namespace$\n",
+      "file_namespace", FileLevelNamespace(file_));
 }
 
 void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) {
   // Generate class definitions.
-  for (int i = 0; i < file_->message_type_count(); i++) {
+  for (int i = 0; i < message_generators_.size(); i++) {
     if (i > 0) {
       printer->Print("\n");
       printer->Print(kThinSeparator);
@@ -921,18 +1328,15 @@
 
 void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) {
   // Generate enum definitions.
-  for (int i = 0; i < file_->message_type_count(); i++) {
-    message_generators_[i]->GenerateEnumDefinitions(printer);
-  }
-  for (int i = 0; i < file_->enum_type_count(); i++) {
+  for (int i = 0; i < enum_generators_.size(); i++) {
     enum_generators_[i]->GenerateDefinition(printer);
   }
 }
 
 void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) {
-  if (HasGenericServices(file_)) {
+  if (HasGenericServices(file_, options_)) {
     // Generate service definitions.
-    for (int i = 0; i < file_->service_count(); i++) {
+    for (int i = 0; i < service_generators_.size(); i++) {
       if (i > 0) {
         printer->Print("\n");
         printer->Print(kThinSeparator);
@@ -948,66 +1352,39 @@
 }
 
 void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) {
-  // Declare extension identifiers.
+  // Declare extension identifiers. These are in global scope and so only
+  // the global scope extensions.
   for (int i = 0; i < file_->extension_count(); i++) {
-    extension_generators_[i]->GenerateDeclaration(printer);
+    extension_generators_owner_[i]->GenerateDeclaration(printer);
   }
 }
 
 void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
-  // An aside about inline functions in .proto.h mode:
-  //
-  // The PROTOBUF_INLINE_NOT_IN_HEADERS symbol controls conditionally
-  // moving much of the inline functions to the .pb.cc file, which can be a
-  // significant performance benefit for compilation time, at the expense
-  // of non-inline function calls.
-  //
-  // However, in .proto.h mode, the definition of the internal dependent
-  // base class must remain in the header, and can never be out-lined. The
-  // dependent base class also needs access to has-bit manipuation
-  // functions, so the has-bit functions must be unconditionally inlined in
-  // proto_h mode.
-  //
-  // This gives us three flavors of functions:
-  //
-  //  1. Functions on the message not used by the internal dependent base
-  //     class: in .proto.h mode, only some functions are defined on the
-  //     message class; others are defined on the dependent base class.
-  //     These are guarded and can be out-lined. These are generated by
-  //     GenerateInlineMethods, and include has_* bit functions in
-  //     non-proto_h mode.
-  //
-  //  2. Functions on the internal dependent base class: these functions
-  //     are dependent on a template parameter, so they always need to
-  //     remain in the header.
-  //
-  //  3. Functions on the message that are used by the dependent base: the
-  //     dependent base class down casts itself to the message
-  //     implementation class to access these functions (the has_* bit
-  //     manipulation functions). Unlike #1, these functions must
-  //     unconditionally remain in the header. These are emitted by
-  //     GenerateDependentInlineMethods, even though they are not actually
-  //     dependent.
-
-  printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
+  // TODO(gerbens) remove pragmas when gcc is no longer used. Current version
+  // of gcc fires a bogus error when compiled with strict-aliasing.
+  printer->Print(
+    "#ifdef __GNUC__\n"
+    "  #pragma GCC diagnostic push\n"
+    "  #pragma GCC diagnostic ignored \"-Wstrict-aliasing\"\n"
+    "#endif  // __GNUC__\n");
   // Generate class inline methods.
-  for (int i = 0; i < file_->message_type_count(); i++) {
+  for (int i = 0; i < message_generators_.size(); i++) {
     if (i > 0) {
       printer->Print(kThinSeparator);
       printer->Print("\n");
     }
-    message_generators_[i]->GenerateInlineMethods(printer,
-                                                  /* is_inline = */ true);
+    message_generators_[i]->GenerateInlineMethods(printer);
   }
-  printer->Print("#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
+  printer->Print(
+    "#ifdef __GNUC__\n"
+    "  #pragma GCC diagnostic pop\n"
+    "#endif  // __GNUC__\n");
 
-  for (int i = 0; i < file_->message_type_count(); i++) {
+  for (int i = 0; i < message_generators_.size(); i++) {
     if (i > 0) {
       printer->Print(kThinSeparator);
       printer->Print("\n");
     }
-    // Methods of the dependent base class must always be inline in the header.
-    message_generators_[i]->GenerateDependentInlineMethods(printer);
   }
 }
 
@@ -1015,25 +1392,16 @@
     io::Printer* printer) {
   // Emit GetEnumDescriptor specializations into google::protobuf namespace:
   if (HasEnumDefinitions(file_)) {
-    // The SWIG conditional is to avoid a null-pointer dereference
-    // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
-    //   namespace X { void Y<Z::W>(); }
-    // which appears in GetEnumDescriptor() specializations.
     printer->Print(
         "\n"
-        "#ifndef SWIG\n"
         "namespace google {\nnamespace protobuf {\n"
         "\n");
-    for (int i = 0; i < file_->message_type_count(); i++) {
-      message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
-    }
-    for (int i = 0; i < file_->enum_type_count(); i++) {
+    for (int i = 0; i < enum_generators_.size(); i++) {
       enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
     }
     printer->Print(
         "\n"
-        "}  // namespace protobuf\n}  // namespace google\n"
-        "#endif  // SWIG\n");
+        "}  // namespace protobuf\n}  // namespace google\n");
   }
 }
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h
index 29cdaea..94da9a1 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.h
+++ b/src/google/protobuf/compiler/cpp/cpp_file.h
@@ -35,14 +35,14 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
 #define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
 
+#include <algorithm>
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
+#include <set>
 #include <string>
 #include <vector>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_options.h>
 
 namespace google {
@@ -65,24 +65,37 @@
 class FileGenerator {
  public:
   // See generator.cc for the meaning of dllexport_decl.
-  explicit FileGenerator(const FileDescriptor* file,
-                         const Options& options);
+  FileGenerator(const FileDescriptor* file, const Options& options);
   ~FileGenerator();
 
-  void GenerateProtoHeader(io::Printer* printer);
-  void GeneratePBHeader(io::Printer* printer);
+  // Shared code between the two header generators below.
+  void GenerateHeader(io::Printer* printer);
+
+  // info_path, if non-empty, should be the path (relative to printer's output)
+  // to the metadata file describing this proto header.
+  void GenerateProtoHeader(io::Printer* printer,
+                           const string& info_path);
+  // info_path, if non-empty, should be the path (relative to printer's output)
+  // to the metadata file describing this PB header.
+  void GeneratePBHeader(io::Printer* printer,
+                        const string& info_path);
   void GenerateSource(io::Printer* printer);
 
+  int NumMessages() const { return message_generators_.size(); }
+  // Similar to GenerateSource but generates only one message
+  void GenerateSourceForMessage(int idx, io::Printer* printer);
+  void GenerateGlobalSource(io::Printer* printer);
+
  private:
   // Internal type used by GenerateForwardDeclarations (defined in file.cc).
   class ForwardDeclarations;
 
-  // Generate the BuildDescriptors() procedure, which builds all descriptors
-  // for types defined in the file.
-  void GenerateBuildDescriptors(io::Printer* printer);
+  void GenerateSourceIncludes(io::Printer* printer);
+  void GenerateSourceDefaultInstance(int idx, io::Printer* printer);
 
-  void GenerateNamespaceOpeners(io::Printer* printer);
-  void GenerateNamespaceClosers(io::Printer* printer);
+  void GenerateInitForSCC(const SCC* scc, io::Printer* printer);
+  void GenerateTables(io::Printer* printer);
+  void GenerateReflectionInitializationCode(io::Printer* printer);
 
   // For other imports, generates their forward-declarations.
   void GenerateForwardDeclarations(io::Printer* printer);
@@ -102,24 +115,16 @@
   void GenerateLibraryIncludes(io::Printer* printer);
   void GenerateDependencyIncludes(io::Printer* printer);
 
+  // Generate a pragma to pull in metadata using the given info_path (if
+  // non-empty). info_path should be relative to printer's output.
+  void GenerateMetadataPragma(io::Printer* printer, const string& info_path);
+
   // Generates a couple of different pieces before definitions:
   void GenerateGlobalStateFunctionDeclarations(io::Printer* printer);
 
   // Generates types for classes.
   void GenerateMessageDefinitions(io::Printer* printer);
 
-  // Generates forward-declarations for just this file's classes. This is
-  // used for .pb.h headers, but not in proto_h mode.
-  void GenerateMessageForwardDeclarations(io::Printer* printer);
-
-  // Fills in types for forward declarations. This is used internally, and
-  // also by other FileGenerators to determine imports' declarations.
-  void FillMessageForwardDeclarations(ForwardDeclarations* decls);
-  void FillMessageDefinitions(ForwardDeclarations* decls);
-
-  // Generates enum definitions.
-  void GenerateEnumForwardDeclarations(io::Printer* printer);
-  void FillEnumForwardDeclarations(ForwardDeclarations* decls);
   void GenerateEnumDefinitions(io::Printer* printer);
 
   // Generates generic service definitions.
@@ -133,16 +138,49 @@
 
   void GenerateProto2NamespaceEnumSpecializations(io::Printer* printer);
 
-  const FileDescriptor* file_;
+  // Sometimes the names we use in a .proto file happen to be defined as macros
+  // on some platforms (e.g., macro/minor used in plugin.proto are defined as
+  // macros in sys/types.h on FreeBSD and a few other platforms). To make the
+  // generated code compile on these platforms, we either have to undef the
+  // macro for these few platforms, or rename the field name for all platforms.
+  // Since these names are part of protobuf public API, renaming is generally
+  // a breaking change so we prefer the #undef approach.
+  void GenerateMacroUndefs(io::Printer* printer);
 
-  google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > message_generators_;
-  google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_;
-  google::protobuf::scoped_array<google::protobuf::scoped_ptr<ServiceGenerator> > service_generators_;
-  google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
+  bool IsSCCRepresentative(const Descriptor* d) {
+    return GetSCCRepresentative(d) == d;
+  }
+  const Descriptor* GetSCCRepresentative(const Descriptor* d) {
+    return GetSCC(d)->GetRepresentative();
+  }
+  const SCC* GetSCC(const Descriptor* d) {
+    return scc_analyzer_.GetSCC(d);
+  }
+
+
+  const FileDescriptor* file_;
+  const Options options_;
+
+  SCCAnalyzer scc_analyzer_;
+
+
+  // Contains the post-order walk of all the messages (and child messages) in
+  // this file. If you need a pre-order walk just reverse iterate.
+  std::vector<MessageGenerator*> message_generators_;
+  std::vector<EnumGenerator*> enum_generators_;
+  std::vector<ServiceGenerator*> service_generators_;
+  std::vector<ExtensionGenerator*> extension_generators_;
+
+  // These members are just for owning (and thus proper deleting).
+  // Nested (enum/extension)_generators are owned by child messages.
+  std::unique_ptr<std::unique_ptr<EnumGenerator> []> enum_generators_owner_;
+  std::unique_ptr<std::unique_ptr<ServiceGenerator> []>
+      service_generators_owner_;
+  std::unique_ptr<std::unique_ptr<ExtensionGenerator> []>
+      extension_generators_owner_;
 
   // E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}.
-  vector<string> package_parts_;
-  const Options options_;
+  std::vector<string> package_parts_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
 };
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc
index 781526b..20bb8a1 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -36,16 +36,15 @@
 
 #include <vector>
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 #include <utility>
 
+#include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/compiler/cpp/cpp_file.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/descriptor.pb.h>
+
 
 namespace google {
 namespace protobuf {
@@ -59,18 +58,12 @@
                             const string& parameter,
                             GeneratorContext* generator_context,
                             string* error) const {
-  vector<pair<string, string> > options;
+  std::vector<std::pair<string, string> > options;
   ParseGeneratorParameter(parameter, &options);
 
   // -----------------------------------------------------------------
   // parse generator options
 
-  // TODO(kenton):  If we ever have more options, we may want to create a
-  //   class that encapsulates them which we can pass down to all the
-  //   generator classes.  Currently we pass dllexport_decl down to all of
-  //   them via the constructors, but we don't want to have to add another
-  //   constructor parameter for every option.
-
   // If the dllexport_decl option is passed to the compiler, we need to write
   // it in front of every symbol that should be exported if this .proto is
   // compiled into a Windows DLL.  E.g., if the user invokes the protocol
@@ -84,45 +77,123 @@
   // __declspec(dllimport) depending on what is being compiled.
   //
   Options file_options;
-
   for (int i = 0; i < options.size(); i++) {
     if (options[i].first == "dllexport_decl") {
       file_options.dllexport_decl = options[i].second;
     } else if (options[i].first == "safe_boundary_check") {
       file_options.safe_boundary_check = true;
+    } else if (options[i].first == "annotate_headers") {
+      file_options.annotate_headers = true;
+    } else if (options[i].first == "annotation_pragma_name") {
+      file_options.annotation_pragma_name = options[i].second;
+    } else if (options[i].first == "annotation_guard_name") {
+      file_options.annotation_guard_name = options[i].second;
+    } else if (options[i].first == "lite") {
+      file_options.enforce_lite = true;
+    } else if (options[i].first == "lite_implicit_weak_fields") {
+      file_options.lite_implicit_weak_fields = true;
+      if (!options[i].second.empty()) {
+        file_options.num_cc_files = strto32(options[i].second.c_str(),
+                                            NULL, 10);
+      }
+    } else if (options[i].first == "table_driven_parsing") {
+      file_options.table_driven_parsing = true;
+    } else if (options[i].first == "table_driven_serialization") {
+      file_options.table_driven_serialization = true;
     } else {
       *error = "Unknown generator option: " + options[i].first;
       return false;
     }
   }
 
+  // The safe_boundary_check option controls behavior for Google-internal
+  // protobuf APIs.
+  if (file_options.safe_boundary_check) {
+    *error =
+        "The safe_boundary_check option is not supported outside of Google.";
+    return false;
+  }
+
   // -----------------------------------------------------------------
 
 
   string basename = StripProto(file->name());
 
+
   FileGenerator file_generator(file, file_options);
 
   // Generate header(s).
   if (file_options.proto_h) {
-    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+    std::unique_ptr<io::ZeroCopyOutputStream> output(
         generator_context->Open(basename + ".proto.h"));
-    io::Printer printer(output.get(), '$');
-    file_generator.GenerateProtoHeader(&printer);
+    GeneratedCodeInfo annotations;
+    io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+        &annotations);
+    string info_path = basename + ".proto.h.meta";
+    io::Printer printer(output.get(), '$', file_options.annotate_headers
+                                               ? &annotation_collector
+                                               : NULL);
+    file_generator.GenerateProtoHeader(
+        &printer, file_options.annotate_headers ? info_path : "");
+    if (file_options.annotate_headers) {
+      std::unique_ptr<io::ZeroCopyOutputStream> info_output(
+          generator_context->Open(info_path));
+      annotations.SerializeToZeroCopyStream(info_output.get());
+    }
   }
 
-  basename.append(".pb");
   {
-    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
-        generator_context->Open(basename + ".h"));
-    io::Printer printer(output.get(), '$');
-    file_generator.GeneratePBHeader(&printer);
+    std::unique_ptr<io::ZeroCopyOutputStream> output(
+        generator_context->Open(basename + ".pb.h"));
+    GeneratedCodeInfo annotations;
+    io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+        &annotations);
+    string info_path = basename + ".pb.h.meta";
+    io::Printer printer(output.get(), '$', file_options.annotate_headers
+                                               ? &annotation_collector
+                                               : NULL);
+    file_generator.GeneratePBHeader(
+        &printer, file_options.annotate_headers ? info_path : "");
+    if (file_options.annotate_headers) {
+      std::unique_ptr<io::ZeroCopyOutputStream> info_output(
+          generator_context->Open(info_path));
+      annotations.SerializeToZeroCopyStream(info_output.get());
+    }
   }
 
-  // Generate cc file.
-  {
-    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
-        generator_context->Open(basename + ".cc"));
+  // Generate cc file(s).
+  if (UsingImplicitWeakFields(file, file_options)) {
+    {
+      // This is the global .cc file, containing enum/services/tables/reflection
+      std::unique_ptr<io::ZeroCopyOutputStream> output(
+          generator_context->Open(basename + ".pb.cc"));
+      io::Printer printer(output.get(), '$');
+      file_generator.GenerateGlobalSource(&printer);
+    }
+
+    int num_cc_files = file_generator.NumMessages();
+
+    // If we're using implicit weak fields then we allow the user to optionally
+    // specify how many files to generate, not counting the global pb.cc file.
+    // If we have more files than messages, then some files will be generated as
+    // empty placeholders.
+    if (file_options.num_cc_files > 0) {
+      GOOGLE_CHECK_LE(file_generator.NumMessages(), file_options.num_cc_files)
+          << "There must be at least as many numbered .cc files as messages.";
+      num_cc_files = file_options.num_cc_files;
+    }
+    for (int i = 0; i < num_cc_files; i++) {
+      // TODO(gerbens) Agree on naming scheme.
+      std::unique_ptr<io::ZeroCopyOutputStream> output(
+          generator_context->Open(basename + "." + SimpleItoa(i) + ".cc"));
+      io::Printer printer(output.get(), '$');
+      if (i < file_generator.NumMessages()) {
+        file_generator.GenerateSourceForMessage(i, &printer);
+      }
+    }
+  } else {
+    std::unique_ptr<io::ZeroCopyOutputStream> output(
+        generator_context->Open(basename + ".pb.cc"));
     io::Printer printer(output.get(), '$');
     file_generator.GenerateSource(&printer);
   }
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index fb46e38..163dac0 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -32,19 +32,23 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/stubs/hash.h>
 #include <limits>
 #include <map>
+#include <queue>
 #include <vector>
-#include <google/protobuf/stubs/hash.h>
 
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
-#include <google/protobuf/io/printer.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
 
 
+
+
 namespace google {
 namespace protobuf {
 namespace compiler {
@@ -68,14 +72,15 @@
   "alignas", "alignof", "and", "and_eq", "asm", "auto", "bitand", "bitor",
   "bool", "break", "case", "catch", "char", "class", "compl", "const",
   "constexpr", "const_cast", "continue", "decltype", "default", "delete", "do",
-  "double", "dynamic_cast", "else", "enum", "explicit", "extern", "false",
-  "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable",
-  "namespace", "new", "noexcept", "not", "not_eq", "NULL", "operator", "or",
-  "or_eq", "private", "protected", "public", "register", "reinterpret_cast",
-  "return", "short", "signed", "sizeof", "static", "static_assert",
-  "static_cast", "struct", "switch", "template", "this", "thread_local",
-  "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned",
-  "using", "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq"
+  "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern",
+  "false", "float", "for", "friend", "goto", "if", "inline", "int", "long",
+  "mutable", "namespace", "new", "noexcept", "not", "not_eq", "nullptr",
+  "operator", "or", "or_eq", "private", "protected", "public", "register",
+  "reinterpret_cast", "return", "short", "signed", "sizeof", "static",
+  "static_assert", "static_cast", "struct", "switch", "template", "this",
+  "thread_local", "throw", "true", "try", "typedef", "typeid", "typename",
+  "union", "unsigned", "using", "virtual", "void", "volatile", "wchar_t",
+  "while", "xor", "xor_eq"
 };
 
 hash_set<string> MakeKeywordsMap() {
@@ -102,6 +107,30 @@
   return false;
 }
 
+// Encode [0..63] as 'A'-'Z', 'a'-'z', '0'-'9', '_'
+char Base63Char(int value) {
+  GOOGLE_CHECK_GE(value, 0);
+  if (value < 26) return 'A' + value;
+  value -= 26;
+  if (value < 26) return 'a' + value;
+  value -= 26;
+  if (value < 10) return '0' + value;
+  GOOGLE_CHECK_EQ(value, 10);
+  return '_';
+}
+
+// Given a c identifier has 63 legal characters we can't implement base64
+// encoding. So we return the k least significant "digits" in base 63.
+template <typename I>
+string Base63(I n, int k) {
+  string res;
+  while (k-- > 0) {
+    res += Base63Char(static_cast<int>(n % 63));
+    n /= 63;
+  }
+  return res;
+}
+
 }  // namespace
 
 string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
@@ -134,54 +163,67 @@
 const char kThinSeparator[] =
   "// -------------------------------------------------------------------\n";
 
-string ClassName(const Descriptor* descriptor, bool qualified) {
-
-  // Find "outer", the descriptor of the top-level message in which
-  // "descriptor" is embedded.
-  const Descriptor* outer = descriptor;
-  while (outer->containing_type() != NULL) outer = outer->containing_type();
-
-  const string& outer_name = outer->full_name();
-  string inner_name = descriptor->full_name().substr(outer_name.size());
-
-  if (qualified) {
-    return "::" + DotsToColons(outer_name) + DotsToUnderscores(inner_name);
-  } else {
-    return outer->name() + DotsToUnderscores(inner_name);
+bool CanInitializeByZeroing(const FieldDescriptor* field) {
+  if (field->is_repeated() || field->is_extension()) return false;
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return field->default_value_enum()->number() == 0;
+    case FieldDescriptor::CPPTYPE_INT32:
+      return field->default_value_int32() == 0;
+    case FieldDescriptor::CPPTYPE_INT64:
+      return field->default_value_int64() == 0;
+    case FieldDescriptor::CPPTYPE_UINT32:
+      return field->default_value_uint32() == 0;
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return field->default_value_uint64() == 0;
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return field->default_value_float() == 0;
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return field->default_value_double() == 0;
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return field->default_value_bool() == false;
+    default:
+      return false;
   }
 }
 
-string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) {
+string ClassName(const Descriptor* descriptor) {
+  const Descriptor* parent = descriptor->containing_type();
+  string res;
+  if (parent) res += ClassName(parent) + "_";
+  res += descriptor->name();
+  if (IsMapEntryMessage(descriptor)) res += "_DoNotUse";
+  return res;
+}
+
+string ClassName(const EnumDescriptor* enum_descriptor) {
   if (enum_descriptor->containing_type() == NULL) {
-    if (qualified) {
-      return "::" + DotsToColons(enum_descriptor->full_name());
-    } else {
-      return enum_descriptor->name();
-    }
+    return enum_descriptor->name();
   } else {
-    string result = ClassName(enum_descriptor->containing_type(), qualified);
-    result += '_';
-    result += enum_descriptor->name();
-    return result;
+    return ClassName(enum_descriptor->containing_type()) + "_" +
+           enum_descriptor->name();
   }
 }
 
-
-string DependentBaseClassTemplateName(const Descriptor* descriptor) {
-  return ClassName(descriptor, false) + "_InternalBase";
+string Namespace(const string& package) {
+  if (package.empty()) return "";
+  return "::" + DotsToColons(package);
 }
 
-string SuperClassName(const Descriptor* descriptor) {
-  return HasDescriptorMethods(descriptor->file()) ?
-      "::google::protobuf::Message" : "::google::protobuf::MessageLite";
+string DefaultInstanceName(const Descriptor* descriptor) {
+  string prefix = descriptor->file()->package().empty() ? "" : "::";
+  return prefix + DotsToColons(descriptor->file()->package()) + "::_" +
+      ClassName(descriptor, false) + "_default_instance_";
 }
 
-string DependentBaseDownCast() {
-  return "reinterpret_cast<T*>(this)->";
+string ReferenceFunctionName(const Descriptor* descriptor) {
+  return QualifiedClassName(descriptor) + "_ReferenceStrong";
 }
 
-string DependentBaseConstDownCast() {
-  return "reinterpret_cast<const T*>(this)->";
+string SuperClassName(const Descriptor* descriptor, const Options& options) {
+  return HasDescriptorMethods(descriptor->file(), options)
+             ? "::google::protobuf::Message"
+             : "::google::protobuf::MessageLite";
 }
 
 string FieldName(const FieldDescriptor* field) {
@@ -201,6 +243,30 @@
   return result;
 }
 
+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.
+}
+
 string FieldConstantName(const FieldDescriptor *field) {
   string field_name = UnderscoresToCamelCase(field->name(), true);
   string result = "k" + field_name + "FieldNumber";
@@ -217,60 +283,6 @@
   return result;
 }
 
-bool IsFieldDependent(const FieldDescriptor* field) {
-  if (field->containing_oneof() != NULL &&
-      field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
-    return true;
-  }
-  if (field->is_map()) {
-    const Descriptor* map_descriptor = field->message_type();
-    for (int i = 0; i < map_descriptor->field_count(); i++) {
-      if (IsFieldDependent(map_descriptor->field(i))) {
-        return true;
-      }
-    }
-    return false;
-  }
-  if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
-    return false;
-  }
-  if (field->containing_oneof() != NULL) {
-    // Oneof fields will always be dependent.
-    //
-    // This is a unique case for field codegen. Field generators are
-    // responsible for generating all the field-specific accessor
-    // functions, except for the clear_*() function; instead, field
-    // generators produce inline clearing code.
-    //
-    // For non-oneof fields, the Message class uses the inline clearing
-    // code to define the field's clear_*() function, as well as in the
-    // destructor. For oneof fields, the Message class generates a much
-    // more complicated clear_*() function, which clears only the oneof
-    // member that is set, in addition to clearing methods for each of the
-    // oneof members individually.
-    //
-    // Since oneofs do not have their own generator class, the Message code
-    // generation logic would be significantly complicated in order to
-    // split dependent and non-dependent manipulation logic based on
-    // whether the oneof truly needs to be dependent; so, for oneof fields,
-    // we just assume it (and its constituents) should be manipulated by a
-    // dependent base class function.
-    //
-    // This is less precise than how dependent message-typed fields are
-    // handled, but the cost is limited to only the generated code for the
-    // oneof field, which seems like an acceptable tradeoff.
-    return true;
-  }
-  if (field->file() == field->message_type()->file()) {
-    return false;
-  }
-  return true;
-}
-
-string DependentTypeName(const FieldDescriptor* field) {
-  return "InternalBase_" + field->name() + "_T";
-}
-
 string FieldMessageTypeName(const FieldDescriptor* field) {
   // Note:  The Google-internal version of Protocol Buffers uses this function
   //   as a hook point for hacks to support legacy code.
@@ -369,9 +381,9 @@
       return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")";
     case FieldDescriptor::CPPTYPE_DOUBLE: {
       double value = field->default_value_double();
-      if (value == numeric_limits<double>::infinity()) {
+      if (value == std::numeric_limits<double>::infinity()) {
         return "::google::protobuf::internal::Infinity()";
-      } else if (value == -numeric_limits<double>::infinity()) {
+      } else if (value == -std::numeric_limits<double>::infinity()) {
         return "-::google::protobuf::internal::Infinity()";
       } else if (value != value) {
         return "::google::protobuf::internal::NaN()";
@@ -382,9 +394,9 @@
     case FieldDescriptor::CPPTYPE_FLOAT:
       {
         float value = field->default_value_float();
-        if (value == numeric_limits<float>::infinity()) {
+        if (value == std::numeric_limits<float>::infinity()) {
           return "static_cast<float>(::google::protobuf::internal::Infinity())";
-        } else if (value == -numeric_limits<float>::infinity()) {
+        } else if (value == -std::numeric_limits<float>::infinity()) {
           return "static_cast<float>(-::google::protobuf::internal::Infinity())";
         } else if (value != value) {
           return "static_cast<float>(::google::protobuf::internal::NaN())";
@@ -413,7 +425,8 @@
         CEscape(field->default_value_string())) +
         "\"";
     case FieldDescriptor::CPPTYPE_MESSAGE:
-      return FieldMessageTypeName(field) + "::default_instance()";
+      return "*" + FieldMessageTypeName(field) +
+             "::internal_default_instance()";
   }
   // Can't actually get here; make compiler happy.  (We could add a default
   // case above but then we wouldn't get the nice compiler warning when a
@@ -437,19 +450,8 @@
   return result;
 }
 
-// Return the name of the AddDescriptors() function for a given file.
-string GlobalAddDescriptorsName(const string& filename) {
-  return "protobuf_AddDesc_" + FilenameIdentifier(filename);
-}
-
-// Return the name of the AssignDescriptors() function for a given file.
-string GlobalAssignDescriptorsName(const string& filename) {
-  return "protobuf_AssignDesc_" + FilenameIdentifier(filename);
-}
-
-// Return the name of the ShutdownFile() function for a given file.
-string GlobalShutdownFileName(const string& filename) {
-  return "protobuf_ShutdownFile_" + FilenameIdentifier(filename);
+string FileLevelNamespace(const string& filename) {
+  return "protobuf_" + FilenameIdentifier(filename);
 }
 
 // Return the qualified C++ name for a file level symbol.
@@ -485,50 +487,6 @@
   return function_name;
 }
 
-bool StaticInitializersForced(const FileDescriptor* file) {
-  if (HasDescriptorMethods(file) || file->extension_count() > 0) {
-    return true;
-  }
-  for (int i = 0; i < file->message_type_count(); ++i) {
-    if (HasExtension(file->message_type(i))) {
-      return true;
-    }
-  }
-  return false;
-}
-
-void PrintHandlingOptionalStaticInitializers(
-    const FileDescriptor* file, io::Printer* printer,
-    const char* with_static_init, const char* without_static_init,
-    const char* var1, const string& val1,
-    const char* var2, const string& val2) {
-  map<string, string> vars;
-  if (var1) {
-    vars[var1] = val1;
-  }
-  if (var2) {
-    vars[var2] = val2;
-  }
-  PrintHandlingOptionalStaticInitializers(
-      vars, file, printer, with_static_init, without_static_init);
-}
-
-void PrintHandlingOptionalStaticInitializers(
-    const map<string, string>& vars, const FileDescriptor* file,
-    io::Printer* printer, const char* with_static_init,
-    const char* without_static_init) {
-  if (StaticInitializersForced(file)) {
-    printer->Print(vars, with_static_init);
-  } else {
-    printer->Print(vars, (string(
-      "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n") +
-      without_static_init +
-      "#else\n" +
-      with_static_init +
-      "#endif\n").c_str());
-  }
-}
-
 
 static bool HasMapFields(const Descriptor* descriptor) {
   for (int i = 0; i < descriptor->field_count(); ++i) {
@@ -612,10 +570,11 @@
 };
 
 // Which level of UTF-8 enforcemant is placed on this file.
-static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field) {
+static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field,
+                                      const Options& options) {
   if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
     return STRICT;
-  } else if (field->file()->options().optimize_for() !=
+  } else if (GetOptimizeFor(field->file(), options) !=
              FileOptions::LITE_RUNTIME) {
     return VERIFY;
   } else {
@@ -624,13 +583,13 @@
 }
 
 static void GenerateUtf8CheckCode(const FieldDescriptor* field,
-                                  bool for_parse,
-                                  const map<string, string>& variables,
+                                  const Options& options, bool for_parse,
+                                  const std::map<string, string>& variables,
                                   const char* parameters,
                                   const char* strict_function,
                                   const char* verify_function,
                                   io::Printer* printer) {
-  switch (GetUtf8CheckMode(field)) {
+  switch (GetUtf8CheckMode(field, options)) {
     case STRICT: {
       if (for_parse) {
         printer->Print("DO_(");
@@ -674,25 +633,234 @@
 }
 
 void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
-                                    bool for_parse,
-                                    const map<string, string>& variables,
+                                    const Options& options, bool for_parse,
+                                    const std::map<string, string>& variables,
                                     const char* parameters,
                                     io::Printer* printer) {
-  GenerateUtf8CheckCode(field, for_parse, variables, parameters,
+  GenerateUtf8CheckCode(field, options, for_parse, variables, parameters,
                         "VerifyUtf8String", "VerifyUTF8StringNamedField",
                         printer);
 }
 
 void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
-                                  bool for_parse,
-                                  const map<string, string>& variables,
+                                  const Options& options, bool for_parse,
+                                  const std::map<string, string>& variables,
                                   const char* parameters,
                                   io::Printer* printer) {
-  GenerateUtf8CheckCode(field, for_parse, variables, parameters,
-                        "VerifyUtf8Cord", "VerifyUTF8CordNamedField",
-                        printer);
+  GenerateUtf8CheckCode(field, options, for_parse, variables, parameters,
+                        "VerifyUtf8Cord", "VerifyUTF8CordNamedField", printer);
 }
 
+namespace {
+
+void Flatten(const Descriptor* descriptor,
+             std::vector<const Descriptor*>* flatten) {
+  for (int i = 0; i < descriptor->nested_type_count(); i++)
+    Flatten(descriptor->nested_type(i), flatten);
+  flatten->push_back(descriptor);
+}
+
+}  // namespace
+
+void FlattenMessagesInFile(const FileDescriptor* file,
+                           std::vector<const Descriptor*>* result) {
+  for (int i = 0; i < file->message_type_count(); i++) {
+    Flatten(file->message_type(i), result);
+  }
+}
+
+bool HasWeakFields(const Descriptor* descriptor) {
+  return false;
+}
+
+bool HasWeakFields(const FileDescriptor* file) {
+  return false;
+}
+
+bool UsingImplicitWeakFields(const FileDescriptor* file,
+                             const Options& options) {
+  return options.lite_implicit_weak_fields &&
+         GetOptimizeFor(file, options) == FileOptions::LITE_RUNTIME;
+}
+
+bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options,
+                         SCCAnalyzer* scc_analyzer) {
+  return UsingImplicitWeakFields(field->file(), options) &&
+         field->type() == FieldDescriptor::TYPE_MESSAGE &&
+         !field->is_required() && !field->is_map() &&
+         field->containing_oneof() == NULL &&
+         !IsWellKnownMessage(field->message_type()->file()) &&
+         // We do not support implicit weak fields between messages in the same
+         // strongly-connected component.
+         scc_analyzer->GetSCC(field->containing_type()) !=
+             scc_analyzer->GetSCC(field->message_type());
+}
+
+struct CompareDescriptors {
+  bool operator()(const Descriptor* a, const Descriptor* b) {
+    return a->full_name() < b->full_name();
+  }
+};
+
+SCCAnalyzer::NodeData SCCAnalyzer::DFS(const Descriptor* descriptor) {
+  // Must not have visited already.
+  GOOGLE_DCHECK_EQ(cache_.count(descriptor), 0);
+
+  // Mark visited by inserting in map.
+  NodeData& result = cache_[descriptor];
+  // Initialize data structures.
+  result.index = result.lowlink = index_++;
+  stack_.push_back(descriptor);
+
+  // Recurse the fields / nodes in graph
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    const Descriptor* child = descriptor->field(i)->message_type();
+    if (child) {
+      if (cache_.count(child) == 0) {
+        // unexplored node
+        NodeData child_data = DFS(child);
+        result.lowlink = std::min(result.lowlink, child_data.lowlink);
+      } else {
+        NodeData child_data = cache_[child];
+        if (child_data.scc == NULL) {
+          // Still in the stack_ so we found a back edge
+          result.lowlink = std::min(result.lowlink, child_data.index);
+        }
+      }
+    }
+  }
+  if (result.index == result.lowlink) {
+    // This is the root of a strongly connected component
+    SCC* scc = CreateSCC();
+    while (true) {
+      const Descriptor* scc_desc = stack_.back();
+      scc->descriptors.push_back(scc_desc);
+      // Remove from stack
+      stack_.pop_back();
+      cache_[scc_desc].scc = scc;
+
+      if (scc_desc == descriptor) break;
+    }
+
+    // The order of descriptors is random and depends how this SCC was
+    // discovered. In-order to ensure maximum stability we sort it by name.
+    std::sort(scc->descriptors.begin(), scc->descriptors.end(),
+              CompareDescriptors());
+    AddChildren(scc);
+  }
+  return result;
+}
+
+void SCCAnalyzer::AddChildren(SCC* scc) {
+  std::set<const SCC*> seen;
+  for (int i = 0; i < scc->descriptors.size(); i++) {
+    const Descriptor* descriptor = scc->descriptors[i];
+    for (int j = 0; j < descriptor->field_count(); j++) {
+      const Descriptor* child_msg = descriptor->field(j)->message_type();
+      if (child_msg) {
+        const SCC* child = GetSCC(child_msg);
+        if (child == scc) continue;
+        if (seen.insert(child).second) {
+          scc->children.push_back(child);
+        }
+      }
+    }
+  }
+}
+
+MessageAnalysis SCCAnalyzer::GetSCCAnalysis(const SCC* scc) {
+  if (analysis_cache_.count(scc)) return analysis_cache_[scc];
+  MessageAnalysis result = MessageAnalysis();
+  for (int i = 0; i < scc->descriptors.size(); i++) {
+    const Descriptor* descriptor = scc->descriptors[i];
+    if (descriptor->extension_range_count() > 0) {
+      result.contains_extension = true;
+    }
+    for (int i = 0; i < descriptor->field_count(); i++) {
+      const FieldDescriptor* field = descriptor->field(i);
+      if (field->is_required()) {
+        result.contains_required = true;
+      }
+      switch (field->type()) {
+        case FieldDescriptor::TYPE_STRING:
+        case FieldDescriptor::TYPE_BYTES: {
+          if (field->options().ctype() == FieldOptions::CORD) {
+            result.contains_cord = true;
+          }
+          break;
+        }
+        case FieldDescriptor::TYPE_GROUP:
+        case FieldDescriptor::TYPE_MESSAGE: {
+          const SCC* child = GetSCC(field->message_type());
+          if (child != scc) {
+            MessageAnalysis analysis = GetSCCAnalysis(child);
+            result.contains_cord |= analysis.contains_cord;
+            result.contains_extension |= analysis.contains_extension;
+            if (!ShouldIgnoreRequiredFieldCheck(field, options_)) {
+              result.contains_required |= analysis.contains_required;
+            }
+          } else {
+            // This field points back into the same SCC hence the messages
+            // in the SCC are recursive. Note if SCC contains more than two
+            // nodes it has to be recursive, however this test also works for
+            // a single node that is recursive.
+            result.is_recursive = true;
+          }
+          break;
+        }
+        default:
+          break;
+      }
+    }
+  }
+  // We deliberately only insert the result here. After we contracted the SCC
+  // in the graph, the graph should be a DAG. Hence we shouldn't need to mark
+  // nodes visited as we can never return to them. By inserting them here
+  // we will go in an infinite loop if the SCC is not correct.
+  return analysis_cache_[scc] = result;
+}
+
+void ListAllFields(const Descriptor* d,
+                   std::vector<const FieldDescriptor*>* fields) {
+  // Collect sub messages
+  for (int i = 0; i < d->nested_type_count(); i++) {
+    ListAllFields(d->nested_type(i), fields);
+  }
+  // Collect message level extensions.
+  for (int i = 0; i < d->extension_count(); i++) {
+    fields->push_back(d->extension(i));
+  }
+  // Add types of fields necessary
+  for (int i = 0; i < d->field_count(); i++) {
+    fields->push_back(d->field(i));
+  }
+}
+
+void ListAllFields(const FileDescriptor* d,
+                   std::vector<const FieldDescriptor*>* fields) {
+  // Collect file level message.
+  for (int i = 0; i < d->message_type_count(); i++) {
+    ListAllFields(d->message_type(i), fields);
+  }
+  // Collect message level extensions.
+  for (int i = 0; i < d->extension_count(); i++) {
+    fields->push_back(d->extension(i));
+  }
+}
+
+void ListAllTypesForServices(const FileDescriptor* fd,
+                             std::vector<const Descriptor*>* types) {
+  for (int i = 0; i < fd->service_count(); i++) {
+    const ServiceDescriptor* sd = fd->service(i);
+    for (int j = 0; j < sd->method_count(); j++) {
+      const MethodDescriptor* method = sd->method(j);
+      types->push_back(method->input_type());
+      types->push_back(method->output_type());
+    }
+  }
+}
+
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index a22d414..eac6512 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -37,16 +37,15 @@
 
 #include <map>
 #include <string>
-#include <google/protobuf/descriptor.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/stubs/strutil.h>
 
 namespace google {
 namespace protobuf {
-
-namespace io {
-class Printer;
-}
-
 namespace compiler {
 namespace cpp {
 
@@ -55,6 +54,32 @@
 extern const char kThickSeparator[];
 extern const char kThinSeparator[];
 
+
+// Name space of the proto file. This namespace is such that the string
+// "<namespace>::some_name" is the correct fully qualified namespace.
+// This means if the package is empty the namespace is "", and otherwise
+// the namespace is "::foo::bar::...::baz" without trailing semi-colons.
+string Namespace(const string& package);
+inline string Namespace(const FileDescriptor* d) {
+  return Namespace(d->package());
+}
+template <typename Desc>
+string Namespace(const Desc* d) {
+  return Namespace(d->file());
+}
+
+// Returns true if it's safe to reset "field" to zero.
+bool CanInitializeByZeroing(const FieldDescriptor* field);
+
+string ClassName(const Descriptor* descriptor);
+string ClassName(const EnumDescriptor* enum_descriptor);
+template <typename Desc>
+string QualifiedClassName(const Desc* d) {
+  return Namespace(d) + "::" + ClassName(d);
+}
+
+// DEPRECATED just use ClassName or QualifiedClassName, a boolean is very
+// unreadable at the callsite.
 // Returns the non-nested type name for the given type.  If "qualified" is
 // true, prefix the type with the full namespace.  For example, if you had:
 //   package foo.bar;
@@ -63,21 +88,24 @@
 //   ::foo::bar::Baz_Qux
 // While the non-qualified version would be:
 //   Baz_Qux
-string ClassName(const Descriptor* descriptor, bool qualified);
-string ClassName(const EnumDescriptor* enum_descriptor, bool qualified);
+inline string ClassName(const Descriptor* descriptor, bool qualified) {
+  return qualified ? QualifiedClassName(descriptor) : ClassName(descriptor);
+}
 
-// Name of the CRTP class template (for use with proto_h).
-// This is a class name, like "ProtoName_InternalBase".
-string DependentBaseClassTemplateName(const Descriptor* descriptor);
+inline string ClassName(const EnumDescriptor* descriptor, bool qualified) {
+  return qualified ? QualifiedClassName(descriptor) : ClassName(descriptor);
+}
 
-// Name of the base class: either the dependent base class (for use with
-// proto_h) or google::protobuf::Message.
-string SuperClassName(const Descriptor* descriptor);
+// Fully qualified name of the default_instance of this message.
+string DefaultInstanceName(const Descriptor* descriptor);
 
-// Returns a string that down-casts from the dependent base class to the
-// derived class.
-string DependentBaseDownCast();
-string DependentBaseConstDownCast();
+// Returns the name of a no-op function that we can call to introduce a linker
+// dependency on the given message type. This is used to implement implicit weak
+// fields.
+string ReferenceFunctionName(const Descriptor* descriptor);
+
+// Name of the base class: google::protobuf::Message or google::protobuf::MessageLite.
+string SuperClassName(const Descriptor* descriptor, const Options& options);
 
 // Get the (unqualified) name that should be used for this field in C++ code.
 // The name is coerced to lower-case to emulate proto1 behavior.  People
@@ -88,6 +116,12 @@
 // Get the sanitized name that should be used for the given enum in C++ code.
 string EnumValueName(const EnumValueDescriptor* enum_value);
 
+// 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);
+
 // Get the unqualified name that should be used for a field's field
 // number constant.
 string FieldConstantName(const FieldDescriptor *field);
@@ -99,26 +133,12 @@
     field->extension_scope() : field->containing_type();
 }
 
-// Returns true if the given 'field_descriptor' has a message type that is
-// a dependency of the file where the field is defined (i.e., the field
-// type is defined in a different file than the message holding the field).
-//
-// This only applies to Message-typed fields. Enum-typed fields may refer
-// to an enum in a dependency; however, enums are specified and
-// forward-declared with an enum-base, so the definition is not required to
-// manipulate the field value.
-bool IsFieldDependent(const FieldDescriptor* field_descriptor);
-
-// Returns the name that should be used for forcing dependent lookup from a
-// dependent base class.
-string DependentTypeName(const FieldDescriptor* field);
-
 // Returns the fully-qualified type name field->message_type().  Usually this
 // is just ClassName(field->message_type(), true);
 string FieldMessageTypeName(const FieldDescriptor* field);
 
 // Strips ".proto" or ".protodevel" from the end of a filename.
-string StripProto(const string& filename);
+LIBPROTOC_EXPORT string StripProto(const string& filename);
 
 // Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.).
 // Note:  non-built-in type names will be qualified, meaning they will start
@@ -143,18 +163,19 @@
 // Convert a file name into a valid identifier.
 string FilenameIdentifier(const string& filename);
 
-// Return the name of the AddDescriptors() function for a given file.
-string GlobalAddDescriptorsName(const string& filename);
-
-// Return the name of the AssignDescriptors() function for a given file.
-string GlobalAssignDescriptorsName(const string& filename);
+// For each .proto file generates a unique namespace. In this namespace global
+// definitions are put to prevent collisions.
+string FileLevelNamespace(const string& filename);
+inline string FileLevelNamespace(const FileDescriptor* file) {
+  return FileLevelNamespace(file->name());
+}
+inline string FileLevelNamespace(const Descriptor* d) {
+  return FileLevelNamespace(d->file());
+}
 
 // Return the qualified C++ name for a file level symbol.
 string QualifiedFileLevelSymbol(const string& package, const string& name);
 
-// Return the name of the ShutdownFile() function for a given file.
-string GlobalShutdownFileName(const string& filename);
-
 // Escape C++ trigraphs by escaping question marks to \?
 string EscapeTrigraphs(const string& to_escape);
 
@@ -163,17 +184,30 @@
                         const FieldDescriptor* field,
                         const string& prefix);
 
-// Returns true if unknown fields are preseved after parsing.
-inline bool PreserveUnknownFields(const Descriptor* message) {
+// Returns true if unknown fields are always preserved after parsing.
+inline bool AlwaysPreserveUnknownFields(const FileDescriptor* file) {
+  return file->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
+// Returns true if unknown fields are preserved after parsing.
+inline bool AlwaysPreserveUnknownFields(const Descriptor* message) {
+  return AlwaysPreserveUnknownFields(message->file());
+}
+
+// Returns true if generated messages have public unknown fields accessors
+inline bool PublicUnknownFieldsAccessors(const Descriptor* message) {
   return message->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
 }
 
-// If PreserveUnknownFields() is true, determines whether unknown
-// fields will be stored in an UnknownFieldSet or a string.
-// If PreserveUnknownFields() is false, this method will not be
-// used.
-inline bool UseUnknownFieldSet(const FileDescriptor* file) {
-  return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
+// Returns the optimize mode for <file>, respecting <options.enforce_lite>.
+::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor(
+    const FileDescriptor* file, const Options& options);
+
+// Determines whether unknown fields will be stored in an UnknownFieldSet or
+// a string.
+inline bool UseUnknownFieldSet(const FileDescriptor* file,
+                               const Options& options) {
+  return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
 }
 
 
@@ -186,46 +220,33 @@
 
 // Does this file have generated parsing, serialization, and other
 // standard methods for which reflection-based fallback implementations exist?
-inline bool HasGeneratedMethods(const FileDescriptor* file) {
-  return file->options().optimize_for() != FileOptions::CODE_SIZE;
+inline bool HasGeneratedMethods(const FileDescriptor* file,
+                                const Options& options) {
+  return GetOptimizeFor(file, options) != FileOptions::CODE_SIZE;
 }
 
 // Do message classes in this file have descriptor and reflection methods?
-inline bool HasDescriptorMethods(const FileDescriptor* file) {
-  return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
+inline bool HasDescriptorMethods(const FileDescriptor* file,
+                                 const Options& options) {
+  return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
 }
 
 // Should we generate generic services for this file?
-inline bool HasGenericServices(const FileDescriptor* file) {
+inline bool HasGenericServices(const FileDescriptor* file,
+                               const Options& options) {
   return file->service_count() > 0 &&
-         file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
+         GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME &&
          file->options().cc_generic_services();
 }
 
 // Should we generate a separate, super-optimized code path for serializing to
 // flat arrays?  We don't do this in Lite mode because we'd rather reduce code
 // size.
-inline bool HasFastArraySerialization(const FileDescriptor* file) {
-  return file->options().optimize_for() == FileOptions::SPEED;
+inline bool HasFastArraySerialization(const FileDescriptor* file,
+                                      const Options& options) {
+  return GetOptimizeFor(file, options) == FileOptions::SPEED;
 }
 
-// Returns whether we have to generate code with static initializers.
-bool StaticInitializersForced(const FileDescriptor* file);
-
-// Prints 'with_static_init' if static initializers have to be used for the
-// provided file. Otherwise emits both 'with_static_init' and
-// 'without_static_init' using #ifdef.
-void PrintHandlingOptionalStaticInitializers(
-    const FileDescriptor* file, io::Printer* printer,
-    const char* with_static_init, const char* without_static_init,
-    const char* var1 = NULL, const string& val1 = "",
-    const char* var2 = NULL, const string& val2 = "");
-
-void PrintHandlingOptionalStaticInitializers(
-    const map<string, string>& vars, const FileDescriptor* file,
-    io::Printer* printer, const char* with_static_init,
-    const char* without_static_init);
-
 
 inline bool IsMapEntryMessage(const Descriptor* descriptor) {
   return descriptor->options().map_entry();
@@ -262,24 +283,175 @@
   return SupportsArenas(field->file());
 }
 
+inline bool IsCrossFileMessage(const FieldDescriptor* field) {
+  return field->type() == FieldDescriptor::TYPE_MESSAGE &&
+         field->message_type()->file() != field->file();
+}
+
+inline string MessageCreateFunction(const Descriptor* d) {
+  return SupportsArenas(d) ? "CreateMessage" : "Create";
+}
+
+inline string MakeDefaultName(const FieldDescriptor* field) {
+  return "_i_give_permission_to_break_this_code_default_" + FieldName(field) +
+         "_";
+}
+
 bool IsAnyMessage(const FileDescriptor* descriptor);
 bool IsAnyMessage(const Descriptor* descriptor);
 
 bool IsWellKnownMessage(const FileDescriptor* descriptor);
 
-void GenerateUtf8CheckCodeForString(
-    const FieldDescriptor* field,
-    bool for_parse,
-    const map<string, string>& variables,
-    const char* parameters,
-    io::Printer* printer);
+void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
+                                    const Options& options, bool for_parse,
+                                    const std::map<string, string>& variables,
+                                    const char* parameters,
+                                    io::Printer* printer);
 
-void GenerateUtf8CheckCodeForCord(
-    const FieldDescriptor* field,
-    bool for_parse,
-    const map<string, string>& variables,
-    const char* parameters,
-    io::Printer* printer);
+void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
+                                  const Options& options, bool for_parse,
+                                  const std::map<string, string>& variables,
+                                  const char* parameters, io::Printer* printer);
+
+inline ::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor(
+    const FileDescriptor* file, const Options& options) {
+  return options.enforce_lite
+      ? FileOptions::LITE_RUNTIME
+      : file->options().optimize_for();
+}
+
+// This orders the messages in a .pb.cc as it's outputted by file.cc
+void FlattenMessagesInFile(const FileDescriptor* file,
+                           std::vector<const Descriptor*>* result);
+inline std::vector<const Descriptor*> FlattenMessagesInFile(
+    const FileDescriptor* file) {
+  std::vector<const Descriptor*> result;
+  FlattenMessagesInFile(file, &result);
+  return result;
+}
+
+bool HasWeakFields(const Descriptor* desc);
+bool HasWeakFields(const FileDescriptor* desc);
+
+// Returns true if the "required" restriction check should be ignored for the
+// given field.
+inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field,
+                                                  const Options& options) {
+  return false;
+}
+
+class LIBPROTOC_EXPORT NamespaceOpener {
+ public:
+  explicit NamespaceOpener(io::Printer* printer) : printer_(printer) {}
+  NamespaceOpener(const string& name, io::Printer* printer)
+      : printer_(printer) {
+    ChangeTo(name);
+  }
+  ~NamespaceOpener() { ChangeTo(""); }
+
+  void ChangeTo(const string& name) {
+    std::vector<string> new_stack_ =
+        Split(name, "::", true);
+    int len = std::min(name_stack_.size(), new_stack_.size());
+    int common_idx = 0;
+    while (common_idx < len) {
+      if (name_stack_[common_idx] != new_stack_[common_idx]) break;
+      common_idx++;
+    }
+    for (int i = name_stack_.size() - 1; i >= common_idx; i--) {
+      printer_->Print("}  // namespace $ns$\n", "ns", name_stack_[i]);
+    }
+    name_stack_.swap(new_stack_);
+    for (int i = common_idx; i < name_stack_.size(); i++) {
+      printer_->Print("namespace $ns$ {\n", "ns", name_stack_[i]);
+    }
+  }
+
+ private:
+  io::Printer* printer_;
+  std::vector<string> name_stack_;
+};
+
+// Description of each strongly connected component. Note that the order
+// of both the descriptors in this SCC and the order of children is
+// deterministic.
+struct SCC {
+  std::vector<const Descriptor*> descriptors;
+  std::vector<const SCC*> children;
+
+  const Descriptor* GetRepresentative() const { return descriptors[0]; }
+};
+
+struct MessageAnalysis {
+  bool is_recursive;
+  bool contains_cord;
+  bool contains_extension;
+  bool contains_required;
+};
+
+// This class is used in FileGenerator, to ensure linear instead of
+// quadratic performance, if we do this per message we would get O(V*(V+E)).
+// Logically this is just only used in message.cc, but in the header for
+// FileGenerator to help share it.
+class LIBPROTOC_EXPORT SCCAnalyzer {
+ public:
+  explicit SCCAnalyzer(const Options& options) : options_(options), index_(0) {}
+  ~SCCAnalyzer() {
+    for (int i = 0; i < garbage_bin_.size(); i++) delete garbage_bin_[i];
+  }
+
+  const SCC* GetSCC(const Descriptor* descriptor) {
+    if (cache_.count(descriptor)) return cache_[descriptor].scc;
+    return DFS(descriptor).scc;
+  }
+
+  MessageAnalysis GetSCCAnalysis(const SCC* scc);
+
+  bool HasRequiredFields(const Descriptor* descriptor) {
+    MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor));
+    return result.contains_required || result.contains_extension;
+  }
+
+ private:
+  struct NodeData {
+    const SCC* scc;  // if null it means its still on the stack
+    int index;
+    int lowlink;
+  };
+
+  Options options_;
+  std::map<const Descriptor*, NodeData> cache_;
+  std::map<const SCC*, MessageAnalysis> analysis_cache_;
+  std::vector<const Descriptor*> stack_;
+  int index_;
+  std::vector<SCC*> garbage_bin_;
+
+  SCC* CreateSCC() {
+    garbage_bin_.push_back(new SCC());
+    return garbage_bin_.back();
+  }
+
+  // Tarjan's Strongly Connected Components algo
+  NodeData DFS(const Descriptor* descriptor);
+
+  // Add the SCC's that are children of this SCC to its children.
+  void AddChildren(SCC* scc);
+};
+
+void ListAllFields(const Descriptor* d,
+                   std::vector<const FieldDescriptor*>* fields);
+void ListAllFields(const FileDescriptor* d,
+                   std::vector<const FieldDescriptor*>* fields);
+void ListAllTypesForServices(const FileDescriptor* fd,
+                             std::vector<const Descriptor*>* types);
+
+// Indicates whether we should use implicit weak fields for this file.
+bool UsingImplicitWeakFields(const FileDescriptor* file,
+                             const Options& options);
+
+// Indicates whether to treat this field as implicitly weak.
+bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options,
+                         SCCAnalyzer* scc_analyzer);
 
 }  // namespace cpp
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
index e5e2f07..0e485ca 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -32,6 +32,7 @@
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/wire_format.h>
+
 #include <google/protobuf/stubs/strutil.h>
 
 namespace google {
@@ -45,14 +46,17 @@
 }
 
 void SetMessageVariables(const FieldDescriptor* descriptor,
-                         map<string, string>* variables,
+                         std::map<string, string>* variables,
                          const Options& options) {
   SetCommonFieldVariables(descriptor, variables, options);
-  (*variables)["type"] = FieldMessageTypeName(descriptor);
-  (*variables)["stream_writer"] = (*variables)["declared_type"] +
-      (HasFastArraySerialization(descriptor->message_type()->file()) ?
-       "MaybeToArray" :
-       "");
+  (*variables)["type"] = ClassName(descriptor->message_type(), false);
+  (*variables)["file_namespace"] =
+      FileLevelNamespace(descriptor->file()->name());
+  (*variables)["stream_writer"] =
+      (*variables)["declared_type"] +
+      (HasFastArraySerialization(descriptor->message_type()->file(), options)
+           ? "MaybeToArray"
+           : "");
   (*variables)["full_name"] = descriptor->full_name();
 
   const FieldDescriptor* key =
@@ -83,7 +87,7 @@
   (*variables)["number"] = SimpleItoa(descriptor->number());
   (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
 
-  if (HasDescriptorMethods(descriptor->file())) {
+  if (HasDescriptorMethods(descriptor->file(), options)) {
     (*variables)["lite"] = "";
   } else {
     (*variables)["lite"] = "Lite";
@@ -98,11 +102,9 @@
   }
 }
 
-MapFieldGenerator::
-MapFieldGenerator(const FieldDescriptor* descriptor,
-                  const Options& options)
-    : descriptor_(descriptor),
-      dependent_field_(options.proto_h && IsFieldDependent(descriptor)) {
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
+                                     const Options& options)
+    : FieldGenerator(options), descriptor_(descriptor) {
   SetMessageVariables(descriptor, &variables_, options);
 }
 
@@ -111,40 +113,36 @@
 void MapFieldGenerator::
 GeneratePrivateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-      "typedef ::google::protobuf::internal::MapEntryLite<\n"
-      "    $key_cpp$, $val_cpp$,\n"
-      "    $key_wire_type$,\n"
-      "    $val_wire_type$,\n"
-      "    $default_enum_value$ >\n"
-      "    $map_classname$;\n"
-      "::google::protobuf::internal::MapField$lite$<\n"
-      "    $key_cpp$, $val_cpp$,\n"
-      "    $key_wire_type$,\n"
-      "    $val_wire_type$,\n"
-      "    $default_enum_value$ > $name$_;\n");
+                 "::google::protobuf::internal::MapField$lite$<\n"
+                 "    $map_classname$,\n"
+                 "    $key_cpp$, $val_cpp$,\n"
+                 "    $key_wire_type$,\n"
+                 "    $val_wire_type$,\n"
+                 "    $default_enum_value$ > $name$_;\n");
 }
 
 void MapFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "$deprecated_attr$const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
+      "    $name$() const;\n");
+  printer->Annotate("name", descriptor_);
   printer->Print(variables_,
-      "const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
-      "    $name$() const$deprecation$;\n"
-      "::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
-      "    mutable_$name$()$deprecation$;\n");
+                 "$deprecated_attr$::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
+                 "    ${$mutable_$name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void MapFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                  bool is_inline) const {
-  map<string, string> variables(variables_);
-  variables["inline"] = is_inline ? "inline" : "";
-  printer->Print(variables,
-      "$inline$ const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+  printer->Print(variables_,
+      "inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
       "$classname$::$name$() const {\n"
       "  // @@protoc_insertion_point(field_map:$full_name$)\n"
       "  return $name$_.GetMap();\n"
       "}\n"
-      "$inline$ ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
+      "inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
       "$classname$::mutable_$name$() {\n"
       "  // @@protoc_insertion_point(field_mutable_map:$full_name$)\n"
       "  return $name$_.MutableMap();\n"
@@ -153,9 +151,7 @@
 
 void MapFieldGenerator::
 GenerateClearingCode(io::Printer* printer) const {
-  map<string, string> variables(variables_);
-  variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
-  printer->Print(variables, "$this_message$$name$_.Clear();\n");
+  printer->Print(variables_, "$name$_.Clear();\n");
 }
 
 void MapFieldGenerator::
@@ -169,45 +165,42 @@
 }
 
 void MapFieldGenerator::
-GenerateConstructorCode(io::Printer* printer) const {
-  if (HasDescriptorMethods(descriptor_->file())) {
-    printer->Print(variables_,
-        "$name$_.SetAssignDescriptorCallback(\n"
-        "    protobuf_AssignDescriptorsOnce);\n"
-        "$name$_.SetEntryDescriptor(\n"
-        "    &$type$_descriptor_);\n");
-  }
+GenerateCopyConstructorCode(io::Printer* printer) const {
+  GenerateConstructorCode(printer);
+  GenerateMergingCode(printer);
 }
 
 void MapFieldGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) const {
+    const FieldDescriptor* key_field =
+        descriptor_->message_type()->FindFieldByName("key");
   const FieldDescriptor* value_field =
       descriptor_->message_type()->FindFieldByName("value");
-  printer->Print(variables_,
-      "::google::protobuf::scoped_ptr<$map_classname$> entry($name$_.NewEntry());\n");
-
+  bool using_entry = false;
+  string key;
+  string value;
   if (IsProto3Field(descriptor_) ||
       value_field->type() != FieldDescriptor::TYPE_ENUM) {
-    printer->Print(variables_,
+    printer->Print(
+        variables_,
+        "$map_classname$::Parser< ::google::protobuf::internal::MapField$lite$<\n"
+        "    $map_classname$,\n"
+        "    $key_cpp$, $val_cpp$,\n"
+        "    $key_wire_type$,\n"
+        "    $val_wire_type$,\n"
+        "    $default_enum_value$ >,\n"
+        "  ::google::protobuf::Map< $key_cpp$, $val_cpp$ > >"
+        " parser(&$name$_);\n"
         "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
-        "    input, entry.get()));\n");
-    switch (value_field->cpp_type()) {
-      case FieldDescriptor::CPPTYPE_MESSAGE:
-        printer->Print(variables_,
-            "(*mutable_$name$())[entry->key()].Swap("
-            "entry->mutable_value());\n");
-        break;
-      case FieldDescriptor::CPPTYPE_ENUM:
-        printer->Print(variables_,
-            "(*mutable_$name$())[entry->key()] =\n"
-            "    static_cast< $val_cpp$ >(*entry->mutable_value());\n");
-        break;
-      default:
-        printer->Print(variables_,
-            "(*mutable_$name$())[entry->key()] = *entry->mutable_value();\n");
-        break;
-    }
+        "    input, &parser));\n");
+    key = "parser.key()";
+    value = "parser.value()";
   } else {
+    using_entry = true;
+    key = "entry->key()";
+    value = "entry->value()";
+    printer->Print(variables_,
+        "::std::unique_ptr<$map_classname$> entry($name$_.NewEntry());\n");
     printer->Print(variables_,
         "{\n"
         "  ::std::string data;\n"
@@ -217,164 +210,197 @@
         "    (*mutable_$name$())[entry->key()] =\n"
         "        static_cast< $val_cpp$ >(*entry->mutable_value());\n"
         "  } else {\n");
-    if (HasDescriptorMethods(descriptor_->file())) {
+    if (HasDescriptorMethods(descriptor_->file(), options_)) {
       printer->Print(variables_,
           "    mutable_unknown_fields()"
           "->AddLengthDelimited($number$, data);\n");
     } else {
       printer->Print(variables_,
-          "    unknown_fields_stream.WriteVarint32($tag$);\n"
-          "    unknown_fields_stream.WriteVarint32(data.size());\n"
+          "    unknown_fields_stream.WriteVarint32($tag$u);\n"
+          "    unknown_fields_stream.WriteVarint32(\n"
+          "        static_cast< ::google::protobuf::uint32>(data.size()));\n"
           "    unknown_fields_stream.WriteString(data);\n");
     }
 
-
     printer->Print(variables_,
         "  }\n"
         "}\n");
   }
 
-  const FieldDescriptor* key_field =
-      descriptor_->message_type()->FindFieldByName("key");
   if (key_field->type() == FieldDescriptor::TYPE_STRING) {
     GenerateUtf8CheckCodeForString(
-        key_field, true, variables_,
-        "entry->key().data(), entry->key().length(),\n", printer);
+        key_field, options_, true, variables_,
+        StrCat(key, ".data(), static_cast<int>(", key, ".length()),\n").data(),
+        printer);
   }
   if (value_field->type() == FieldDescriptor::TYPE_STRING) {
     GenerateUtf8CheckCodeForString(
-        value_field, true, variables_,
-        "entry->mutable_value()->data(),\n"
-        "entry->mutable_value()->length(),\n", printer);
+        value_field, options_, true, variables_,
+        StrCat(value, ".data(), static_cast<int>(", value, ".length()),\n")
+            .data(),
+        printer);
   }
 
   // If entry is allocated by arena, its desctructor should be avoided.
-  if (SupportsArenas(descriptor_)) {
+  if (using_entry && SupportsArenas(descriptor_)) {
     printer->Print(variables_,
         "if (entry->GetArena() != NULL) entry.release();\n");
   }
 }
 
+static void GenerateSerializationLoop(io::Printer* printer,
+                                      const std::map<string, string>& variables,
+                                      bool supports_arenas,
+                                      const string& utf8_check,
+                                      const string& loop_header,
+                                      const string& ptr,
+                                      bool loop_via_iterators) {
+  printer->Print(variables,
+      StrCat("::std::unique_ptr<$map_classname$> entry;\n",
+             loop_header, " {\n").c_str());
+  printer->Indent();
+
+  printer->Print(variables, StrCat(
+      "entry.reset($name$_.New$wrapper$(\n"
+      "    ", ptr, "->first, ", ptr, "->second));\n"
+      "$write_entry$;\n").c_str());
+
+  // If entry is allocated by arena, its desctructor should be avoided.
+  if (supports_arenas) {
+    printer->Print(
+        "if (entry->GetArena() != NULL) {\n"
+        "  entry.release();\n"
+        "}\n");
+  }
+
+  if (!utf8_check.empty()) {
+    // If loop_via_iterators is true then ptr is actually an iterator, and we
+    // create a pointer by prefixing it with "&*".
+    printer->Print(
+        StrCat(utf8_check, "(", (loop_via_iterators ? "&*" : ""), ptr, ");\n")
+            .c_str());
+  }
+
+  printer->Outdent();
+  printer->Print(
+      "}\n");
+}
+
 void MapFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
-  printer->Print(variables_,
-      "{\n"
-      "  ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
-      "  for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
-      "      it = this->$name$().begin();\n"
-      "      it != this->$name$().end(); ++it) {\n");
-
-  // If entry is allocated by arena, its desctructor should be avoided.
-  if (SupportsArenas(descriptor_)) {
-    printer->Print(variables_,
-        "    if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
-        "      entry.release();\n"
-        "    }\n");
-  }
-
-  printer->Print(variables_,
-      "    entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
-      "    ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
-      "        $number$, *entry, output);\n");
-
-  printer->Indent();
-  printer->Indent();
-
-  const FieldDescriptor* key_field =
-      descriptor_->message_type()->FindFieldByName("key");
-  const FieldDescriptor* value_field =
-      descriptor_->message_type()->FindFieldByName("value");
-  if (key_field->type() == FieldDescriptor::TYPE_STRING) {
-    GenerateUtf8CheckCodeForString(
-        key_field, false, variables_,
-        "it->first.data(), it->first.length(),\n", printer);
-  }
-  if (value_field->type() == FieldDescriptor::TYPE_STRING) {
-    GenerateUtf8CheckCodeForString(
-        value_field, false, variables_,
-        "it->second.data(), it->second.length(),\n", printer);
-  }
-
-  printer->Outdent();
-  printer->Outdent();
-
-  printer->Print(
-      "  }\n");
-
-  // If entry is allocated by arena, its desctructor should be avoided.
-  if (SupportsArenas(descriptor_)) {
-    printer->Print(variables_,
-        "  if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
-        "    entry.release();\n"
-        "  }\n");
-  }
-
-  printer->Print("}\n");
+  std::map<string, string> variables(variables_);
+  variables["write_entry"] = "::google::protobuf::internal::WireFormatLite::Write" +
+                             variables["stream_writer"] + "(\n            " +
+                             variables["number"] + ", *entry, output)";
+  variables["deterministic"] = "output->IsSerializationDeterministic()";
+  GenerateSerializeWithCachedSizes(printer, variables);
 }
 
 void MapFieldGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
-  printer->Print(variables_,
-      "{\n"
-      "  ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
-      "  for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
-      "      it = this->$name$().begin();\n"
-      "      it != this->$name$().end(); ++it) {\n");
+  std::map<string, string> variables(variables_);
+  variables["write_entry"] =
+      "target = ::google::protobuf::internal::WireFormatLite::\n"
+      "                   InternalWrite" + variables["declared_type"] +
+      "NoVirtualToArray(\n                       " + variables["number"] +
+      ", *entry, deterministic, target);\n";
+  variables["deterministic"] = "deterministic";
+  GenerateSerializeWithCachedSizes(printer, variables);
+}
 
-  // If entry is allocated by arena, its desctructor should be avoided.
-  if (SupportsArenas(descriptor_)) {
-    printer->Print(variables_,
-        "    if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
-        "      entry.release();\n"
-        "    }\n");
-  }
-
-  printer->Print(variables_,
-      "    entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
-      "    target = ::google::protobuf::internal::WireFormatLite::\n"
-      "        Write$declared_type$NoVirtualToArray(\n"
-      "            $number$, *entry, target);\n");
-
+void MapFieldGenerator::GenerateSerializeWithCachedSizes(
+    io::Printer* printer, const std::map<string, string>& variables) const {
+  printer->Print(variables,
+      "if (!this->$name$().empty()) {\n");
   printer->Indent();
-  printer->Indent();
-
   const FieldDescriptor* key_field =
       descriptor_->message_type()->FindFieldByName("key");
   const FieldDescriptor* value_field =
       descriptor_->message_type()->FindFieldByName("value");
-  if (key_field->type() == FieldDescriptor::TYPE_STRING) {
-    GenerateUtf8CheckCodeForString(
-        key_field, false, variables_,
-        "it->first.data(), it->first.length(),\n", printer);
+  const bool string_key = key_field->type() == FieldDescriptor::TYPE_STRING;
+  const bool string_value = value_field->type() == FieldDescriptor::TYPE_STRING;
+
+  printer->Print(variables,
+      "typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_pointer\n"
+      "    ConstPtr;\n");
+  if (string_key) {
+    printer->Print(variables,
+        "typedef ConstPtr SortItem;\n"
+        "typedef ::google::protobuf::internal::"
+        "CompareByDerefFirst<SortItem> Less;\n");
+  } else {
+    printer->Print(variables,
+        "typedef ::google::protobuf::internal::SortItem< $key_cpp$, ConstPtr > "
+        "SortItem;\n"
+        "typedef ::google::protobuf::internal::CompareByFirstField<SortItem> Less;\n");
   }
-  if (value_field->type() == FieldDescriptor::TYPE_STRING) {
-    GenerateUtf8CheckCodeForString(
-        value_field, false, variables_,
-        "it->second.data(), it->second.length(),\n", printer);
+  string utf8_check;
+  if (string_key || string_value) {
+    printer->Print(
+        "struct Utf8Check {\n"
+        "  static void Check(ConstPtr p) {\n");
+    printer->Indent();
+    printer->Indent();
+    if (string_key) {
+      GenerateUtf8CheckCodeForString(
+          key_field, options_, false, variables,
+          "p->first.data(), static_cast<int>(p->first.length()),\n", printer);
+    }
+    if (string_value) {
+      GenerateUtf8CheckCodeForString(
+          value_field, options_, false, variables,
+          "p->second.data(), static_cast<int>(p->second.length()),\n", printer);
+    }
+    printer->Outdent();
+    printer->Outdent();
+    printer->Print(
+        "  }\n"
+        "};\n");
+    utf8_check = "Utf8Check::Check";
   }
 
-  printer->Outdent();
+  printer->Print(variables,
+      "\n"
+      "if ($deterministic$ &&\n"
+      "    this->$name$().size() > 1) {\n"
+      "  ::std::unique_ptr<SortItem[]> items(\n"
+      "      new SortItem[this->$name$().size()]);\n"
+      "  typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::size_type size_type;\n"
+      "  size_type n = 0;\n"
+      "  for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
+      "      it = this->$name$().begin();\n"
+      "      it != this->$name$().end(); ++it, ++n) {\n"
+      "    items[static_cast<ptrdiff_t>(n)] = SortItem(&*it);\n"
+      "  }\n"
+      "  ::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());\n");
+  printer->Indent();
+  GenerateSerializationLoop(printer, variables, SupportsArenas(descriptor_),
+      utf8_check, "for (size_type i = 0; i < n; i++)",
+      string_key ? "items[static_cast<ptrdiff_t>(i)]" :
+                   "items[static_cast<ptrdiff_t>(i)].second", false);
   printer->Outdent();
   printer->Print(
-      "  }\n");
-
-  // If entry is allocated by arena, its desctructor should be avoided.
-  if (SupportsArenas(descriptor_)) {
-    printer->Print(variables_,
-        "  if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
-        "    entry.release();\n"
-        "  }\n");
-  }
-
+      "} else {\n");
+  printer->Indent();
+  GenerateSerializationLoop(
+      printer, variables, SupportsArenas(descriptor_), utf8_check,
+      "for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
+      "    it = this->$name$().begin();\n"
+      "    it != this->$name$().end(); ++it)",
+      "it", true);
+  printer->Outdent();
+  printer->Print("}\n");
+  printer->Outdent();
   printer->Print("}\n");
 }
 
 void MapFieldGenerator::
 GenerateByteSize(io::Printer* printer) const {
   printer->Print(variables_,
-      "total_size += $tag_size$ * this->$name$_size();\n"
+      "total_size += $tag_size$ *\n"
+      "    ::google::protobuf::internal::FromIntSize(this->$name$_size());\n"
       "{\n"
-      "  ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
+      "  ::std::unique_ptr<$map_classname$> entry;\n"
       "  for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
       "      it = this->$name$().begin();\n"
       "      it != this->$name$().end(); ++it) {\n");
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.h b/src/google/protobuf/compiler/cpp/cpp_map_field.h
index 5e20562..0d54f0e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.h
@@ -43,28 +43,30 @@
 
 class MapFieldGenerator : public FieldGenerator {
  public:
-  explicit MapFieldGenerator(const FieldDescriptor* descriptor,
-                             const Options& options);
+  MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
   ~MapFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
   void GeneratePrivateMembers(io::Printer* printer) const;
   void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                         bool is_inline) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
-  void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateConstructorCode(io::Printer* printer) const {}
+  void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
 
  private:
+  // A helper for GenerateSerializeWithCachedSizes{,ToArray}.
+  void GenerateSerializeWithCachedSizes(
+      io::Printer* printer, const std::map<string, string>& variables) const;
+
   const FieldDescriptor* descriptor_;
-  const bool dependent_field_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
 };
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 8304ebb..8c2336a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -32,25 +32,30 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/cpp/cpp_message.h>
+
 #include <algorithm>
 #include <google/protobuf/stubs/hash.h>
 #include <map>
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 #include <utility>
 #include <vector>
-#include <google/protobuf/compiler/cpp/cpp_message.h>
-#include <google/protobuf/compiler/cpp/cpp_field.h>
+
 #include <google/protobuf/compiler/cpp/cpp_enum.h>
 #include <google/protobuf/compiler/cpp/cpp_extension.h>
+#include <google/protobuf/compiler/cpp/cpp_field.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/wire_format.h>
+#include <google/protobuf/compiler/cpp/cpp_padding_optimizer.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/generated_message_table_driven.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/map_entry_lite.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
 
 
 namespace google {
@@ -85,14 +90,13 @@
 
 // Sort the fields of the given Descriptor by number into a new[]'d array
 // and return it.
-const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
-  const FieldDescriptor** fields =
-    new const FieldDescriptor*[descriptor->field_count()];
+std::vector<const FieldDescriptor*> SortFieldsByNumber(
+    const Descriptor* descriptor) {
+  std::vector<const FieldDescriptor*> fields(descriptor->field_count());
   for (int i = 0; i < descriptor->field_count(); i++) {
     fields[i] = descriptor->field(i);
   }
-  std::sort(fields, fields + descriptor->field_count(),
-            FieldOrderingByNumber());
+  std::sort(fields.begin(), fields.end(), FieldOrderingByNumber());
   return fields;
 }
 
@@ -104,188 +108,37 @@
   }
 };
 
-// Returns true if the "required" restriction check should be ignored for the
-// given field.
-inline static bool ShouldIgnoreRequiredFieldCheck(
-    const FieldDescriptor* field) {
-  return false;
-}
-
-// Returns true if the message type has any required fields.  If it doesn't,
-// we can optimize out calls to its IsInitialized() method.
-//
-// already_seen is used to avoid checking the same type multiple times
-// (and also to protect against recursion).
-static bool HasRequiredFields(
-    const Descriptor* type,
-    hash_set<const Descriptor*>* already_seen) {
-  if (already_seen->count(type) > 0) {
-    // Since the first occurrence of a required field causes the whole
-    // function to return true, we can assume that if the type is already
-    // in the cache it didn't have any required fields.
-    return false;
-  }
-  already_seen->insert(type);
-
-  // If the type has extensions, an extension with message type could contain
-  // required fields, so we have to be conservative and assume such an
-  // extension exists.
-  if (type->extension_range_count() > 0) return true;
-
-  for (int i = 0; i < type->field_count(); i++) {
-    const FieldDescriptor* field = type->field(i);
-    if (field->is_required()) {
-      return true;
-    }
-    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
-        !ShouldIgnoreRequiredFieldCheck(field)) {
-      if (HasRequiredFields(field->message_type(), already_seen)) {
-        return true;
-      }
-    }
-  }
-
-  return false;
-}
-
-static bool HasRequiredFields(const Descriptor* type) {
-  hash_set<const Descriptor*> already_seen;
-  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;
+bool IsPOD(const FieldDescriptor* field) {
+  if (field->is_repeated() || field->is_extension()) return false;
   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_INT32:
     case FieldDescriptor::CPPTYPE_INT64:
+    case FieldDescriptor::CPPTYPE_UINT32:
     case FieldDescriptor::CPPTYPE_UINT64:
+    case FieldDescriptor::CPPTYPE_FLOAT:
     case FieldDescriptor::CPPTYPE_DOUBLE:
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return true;
     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.  Using stable_sort ensures that the output is
-  // consistent across runs.
-  std::stable_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.
-  std::stable_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());
+      return false;
+    default:
+      return false;
   }
 }
 
-string MessageTypeProtoName(const FieldDescriptor* field) {
-  return field->message_type()->full_name();
+// Helper for the code that emits the SharedCtor() method.
+bool CanConstructByZeroing(const FieldDescriptor* field,
+                           const Options& options) {
+  bool ret = CanInitializeByZeroing(field);
+
+  // Non-repeated, non-lazy message fields are simply raw pointers, so we can
+  // use memset to initialize these in SharedCtor.  We cannot use this in
+  // Clear, as we need to potentially delete the existing value.
+  ret = ret ||
+      (!field->is_repeated() &&
+       field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE);
+  return ret;
 }
 
 // Emits an if-statement with a condition that evaluates to true if |field| is
@@ -340,27 +193,33 @@
 
 // Collects map entry message type information.
 void CollectMapInfo(const Descriptor* descriptor,
-                    map<string, string>* variables) {
+                    std::map<string, string>* variables) {
   GOOGLE_CHECK(IsMapEntryMessage(descriptor));
+  std::map<string, string>& vars = *variables;
   const FieldDescriptor* key = descriptor->FindFieldByName("key");
   const FieldDescriptor* val = descriptor->FindFieldByName("value");
-  (*variables)["key"] = PrimitiveTypeName(key->cpp_type());
+  vars["key_cpp"] = PrimitiveTypeName(key->cpp_type());
   switch (val->cpp_type()) {
     case FieldDescriptor::CPPTYPE_MESSAGE:
-      (*variables)["val"] = FieldMessageTypeName(val);
+      vars["val_cpp"] = FieldMessageTypeName(val);
       break;
     case FieldDescriptor::CPPTYPE_ENUM:
-      (*variables)["val"] = ClassName(val->enum_type(), true);
+      vars["val_cpp"] = ClassName(val->enum_type(), true);
       break;
     default:
-      (*variables)["val"] = PrimitiveTypeName(val->cpp_type());
+      vars["val_cpp"] = PrimitiveTypeName(val->cpp_type());
   }
-  (*variables)["key_wire_type"] =
-      "::google::protobuf::internal::WireFormatLite::TYPE_" +
-      ToUpper(DeclaredTypeMethodName(key->type()));
-  (*variables)["val_wire_type"] =
-      "::google::protobuf::internal::WireFormatLite::TYPE_" +
-      ToUpper(DeclaredTypeMethodName(val->type()));
+  vars["key_wire_type"] = "::google::protobuf::internal::WireFormatLite::TYPE_" +
+                          ToUpper(DeclaredTypeMethodName(key->type()));
+  vars["val_wire_type"] = "::google::protobuf::internal::WireFormatLite::TYPE_" +
+                          ToUpper(DeclaredTypeMethodName(val->type()));
+  if (descriptor->file()->syntax() != FileDescriptor::SYNTAX_PROTO3 &&
+      val->type() == FieldDescriptor::TYPE_ENUM) {
+    const EnumValueDescriptor* default_value = val->default_value_enum();
+    vars["default_enum_value"] = Int32ToString(default_value->number());
+  } else {
+    vars["default_enum_value"] = "0";
+  }
 }
 
 // Does the given field have a private (internal helper only) has_$name$()
@@ -372,27 +231,247 @@
           field->containing_oneof() != NULL);
 }
 
+
+bool TableDrivenParsingEnabled(
+    const Descriptor* descriptor, const Options& options) {
+  if (!options.table_driven_parsing) {
+    return false;
+  }
+
+  // Consider table-driven parsing.  We only do this if:
+  // - We have has_bits for fields.  This avoids a check on every field we set
+  //   when are present (the common case).
+  if (!HasFieldPresence(descriptor->file())) {
+    return false;
+  }
+
+  const double table_sparseness = 0.5;
+  int max_field_number = 0;
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    const FieldDescriptor* field = descriptor->field(i);
+    if (max_field_number < field->number()) {
+      max_field_number = field->number();
+    }
+
+    // - There are no weak fields.
+    if (field->options().weak()) {
+      return false;
+    }
+  }
+
+  // - There range of field numbers is "small"
+  if (max_field_number >= (2 << 14)) {
+    return false;
+  }
+
+  // - Field numbers are relatively dense within the actual number of fields.
+  //   We check for strictly greater than in the case where there are no fields
+  //   (only extensions) so max_field_number == descriptor->field_count() == 0.
+  if (max_field_number * table_sparseness > descriptor->field_count()) {
+    return false;
+  }
+
+  // - This is not a MapEntryMessage.
+  if (IsMapEntryMessage(descriptor)) {
+    return false;
+  }
+
+  return true;
+}
+
+void SetUnknkownFieldsVariable(const Descriptor* descriptor,
+                               const Options& options,
+                               std::map<string, string>* variables) {
+  if (UseUnknownFieldSet(descriptor->file(), options)) {
+    (*variables)["unknown_fields_type"] = "::google::protobuf::UnknownFieldSet";
+  } else {
+    (*variables)["unknown_fields_type"] = "::std::string";
+  }
+  if (AlwaysPreserveUnknownFields(descriptor)) {
+    (*variables)["have_unknown_fields"] =
+        "_internal_metadata_.have_unknown_fields()";
+    (*variables)["unknown_fields"] = "_internal_metadata_.unknown_fields()";
+  } else {
+    (*variables)["have_unknown_fields"] =
+        "(_internal_metadata_.have_unknown_fields() && "
+        " ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())";
+    (*variables)["unknown_fields"] =
+        "(::google::protobuf::internal::GetProto3PreserveUnknownsDefault()"
+        "   ? _internal_metadata_.unknown_fields()"
+        "   : _internal_metadata_.default_instance())";
+  }
+  (*variables)["mutable_unknown_fields"] =
+      "_internal_metadata_.mutable_unknown_fields()";
+}
+
+bool IsCrossFileMapField(const FieldDescriptor* field) {
+  if (!field->is_map()) {
+    return false;
+  }
+
+  const Descriptor* d = field->message_type();
+  const FieldDescriptor* value = d->FindFieldByNumber(2);
+
+  return IsCrossFileMessage(value);
+}
+
+bool IsCrossFileMaybeMap(const FieldDescriptor* field) {
+  if (IsCrossFileMapField(field)) {
+    return true;
+  }
+
+  return IsCrossFileMessage(field);
+}
+
+bool IsRequired(const std::vector<const FieldDescriptor*>& v) {
+  return v.front()->is_required();
+}
+
+// Allows chunking repeated fields together and non-repeated fields if the
+// fields share the same has_byte index.
+// TODO(seongkim): use lambda with capture instead of functor.
+class MatchRepeatedAndHasByte {
+ public:
+  MatchRepeatedAndHasByte(const std::vector<int>* has_bit_indices,
+                          bool has_field_presence)
+      : has_bit_indices_(*has_bit_indices),
+        has_field_presence_(has_field_presence) {}
+
+  // Returns true if the following conditions are met:
+  // --both fields are repeated fields
+  // --both fields are non-repeated fields with either has_field_presence is
+  //   false or have the same has_byte index.
+  bool operator()(const FieldDescriptor* a, const FieldDescriptor* b) const {
+    return a->is_repeated() == b->is_repeated() &&
+           (!has_field_presence_ || a->is_repeated() ||
+            has_bit_indices_[a->index()] / 8 ==
+                has_bit_indices_[b->index()] / 8);
+  }
+
+ private:
+  const std::vector<int>& has_bit_indices_;
+  const bool has_field_presence_;
+};
+
+// Allows chunking required fields separately after chunking with
+// MatchRepeatedAndHasByte.
+class MatchRepeatedAndHasByteAndRequired : public MatchRepeatedAndHasByte {
+ public:
+  MatchRepeatedAndHasByteAndRequired(const std::vector<int>* has_bit_indices,
+                                     bool has_field_presence)
+      : MatchRepeatedAndHasByte(has_bit_indices, has_field_presence) {}
+
+  bool operator()(const FieldDescriptor* a, const FieldDescriptor* b) const {
+    return MatchRepeatedAndHasByte::operator()(a, b) &&
+           a->is_required() == b->is_required();
+  }
+};
+
+// Allows chunking zero-initializable fields separately after chunking with
+// MatchRepeatedAndHasByte.
+class MatchRepeatedAndHasByteAndZeroInits : public MatchRepeatedAndHasByte {
+ public:
+  MatchRepeatedAndHasByteAndZeroInits(const std::vector<int>* has_bit_indices,
+                                      bool has_field_presence)
+      : MatchRepeatedAndHasByte(has_bit_indices, has_field_presence) {}
+
+  bool operator()(const FieldDescriptor* a, const FieldDescriptor* b) const {
+    return MatchRepeatedAndHasByte::operator()(a, b) &&
+           CanInitializeByZeroing(a) == CanInitializeByZeroing(b);
+  }
+};
+
+// Collects neighboring fields based on a given criteria (equivalent predicate).
+template <typename Predicate>
+std::vector<std::vector<const FieldDescriptor*> > CollectFields(
+    const std::vector<const FieldDescriptor*>& fields,
+    const Predicate& equivalent) {
+  std::vector<std::vector<const FieldDescriptor*> > chunks;
+  if (fields.empty()) {
+    return chunks;
+  }
+
+  const FieldDescriptor* last_field = fields.front();
+  std::vector<const FieldDescriptor*> chunk;
+  for (int i = 0; i < fields.size(); i++) {
+    if (!equivalent(last_field, fields[i]) && !chunk.empty()) {
+      chunks.push_back(chunk);
+      chunk.clear();
+    }
+    chunk.push_back(fields[i]);
+    last_field = fields[i];
+  }
+  if (!chunk.empty()) {
+    chunks.push_back(chunk);
+  }
+  return chunks;
+}
+
+// Returns a bit mask based on has_bit index of "fields" that are typically on
+// the same chunk. It is used in a group presence check where _has_bits_ is
+// masked to tell if any thing in "fields" is present.
+uint32 GenChunkMask(const std::vector<const FieldDescriptor*>& fields,
+                    const std::vector<int>& has_bit_indices) {
+  GOOGLE_CHECK(!fields.empty());
+  int first_index_offset = has_bit_indices[fields.front()->index()] / 32;
+  uint32 chunk_mask = 0;
+  for (int i = 0; i < fields.size(); i++) {
+    const FieldDescriptor* field = fields[i];
+    // "index" defines where in the _has_bits_ the field appears.
+    int index = has_bit_indices[field->index()];
+    GOOGLE_CHECK_EQ(first_index_offset, index / 32);
+    chunk_mask |= static_cast<uint32>(1) << (index % 32);
+  }
+  GOOGLE_CHECK_NE(0, chunk_mask);
+  return chunk_mask;
+}
+
 }  // anonymous namespace
 
 // ===================================================================
 
 MessageGenerator::MessageGenerator(const Descriptor* descriptor,
-                                   const Options& options)
+                                   int index_in_file_messages,
+                                   const Options& options,
+                                   SCCAnalyzer* scc_analyzer)
     : descriptor_(descriptor),
+      index_in_file_messages_(index_in_file_messages),
       classname_(ClassName(descriptor, false)),
       options_(options),
-      field_generators_(descriptor, options),
-      nested_generators_(new google::protobuf::scoped_ptr<
-          MessageGenerator>[descriptor->nested_type_count()]),
+      field_generators_(descriptor, options, scc_analyzer),
+      max_has_bit_index_(0),
       enum_generators_(
-          new google::protobuf::scoped_ptr<EnumGenerator>[descriptor->enum_type_count()]),
-      extension_generators_(new google::protobuf::scoped_ptr<
-          ExtensionGenerator>[descriptor->extension_count()]),
-      use_dependent_base_(false) {
+          new std::unique_ptr<EnumGenerator>[descriptor->enum_type_count()]),
+      extension_generators_(new std::unique_ptr<
+                            ExtensionGenerator>[descriptor->extension_count()]),
+      num_weak_fields_(0),
+      message_layout_helper_(new PaddingOptimizer()),
+      scc_analyzer_(scc_analyzer) {
+  // Compute optimized field order to be used for layout and initialization
+  // purposes.
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (field->options().weak()) {
+      num_weak_fields_++;
+    } else if (!field->containing_oneof()) {
+      optimized_order_.push_back(field);
+    }
+  }
 
-  for (int i = 0; i < descriptor->nested_type_count(); i++) {
-    nested_generators_[i].reset(
-      new MessageGenerator(descriptor->nested_type(i), options));
+  message_layout_helper_->OptimizeLayout(&optimized_order_, options_);
+
+  if (HasFieldPresence(descriptor_->file())) {
+    // We use -1 as a sentinel.
+    has_bit_indices_.resize(descriptor_->field_count(), -1);
+    for (int i = 0; i < optimized_order_.size(); i++) {
+      const FieldDescriptor* field = optimized_order_[i];
+      // Skip fields that do not have has bits.
+      if (field->is_repeated()) {
+        continue;
+      }
+
+      has_bit_indices_[field->index()] = max_has_bit_index_++;
+    }
   }
 
   for (int i = 0; i < descriptor->enum_type_count(); i++) {
@@ -410,127 +489,96 @@
     if (descriptor->field(i)->is_required()) {
       ++num_required_fields_;
     }
-    if (options.proto_h && IsFieldDependent(descriptor->field(i))) {
-      use_dependent_base_ = true;
-    }
   }
-  if (options.proto_h && descriptor->oneof_decl_count() > 0) {
-    // Always make oneofs dependent.
-    use_dependent_base_ = true;
-  }
+
+  table_driven_ = TableDrivenParsingEnabled(descriptor_, options_);
+
+  scc_name_ =
+      ClassName(scc_analyzer_->GetSCC(descriptor_)->GetRepresentative(), false);
 }
 
 MessageGenerator::~MessageGenerator() {}
 
-void MessageGenerator::
-FillMessageForwardDeclarations(set<string>* class_names) {
-  class_names->insert(classname_);
-
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    // map entry message doesn't need forward declaration. Since map entry
-    // message cannot be a top level class, we just need to avoid calling
-    // GenerateForwardDeclaration here.
-    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
-    nested_generators_[i]->FillMessageForwardDeclarations(class_names);
+size_t MessageGenerator::HasBitsSize() const {
+  size_t sizeof_has_bits = (max_has_bit_index_ + 31) / 32 * 4;
+  if (sizeof_has_bits == 0) {
+    // 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.
+    sizeof_has_bits = 4;
   }
+
+  return sizeof_has_bits;
 }
 
-void MessageGenerator::
-FillEnumForwardDeclarations(set<string>* enum_names) {
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    nested_generators_[i]->FillEnumForwardDeclarations(enum_names);
-  }
+void MessageGenerator::AddGenerators(
+    std::vector<EnumGenerator*>* enum_generators,
+    std::vector<ExtensionGenerator*>* extension_generators) {
   for (int i = 0; i < descriptor_->enum_type_count(); i++) {
-    enum_generators_[i]->FillForwardDeclaration(enum_names);
+    enum_generators->push_back(enum_generators_[i].get());
+  }
+  for (int i = 0; i < descriptor_->extension_count(); i++) {
+    extension_generators->push_back(extension_generators_[i].get());
   }
 }
 
-void MessageGenerator::
-GenerateEnumDefinitions(io::Printer* printer) {
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    nested_generators_[i]->GenerateEnumDefinitions(printer);
-  }
-
-  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
-    enum_generators_[i]->GenerateDefinition(printer);
-  }
-}
-
-void MessageGenerator::
-GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    nested_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
-  }
-  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
-    enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
-  }
-}
-
-void MessageGenerator::
-GenerateDependentFieldAccessorDeclarations(io::Printer* printer) {
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = descriptor_->field(i);
-
-    PrintFieldComment(printer, field);
-
-    map<string, string> vars;
-    SetCommonFieldVariables(field, &vars, options_);
-
-    if (use_dependent_base_ && IsFieldDependent(field)) {
-      // If the message is dependent, the inline clear_*() method will need
-      // to delete the message type, so it must be in the dependent base
-      // class. (See also GenerateFieldAccessorDeclarations.)
-      printer->Print(vars, "void clear_$name$()$deprecation$;\n");
-    }
-    // Generate type-specific accessor declarations.
-    field_generators_.get(field).GenerateDependentAccessorDeclarations(printer);
-    printer->Print("\n");
-  }
+void MessageGenerator::FillMessageForwardDeclarations(
+    std::map<string, const Descriptor*>* class_names) {
+  (*class_names)[classname_] = descriptor_;
 }
 
 void MessageGenerator::
 GenerateFieldAccessorDeclarations(io::Printer* printer) {
+  // optimized_fields_ does not contain fields where
+  //    field->containing_oneof() != NULL
+  // so we need to iterate over those as well.
+  //
+  // We place the non-oneof fields in optimized_order_, as that controls the
+  // order of the _has_bits_ entries and we want GDB's pretty printers to be
+  // able to infer these indices from the k[FIELDNAME]FieldNumber order.
+  std::vector<const FieldDescriptor*> ordered_fields;
+  ordered_fields.reserve(descriptor_->field_count());
+
+  ordered_fields.insert(
+      ordered_fields.begin(), optimized_order_.begin(), optimized_order_.end());
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
+    if (field->containing_oneof() == NULL && !field->options().weak()) {
+      continue;
+    }
+    ordered_fields.push_back(field);
+  }
+
+  for (int i = 0; i < ordered_fields.size(); i++) {
+    const FieldDescriptor* field = ordered_fields[i];
 
     PrintFieldComment(printer, field);
 
-    map<string, string> vars;
+    std::map<string, string> vars;
     SetCommonFieldVariables(field, &vars, options_);
     vars["constant_name"] = FieldConstantName(field);
 
-    bool dependent_field = use_dependent_base_ && IsFieldDependent(field);
-    if (dependent_field &&
-        field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
-        !field->is_map()) {
-      // If this field is dependent, the dependent base class determines
-      // the message type from the derived class (which is a template
-      // parameter). This typedef is for that:
-      printer->Print(
-          "private:\n"
-          "typedef $field_type$ $dependent_type$;\n"
-          "public:\n",
-          "field_type", FieldMessageTypeName(field),
-          "dependent_type", DependentTypeName(field));
-    }
-
     if (field->is_repeated()) {
-      printer->Print(vars, "int $name$_size() const$deprecation$;\n");
+      printer->Print(vars, "$deprecated_attr$int ${$$name$_size$}$() const;\n");
+      printer->Annotate("{", "}", field);
     } else if (HasHasMethod(field)) {
-      printer->Print(vars, "bool has_$name$() const$deprecation$;\n");
+      printer->Print(vars, "$deprecated_attr$bool ${$has_$name$$}$() const;\n");
+      printer->Annotate("{", "}", field);
     } else if (HasPrivateHasMethod(field)) {
       printer->Print(vars,
-          "private:\n"
-          "bool has_$name$() const$deprecation$;\n"
-          "public:\n");
+                     "private:\n"
+                     "bool ${$has_$name$$}$() const;\n"
+                     "public:\n");
+      printer->Annotate("{", "}", field);
     }
 
-    if (!dependent_field) {
-      // If this field is dependent, then its clear_() method is in the
-      // depenent base class. (See also GenerateDependentAccessorDeclarations.)
-      printer->Print(vars, "void clear_$name$()$deprecation$;\n");
-    }
-    printer->Print(vars, "static const int $constant_name$ = $number$;\n");
+    printer->Print(vars, "$deprecated_attr$void ${$clear_$name$$}$();\n");
+    printer->Annotate("{", "}", field);
+    printer->Print(vars,
+                   "$deprecated_attr$static const int $constant_name$ = "
+                   "$number$;\n");
+    printer->Annotate("constant_name", field);
 
     // Generate type-specific accessor declarations.
     field_generators_.get(field).GenerateAccessorDeclarations(printer);
@@ -548,6 +596,7 @@
 
   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
     printer->Print(
+        "void clear_$oneof_name$();\n"
         "$camel_oneof_name$Case $oneof_name$_case() const;\n",
         "camel_oneof_name",
         UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true),
@@ -556,80 +605,34 @@
 }
 
 void MessageGenerator::
-GenerateDependentFieldAccessorDefinitions(io::Printer* printer) {
-  if (!use_dependent_base_) return;
-
-  printer->Print("// $classname$\n\n", "classname",
-                 DependentBaseClassTemplateName(descriptor_));
-
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = descriptor_->field(i);
-
-    PrintFieldComment(printer, field);
-
-    // These functions are not really dependent: they are part of the
-    // (non-dependent) derived class. However, they need to live outside
-    // any #ifdef guards, so we treat them as if they were dependent.
-    //
-    // See the comment in FileGenerator::GenerateInlineFunctionDefinitions
-    // for a more complete explanation.
-    if (use_dependent_base_ && IsFieldDependent(field)) {
-      map<string, string> vars;
-      SetCommonFieldVariables(field, &vars, options_);
-      vars["inline"] = "inline ";
-      if (field->containing_oneof()) {
-        vars["field_name"] = UnderscoresToCamelCase(field->name(), true);
-        vars["oneof_name"] = field->containing_oneof()->name();
-        vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index());
-        GenerateOneofMemberHasBits(field, vars, printer);
-      } else if (!field->is_repeated()) {
-        // There will be no header guard, so this always has to be inline.
-        GenerateSingularFieldHasBits(field, vars, printer);
-      }
-      // vars needed for clear_(), which is in the dependent base:
-      // (See also GenerateDependentFieldAccessorDeclarations.)
-      vars["tmpl"] = "template<class T>\n";
-      vars["dependent_classname"] =
-          DependentBaseClassTemplateName(descriptor_) + "<T>";
-      vars["this_message"] = DependentBaseDownCast();
-      vars["this_const_message"] = DependentBaseConstDownCast();
-      GenerateFieldClear(field, vars, printer);
-    }
-
-    // Generate type-specific accessors.
-    field_generators_.get(field)
-        .GenerateDependentInlineAccessorDefinitions(printer);
-
-    printer->Print("\n");
-  }
-
-  // Generate has_$name$() and clear_has_$name$() functions for oneofs
-  // Similar to other has-bits, these must always be in the header if we
-  // are using a dependent base class.
-  GenerateOneofHasBits(printer, true /* is_inline */);
-}
-
-void MessageGenerator::
 GenerateSingularFieldHasBits(const FieldDescriptor* field,
-                             map<string, string> vars,
+                             std::map<string, string> vars,
                              io::Printer* printer) {
+  if (field->options().weak()) {
+    printer->Print(
+        vars,
+        "inline bool $classname$::has_$name$() const {\n"
+        "  return _weak_field_map_.Has($number$);\n"
+        "}\n");
+    return;
+  }
   if (HasFieldPresence(descriptor_->file())) {
     // N.B.: without field presence, we do not use has-bits or generate
     // has_$name$() methods.
-    vars["has_array_index"] = SimpleItoa(field->index() / 32);
-    vars["has_mask"] = StrCat(strings::Hex(1u << (field->index() % 32),
+    int has_bit_index = has_bit_indices_[field->index()];
+    GOOGLE_CHECK_GE(has_bit_index, 0);
+
+    vars["has_array_index"] = SimpleItoa(has_bit_index / 32);
+    vars["has_mask"] = StrCat(strings::Hex(1u << (has_bit_index % 32),
                                            strings::ZERO_PAD_8));
     printer->Print(vars,
-      "$inline$"
-      "bool $classname$::has_$name$() const {\n"
+      "inline bool $classname$::has_$name$() const {\n"
       "  return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n"
       "}\n"
-      "$inline$"
-      "void $classname$::set_has_$name$() {\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"
+      "inline void $classname$::clear_has_$name$() {\n"
       "  _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n"
       "}\n");
   } else {
@@ -638,39 +641,35 @@
       bool is_lazy = false;
       if (is_lazy) {
         printer->Print(vars,
-          "$inline$"
-          "bool $classname$::has_$name$() const {\n"
+          "inline bool $classname$::has_$name$() const {\n"
           "  return !$name$_.IsCleared();\n"
           "}\n");
       } else {
-        printer->Print(vars,
-          "$inline$"
-          "bool $classname$::has_$name$() const {\n"
-          "  return !_is_default_instance_ && $name$_ != NULL;\n"
-          "}\n");
+        printer->Print(
+            vars,
+            "inline bool $classname$::has_$name$() const {\n"
+            "  return this != internal_default_instance() && $name$_ != NULL;\n"
+            "}\n");
       }
     }
   }
 }
 
 void MessageGenerator::
-GenerateOneofHasBits(io::Printer* printer, bool is_inline) {
+GenerateOneofHasBits(io::Printer* printer) {
   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
-    map<string, string> vars;
+    std::map<string, string> vars;
     vars["oneof_name"] = descriptor_->oneof_decl(i)->name();
     vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
     vars["cap_oneof_name"] =
         ToUpper(descriptor_->oneof_decl(i)->name());
     vars["classname"] = classname_;
-    vars["inline"] = (is_inline ? "inline " : "");
     printer->Print(
         vars,
-        "$inline$"
-        "bool $classname$::has_$oneof_name$() const {\n"
+        "inline bool $classname$::has_$oneof_name$() const {\n"
         "  return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n"
         "}\n"
-        "$inline$"
-        "void $classname$::clear_has_$oneof_name$() {\n"
+        "inline void $classname$::clear_has_$oneof_name$() {\n"
         "  _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n"
         "}\n");
   }
@@ -678,7 +677,7 @@
 
 void MessageGenerator::
 GenerateOneofMemberHasBits(const FieldDescriptor* field,
-                           const map<string, string>& vars,
+                           const std::map<string, string>& vars,
                            io::Printer* printer) {
   // Singular field in a oneof
   // N.B.: Without field presence, we do not use has-bits or generate
@@ -687,28 +686,26 @@
   // method, so that generated code is slightly cleaner (vs.  comparing
   // _oneof_case_[index] against a constant everywhere).
   printer->Print(vars,
-    "$inline$"
-    "bool $classname$::has_$name$() const {\n"
+    "inline bool $classname$::has_$name$() const {\n"
     "  return $oneof_name$_case() == k$field_name$;\n"
     "}\n");
   printer->Print(vars,
-    "$inline$"
-    "void $classname$::set_has_$name$() {\n"
+    "inline void $classname$::set_has_$name$() {\n"
     "  _oneof_case_[$oneof_index$] = k$field_name$;\n"
     "}\n");
 }
 
 void MessageGenerator::
 GenerateFieldClear(const FieldDescriptor* field,
-                   const map<string, string>& vars,
+                   const std::map<string, string>& vars,
+                   bool is_inline,
                    io::Printer* printer) {
-  // Generate clear_$name$() (See GenerateFieldAccessorDeclarations and
-  // GenerateDependentFieldAccessorDeclarations, $dependent_classname$ is
-  // set by the Generate*Definitions functions.)
+  // Generate clear_$name$().
+  if (is_inline) {
+    printer->Print("inline ");
+  }
   printer->Print(vars,
-    "$tmpl$"
-    "$inline$"
-    "void $dependent_classname$::clear_$name$() {\n");
+    "void $classname$::clear_$name$() {\n");
 
   printer->Indent();
 
@@ -716,21 +713,20 @@
     // Clear this field only if it is the active field in this oneof,
     // otherwise ignore
     printer->Print(vars,
-      "if ($this_message$has_$name$()) {\n");
+      "if (has_$name$()) {\n");
     printer->Indent();
     field_generators_.get(field)
         .GenerateClearingCode(printer);
     printer->Print(vars,
-      "$this_message$clear_has_$oneof_name$();\n");
+      "clear_has_$oneof_name$();\n");
     printer->Outdent();
     printer->Print("}\n");
   } else {
     field_generators_.get(field)
         .GenerateClearingCode(printer);
     if (HasFieldPresence(descriptor_->file())) {
-      if (!field->is_repeated()) {
-        printer->Print(vars,
-                       "$this_message$clear_has_$name$();\n");
+      if (!field->is_repeated() && !field->options().weak()) {
+        printer->Print(vars, "clear_has_$name$();\n");
       }
     }
   }
@@ -740,7 +736,7 @@
 }
 
 void MessageGenerator::
-GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) {
+GenerateFieldAccessorDefinitions(io::Printer* printer) {
   printer->Print("// $classname$\n\n", "classname", classname_);
 
   for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -748,135 +744,81 @@
 
     PrintFieldComment(printer, field);
 
-    map<string, string> vars;
+    std::map<string, string> vars;
     SetCommonFieldVariables(field, &vars, options_);
-    vars["inline"] = is_inline ? "inline " : "";
-    if (use_dependent_base_ && IsFieldDependent(field)) {
-      vars["tmpl"] = "template<class T>\n";
-      vars["dependent_classname"] =
-          DependentBaseClassTemplateName(descriptor_) + "<T>";
-      vars["this_message"] = "reinterpret_cast<T*>(this)->";
-      vars["this_const_message"] = "reinterpret_cast<const T*>(this)->";
-    } else {
-      vars["tmpl"] = "";
-      vars["dependent_classname"] = vars["classname"];
-      vars["this_message"] = "";
-      vars["this_const_message"] = "";
-    }
 
     // Generate has_$name$() or $name$_size().
     if (field->is_repeated()) {
       printer->Print(vars,
-        "$inline$"
-        "int $classname$::$name$_size() const {\n"
+        "inline int $classname$::$name$_size() const {\n"
         "  return $name$_.size();\n"
         "}\n");
     } else if (field->containing_oneof()) {
       vars["field_name"] = UnderscoresToCamelCase(field->name(), true);
       vars["oneof_name"] = field->containing_oneof()->name();
       vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index());
-      if (!use_dependent_base_ || !IsFieldDependent(field)) {
-        GenerateOneofMemberHasBits(field, vars, printer);
-      }
+      GenerateOneofMemberHasBits(field, vars, printer);
     } else {
       // Singular field.
-      if (!use_dependent_base_ || !IsFieldDependent(field)) {
-        GenerateSingularFieldHasBits(field, vars, printer);
-      }
+      GenerateSingularFieldHasBits(field, vars, printer);
     }
 
-    if (!use_dependent_base_ || !IsFieldDependent(field)) {
-      GenerateFieldClear(field, vars, printer);
+    if (!IsCrossFileMaybeMap(field)) {
+      GenerateFieldClear(field, vars, true, printer);
     }
 
     // Generate type-specific accessors.
-    field_generators_.get(field).GenerateInlineAccessorDefinitions(printer,
-                                                                   is_inline);
+    field_generators_.get(field).GenerateInlineAccessorDefinitions(printer);
 
     printer->Print("\n");
   }
 
-  if (!use_dependent_base_) {
-    // Generate has_$name$() and clear_has_$name$() functions for oneofs
-    // If we aren't using a dependent base, they can be with the other functions
-    // that are #ifdef-guarded.
-    GenerateOneofHasBits(printer, is_inline);
-  }
-}
-
-// Helper for the code that emits the Clear() method.
-static bool CanClearByZeroing(const FieldDescriptor* field) {
-  if (field->is_repeated() || field->is_extension()) return false;
-  switch (field->cpp_type()) {
-    case internal::WireFormatLite::CPPTYPE_ENUM:
-      return field->default_value_enum()->number() == 0;
-    case internal::WireFormatLite::CPPTYPE_INT32:
-      return field->default_value_int32() == 0;
-    case internal::WireFormatLite::CPPTYPE_INT64:
-      return field->default_value_int64() == 0;
-    case internal::WireFormatLite::CPPTYPE_UINT32:
-      return field->default_value_uint32() == 0;
-    case internal::WireFormatLite::CPPTYPE_UINT64:
-      return field->default_value_uint64() == 0;
-    case internal::WireFormatLite::CPPTYPE_FLOAT:
-      return field->default_value_float() == 0;
-    case internal::WireFormatLite::CPPTYPE_DOUBLE:
-      return field->default_value_double() == 0;
-    case internal::WireFormatLite::CPPTYPE_BOOL:
-      return field->default_value_bool() == false;
-    default:
-      return false;
-  }
-}
-
-void MessageGenerator::
-GenerateDependentBaseClassDefinition(io::Printer* printer) {
-  if (!use_dependent_base_) {
-    return;
-  }
-
-  map<string, string> vars;
-  vars["classname"] = DependentBaseClassTemplateName(descriptor_);
-  vars["superclass"] = SuperClassName(descriptor_);
-
-  printer->Print(vars,
-    "template <class T>\n"
-    "class $classname$ : public $superclass$ {\n"
-    " public:\n");
-  printer->Indent();
-
-  printer->Print(vars,
-    "$classname$() {}\n"
-    "virtual ~$classname$() {}\n"
-    "\n");
-
-  // Generate dependent accessor methods for all fields.
-  GenerateDependentFieldAccessorDeclarations(printer);
-
-  printer->Outdent();
-  printer->Print("};\n");
+  // Generate has_$name$() and clear_has_$name$() functions for oneofs.
+  GenerateOneofHasBits(printer);
 }
 
 void MessageGenerator::
 GenerateClassDefinition(io::Printer* printer) {
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    // map entry message doesn't need class definition. Since map entry message
-    // cannot be a top level class, we just need to avoid calling
-    // GenerateClassDefinition here.
-    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
-    nested_generators_[i]->GenerateClassDefinition(printer);
-    printer->Print("\n");
-    printer->Print(kThinSeparator);
-    printer->Print("\n");
+  if (IsMapEntryMessage(descriptor_)) {
+    std::map<string, string> vars;
+    vars["classname"] = classname_;
+    CollectMapInfo(descriptor_, &vars);
+    vars["lite"] =
+        HasDescriptorMethods(descriptor_->file(), options_) ? "" : "Lite";
+    printer->Print(
+        vars,
+        "class $classname$ : public "
+        "::google::protobuf::internal::MapEntry$lite$<$classname$, \n"
+        "    $key_cpp$, $val_cpp$,\n"
+        "    $key_wire_type$,\n"
+        "    $val_wire_type$,\n"
+        "    $default_enum_value$ > {\n"
+        "public:\n"
+        "  typedef ::google::protobuf::internal::MapEntry$lite$<$classname$, \n"
+        "    $key_cpp$, $val_cpp$,\n"
+        "    $key_wire_type$,\n"
+        "    $val_wire_type$,\n"
+        "    $default_enum_value$ > SuperType;\n"
+        "  $classname$();\n"
+        "  $classname$(::google::protobuf::Arena* arena);\n"
+        "  void MergeFrom(const $classname$& other);\n"
+        "  static const $classname$* internal_default_instance() { return "
+        "reinterpret_cast<const "
+        "$classname$*>(&_$classname$_default_instance_); }\n");
+    if (HasDescriptorMethods(descriptor_->file(), options_)) {
+      printer->Print(
+          "  void MergeFrom(const ::google::protobuf::Message& other) final;\n"
+          "  ::google::protobuf::Metadata GetMetadata() const;\n"
+          "};\n");
+    } else {
+      printer->Print("};\n");
+    }
+    return;
   }
 
-  if (use_dependent_base_) {
-    GenerateDependentBaseClassDefinition(printer);
-      printer->Print("\n");
-  }
-
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["classname"] = classname_;
+  vars["full_name"] = descriptor_->full_name();
   vars["field_count"] = SimpleItoa(descriptor_->field_count());
   vars["oneof_decl_count"] = SimpleItoa(descriptor_->oneof_decl_count());
   if (options_.dllexport_decl.empty()) {
@@ -884,71 +826,63 @@
   } else {
     vars["dllexport"] = options_.dllexport_decl + " ";
   }
-  if (use_dependent_base_) {
-    vars["superclass"] =
-        DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">";
-  } else {
-    vars["superclass"] = SuperClassName(descriptor_);
-  }
+  vars["superclass"] = SuperClassName(descriptor_, options_);
   printer->Print(vars,
-    "class $dllexport$$classname$ : public $superclass$ {\n");
-  if (use_dependent_base_) {
-    printer->Print(vars, "  friend class $superclass$;\n");
-  }
+    "class $dllexport$$classname$ : public $superclass$ "
+    "/* @@protoc_insertion_point(class_definition:$full_name$) */ "
+    "{\n");
+  printer->Annotate("classname", descriptor_);
   printer->Print(" public:\n");
   printer->Indent();
 
+  printer->Print(
+      vars,
+      "$classname$();\n"
+      "virtual ~$classname$();\n"
+      "\n"
+      "$classname$(const $classname$& from);\n"
+      "\n"
+      "inline $classname$& operator=(const $classname$& from) {\n"
+      "  CopyFrom(from);\n"
+      "  return *this;\n"
+      "}\n");
+
+  if (options_.table_driven_serialization) {
+    printer->Print(
+      "private:\n"
+      "const void* InternalGetTable() const;\n"
+      "public:\n"
+      "\n");
+  }
+
+  // Generate move constructor and move assignment operator.
   printer->Print(vars,
-    "$classname$();\n"
-    "virtual ~$classname$();\n"
+    "#if LANG_CXX11\n"
+    "$classname$($classname$&& from) noexcept\n"
+    "  : $classname$() {\n"
+    "  *this = ::std::move(from);\n"
+    "}\n"
     "\n"
-    "$classname$(const $classname$& from);\n"
-    "\n"
-    "inline $classname$& operator=(const $classname$& from) {\n"
-    "  CopyFrom(from);\n"
+    "inline $classname$& operator=($classname$&& from) noexcept {\n"
+    "  if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {\n"
+    "    if (this != &from) InternalSwap(&from);\n"
+    "  } else {\n"
+    "    CopyFrom(from);\n"
+    "  }\n"
     "  return *this;\n"
     "}\n"
-    "\n");
+    "#endif\n");
 
-  if (PreserveUnknownFields(descriptor_)) {
-    if (UseUnknownFieldSet(descriptor_->file())) {
-      printer->Print(
-        "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n"
-        "  return _internal_metadata_.unknown_fields();\n"
+  SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+  if (PublicUnknownFieldsAccessors(descriptor_)) {
+    printer->Print(vars,
+        "inline const $unknown_fields_type$& unknown_fields() const {\n"
+        "  return $unknown_fields$;\n"
         "}\n"
-        "\n"
-        "inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\n"
-        "  return _internal_metadata_.mutable_unknown_fields();\n"
+        "inline $unknown_fields_type$* mutable_unknown_fields() {\n"
+        "  return $mutable_unknown_fields$;\n"
         "}\n"
         "\n");
-    } else {
-      if (SupportsArenas(descriptor_)) {
-        printer->Print(
-          "inline const ::std::string& unknown_fields() const {\n"
-          "  return _unknown_fields_.Get(\n"
-          "      &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"
-          "}\n"
-          "\n"
-          "inline ::std::string* mutable_unknown_fields() {\n"
-          "  return _unknown_fields_.Mutable(\n"
-          "      &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n"
-          "      GetArenaNoVirtual());\n"
-          "}\n"
-          "\n");
-      } else {
-        printer->Print(
-          "inline const ::std::string& unknown_fields() const {\n"
-          "  return _unknown_fields_.GetNoArena(\n"
-          "      &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"
-          "}\n"
-          "\n"
-          "inline ::std::string* mutable_unknown_fields() {\n"
-          "  return _unknown_fields_.MutableNoArena(\n"
-          "      &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"
-          "}\n"
-          "\n");
-      }
-    }
   }
 
   // N.B.: We exclude GetArena() when arena support is disabled, falling back on
@@ -958,14 +892,16 @@
     // virtual method version of GetArenaNoVirtual(), required for generic dispatch given a
     // MessageLite* (e.g., in RepeatedField::AddAllocated()).
     printer->Print(
-        "inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }\n"
-        "inline void* GetMaybeArenaPointer() const {\n"
+        "inline ::google::protobuf::Arena* GetArena() const final {\n"
+        "  return GetArenaNoVirtual();\n"
+        "}\n"
+        "inline void* GetMaybeArenaPointer() const final {\n"
         "  return MaybeArenaPtr();\n"
         "}\n");
   }
 
   // Only generate this member if it's not disabled.
-  if (HasDescriptorMethods(descriptor_->file()) &&
+  if (HasDescriptorMethods(descriptor_->file(), options_) &&
       !descriptor_->options().no_standard_descriptor_accessor()) {
     printer->Print(vars,
       "static const ::google::protobuf::Descriptor* descriptor();\n");
@@ -1002,20 +938,18 @@
         "\n");
   }
 
-  if (!StaticInitializersForced(descriptor_->file())) {
-    printer->Print(vars,
-      "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n"
-      "// Returns the internal default instance pointer. This function can\n"
-      "// return NULL thus should not be used by the user. This is intended\n"
-      "// for Protobuf internal code. Please use default_instance() declared\n"
-      "// above instead.\n"
+  // TODO(gerbens) make this private, while still granting other protos access.
+  vars["message_index"] = SimpleItoa(index_in_file_messages_);
+  printer->Print(
+      vars,
+      "static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY\n"
       "static inline const $classname$* internal_default_instance() {\n"
-      "  return default_instance_;\n"
+      "  return reinterpret_cast<const $classname$*>(\n"
+      "             &_$classname$_default_instance_);\n"
       "}\n"
-      "#endif\n"
+      "static constexpr int kIndexInFileMessages =\n"
+      "  $message_index$;\n"
       "\n");
-  }
-
 
   if (SupportsArenas(descriptor_)) {
     printer->Print(vars,
@@ -1027,94 +961,99 @@
       "// implements Any -----------------------------------------------\n"
       "\n"
       "void PackFrom(const ::google::protobuf::Message& message);\n"
+      "void PackFrom(const ::google::protobuf::Message& message,\n"
+      "              const ::std::string& type_url_prefix);\n"
       "bool UnpackTo(::google::protobuf::Message* message) const;\n"
       "template<typename T> bool Is() const {\n"
       "  return _any_metadata_.Is<T>();\n"
       "}\n"
+      "static bool ParseAnyTypeUrl(const string& type_url,\n"
+      "                            string* full_type_name);\n"
       "\n");
   }
 
+  vars["new_final"] = " final";
+
   printer->Print(vars,
     "void Swap($classname$* other);\n"
+    "friend void swap($classname$& a, $classname$& b) {\n"
+    "  a.Swap(&b);\n"
+    "}\n"
     "\n"
     "// implements Message ----------------------------------------------\n"
     "\n"
-    "inline $classname$* New() const { return New(NULL); }\n"
+    "inline $classname$* New() const$new_final$ {\n"
+    "  return CreateMaybeMessage<$classname$>(NULL);\n"
+    "}\n"
     "\n"
-    "$classname$* New(::google::protobuf::Arena* arena) const;\n");
+    "$classname$* New(::google::protobuf::Arena* arena) const$new_final$ {\n"
+    "  return CreateMaybeMessage<$classname$>(arena);\n"
+    "}\n");
 
-  if (HasGeneratedMethods(descriptor_->file())) {
-    if (HasDescriptorMethods(descriptor_->file())) {
+  // For instances that derive from Message (rather than MessageLite), some
+  // methods are virtual and should be marked as final.
+  string use_final = HasDescriptorMethods(descriptor_->file(), options_) ?
+      " final" : "";
+
+  if (HasGeneratedMethods(descriptor_->file(), options_)) {
+    if (HasDescriptorMethods(descriptor_->file(), options_)) {
       printer->Print(vars,
-        "void CopyFrom(const ::google::protobuf::Message& from);\n"
-        "void MergeFrom(const ::google::protobuf::Message& from);\n");
+        "void CopyFrom(const ::google::protobuf::Message& from) final;\n"
+        "void MergeFrom(const ::google::protobuf::Message& from) final;\n");
     } else {
       printer->Print(vars,
-        "void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);\n");
+        "void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from)\n"
+        "  final;\n");
     }
 
-    printer->Print(vars,
-      "void CopyFrom(const $classname$& from);\n"
-      "void MergeFrom(const $classname$& from);\n"
-      "void Clear();\n"
-      "bool IsInitialized() const;\n"
-      "\n"
-      "int ByteSize() const;\n"
-      "bool MergePartialFromCodedStream(\n"
-      "    ::google::protobuf::io::CodedInputStream* input);\n"
-      "void SerializeWithCachedSizes(\n"
-      "    ::google::protobuf::io::CodedOutputStream* output) const;\n");
+    vars["clear_final"] = " final";
+    vars["is_initialized_final"] = " final";
+    vars["merge_partial_final"] = " final";
+
+    printer->Print(
+        vars,
+        "void CopyFrom(const $classname$& from);\n"
+        "void MergeFrom(const $classname$& from);\n"
+        "void Clear()$clear_final$;\n"
+        "bool IsInitialized() const$is_initialized_final$;\n"
+        "\n"
+        "size_t ByteSizeLong() const final;\n"
+        "bool MergePartialFromCodedStream(\n"
+        "    ::google::protobuf::io::CodedInputStream* input)$merge_partial_final$;\n");
+    if (!options_.table_driven_serialization ||
+        descriptor_->options().message_set_wire_format()) {
+      printer->Print(
+          "void SerializeWithCachedSizes(\n"
+          "    ::google::protobuf::io::CodedOutputStream* output) const "
+          "final;\n");
+    }
     // DiscardUnknownFields() is implemented in message.cc using reflections. We
     // need to implement this function in generated code for messages.
-    if (!UseUnknownFieldSet(descriptor_->file())) {
+    if (!UseUnknownFieldSet(descriptor_->file(), options_)) {
       printer->Print(
-        "void DiscardUnknownFields();\n");
+        "void DiscardUnknownFields()$final$;\n",
+        "final", use_final);
     }
-    if (HasFastArraySerialization(descriptor_->file())) {
+    if (HasFastArraySerialization(descriptor_->file(), options_)) {
       printer->Print(
-        "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;\n");
-    }
-  }
-
-  // Check all FieldDescriptors including those in oneofs to estimate
-  // whether ::std::string is likely to be used, and depending on that
-  // estimate, set uses_string_ to true or false.  That contols
-  // whether to force initialization of empty_string_ in SharedCtor().
-  // It's often advantageous to do so to keep "is empty_string_
-  // inited?" code from appearing all over the place.
-  vector<const FieldDescriptor*> descriptors;
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    descriptors.push_back(descriptor_->field(i));
-  }
-  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
-    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
-      descriptors.push_back(descriptor_->oneof_decl(i)->field(j));
-    }
-  }
-  uses_string_ = false;
-  if (PreserveUnknownFields(descriptor_) &&
-      !UseUnknownFieldSet(descriptor_->file())) {
-    uses_string_ = true;
-  }
-  for (int i = 0; i < descriptors.size(); i++) {
-    const FieldDescriptor* field = descriptors[i];
-    if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
-      switch (field->options().ctype()) {
-        default: uses_string_ = true; break;
-      }
+        "::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(\n"
+        "    bool deterministic, ::google::protobuf::uint8* target) const final;\n");
     }
   }
 
   printer->Print(
-    "int GetCachedSize() const { return _cached_size_; }\n"
-    "private:\n"
-    "void SharedCtor();\n"
-    "void SharedDtor();\n"
-    "void SetCachedSize(int size) const;\n"
-    "void InternalSwap($classname$* other);\n",
-    "classname", classname_);
+      "int GetCachedSize() const final { return _cached_size_.Get(); }"
+      "\n\nprivate:\n"
+      "void SharedCtor();\n"
+      "void SharedDtor();\n"
+      "void SetCachedSize(int size) const$final$;\n"
+      "void InternalSwap($classname$* other);\n",
+      "classname", classname_, "final", use_final);
   if (SupportsArenas(descriptor_)) {
     printer->Print(
+      // TODO(gerbens) Make this private! Currently people are deriving from
+      // protos to give access to this constructor, breaking the invariants
+      // we rely on.
       "protected:\n"
       "explicit $classname$(::google::protobuf::Arena* arena);\n"
       "private:\n"
@@ -1123,7 +1062,7 @@
       "classname", classname_);
   }
 
-  if (UseUnknownFieldSet(descriptor_->file())) {
+  if (SupportsArenas(descriptor_)) {
     printer->Print(
       "private:\n"
       "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n"
@@ -1131,29 +1070,29 @@
       "}\n"
       "inline void* MaybeArenaPtr() const {\n"
       "  return _internal_metadata_.raw_arena_ptr();\n"
-      "}\n"
-      "public:\n"
-      "\n");
+      "}\n");
   } else {
     printer->Print(
       "private:\n"
       "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n"
-      "  return _arena_ptr_;\n"
+      "  return NULL;\n"
       "}\n"
-      "inline ::google::protobuf::Arena* MaybeArenaPtr() const {\n"
-      "  return _arena_ptr_;\n"
-      "}\n"
-      "public:\n"
-      "\n");
+      "inline void* MaybeArenaPtr() const {\n"
+      "  return NULL;\n"
+      "}\n");
   }
 
-  if (HasDescriptorMethods(descriptor_->file())) {
+  printer->Print(
+      "public:\n"
+      "\n");
+
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
     printer->Print(
-      "::google::protobuf::Metadata GetMetadata() const;\n"
+      "::google::protobuf::Metadata GetMetadata() const final;\n"
       "\n");
   } else {
     printer->Print(
-      "::std::string GetTypeName() const;\n"
+      "::std::string GetTypeName() const final;\n"
       "\n");
   }
 
@@ -1168,6 +1107,8 @@
       printer->Print("typedef $nested_full_name$ $nested_name$;\n",
                      "nested_name", nested_type->name(),
                      "nested_full_name", ClassName(nested_type, false));
+      printer->Annotate("nested_full_name", nested_type);
+      printer->Annotate("nested_name", nested_type);
     }
   }
 
@@ -1206,22 +1147,21 @@
 
 
   for (int i = 0; i < descriptor_->field_count(); i++) {
-    if (!descriptor_->field(i)->is_repeated()) {
+    if (!descriptor_->field(i)->is_repeated() &&
+        !descriptor_->field(i)->options().weak()) {
       // set_has_***() generated in all proto1/2 code and in oneofs (only) for
       // messages without true field presence.
       if (HasFieldPresence(descriptor_->file()) ||
           descriptor_->field(i)->containing_oneof()) {
-        printer->Print(
-          "inline void set_has_$name$();\n",
-          "name", FieldName(descriptor_->field(i)));
+        printer->Print("void set_has_$name$();\n", "name",
+                       FieldName(descriptor_->field(i)));
       }
       // clear_has_***() generated only for non-oneof fields
       // in proto1/2.
       if (!descriptor_->field(i)->containing_oneof() &&
           HasFieldPresence(descriptor_->file())) {
-        printer->Print(
-          "inline void clear_has_$name$();\n",
-          "name", FieldName(descriptor_->field(i)));
+        printer->Print("void clear_has_$name$();\n", "name",
+                       FieldName(descriptor_->field(i)));
       }
     }
   }
@@ -1231,17 +1171,16 @@
   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
     printer->Print(
         "inline bool has_$oneof_name$() const;\n"
-        "void clear_$oneof_name$();\n"
         "inline void clear_has_$oneof_name$();\n\n",
         "oneof_name", descriptor_->oneof_decl(i)->name());
   }
 
-  if (HasGeneratedMethods(descriptor_->file()) &&
+  if (HasGeneratedMethods(descriptor_->file(), options_) &&
       !descriptor_->options().message_set_wire_format() &&
       num_required_fields_ > 1) {
     printer->Print(
-        "// helper for ByteSize()\n"
-        "int RequiredFieldsByteSizeFallback() const;\n\n");
+        "// helper for ByteSizeLong()\n"
+        "size_t RequiredFieldsByteSizeFallback() const;\n\n");
   }
 
   // Prepare decls for _cached_size_ and _has_bits_.  Their position in the
@@ -1249,20 +1188,13 @@
 
   bool need_to_emit_cached_size = true;
   // TODO(kenton):  Make _cached_size_ an atomic<int> when C++ supports it.
-  const string cached_size_decl = "mutable int _cached_size_;\n";
+  const string cached_size_decl =
+      "mutable ::google::protobuf::internal::CachedSize _cached_size_;\n";
 
-  // TODO(jieluo) - Optimize _has_bits_ for repeated and oneof fields.
-  size_t sizeof_has_bits = (descriptor_->field_count() + 31) / 32 * 4;
-  if (descriptor_->field_count() == 0) {
-    // 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.
-    sizeof_has_bits = 4;
-  }
+  const size_t sizeof_has_bits = HasBitsSize();
   const string has_bits_decl = sizeof_has_bits == 0 ? "" :
-      "::google::protobuf::uint32 _has_bits_[" + SimpleItoa(sizeof_has_bits / 4) + "];\n";
-
+      "::google::protobuf::internal::HasBits<" + SimpleItoa(sizeof_has_bits / 4) +
+      "> _has_bits_;\n";
 
   // To minimize padding, data members are divided into three sections:
   // (1) members assumed to align to 8 bytes
@@ -1278,19 +1210,18 @@
       "\n");
   }
 
-  if (UseUnknownFieldSet(descriptor_->file())) {
+  if (UseUnknownFieldSet(descriptor_->file(), options_)) {
     printer->Print(
       "::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;\n");
   } else {
     printer->Print(
-      "::google::protobuf::internal::ArenaStringPtr _unknown_fields_;\n"
-      "::google::protobuf::Arena* _arena_ptr_;\n"
-      "\n");
+        "::google::protobuf::internal::InternalMetadataWithArenaLite "
+        "_internal_metadata_;\n");
   }
 
   if (SupportsArenas(descriptor_)) {
     printer->Print(
-      "friend class ::google::protobuf::Arena;\n"
+      "template <typename T> friend class ::google::protobuf::Arena::InternalHelper;\n"
       "typedef void InternalArenaConstructable_;\n"
       "typedef void DestructorSkippable_;\n");
   }
@@ -1306,55 +1237,16 @@
       printer->Print(cached_size_decl.c_str());
       need_to_emit_cached_size = false;
     }
-  } else {
-    // Without field presence, we need another way to disambiguate the default
-    // instance, because the default instance's submessage fields (if any) store
-    // pointers to the default instances of the submessages even when they
-    // aren't present. Alternatives to this approach might be to (i) use a
-    // tagged pointer on all message fields, setting a tag bit for "not really
-    // present, just default instance"; or (ii) comparing |this| against the
-    // return value from GeneratedMessageFactory::GetPrototype() in all
-    // has_$field$() calls. However, both of these options are much more
-    // expensive (in code size and CPU overhead) than just checking a field in
-    // the message. Long-term, the best solution would be to rearchitect the
-    // default instance design not to store pointers to submessage default
-    // instances, and have reflection get those some other way; but that change
-    // would have too much impact on proto2.
-    printer->Print(
-      "bool _is_default_instance_;\n");
   }
 
   // Field members:
 
-  // List fields which doesn't belong to any oneof
-  vector<const FieldDescriptor*> fields;
-  hash_map<string, int> fieldname_to_chunk;
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    if (!descriptor_->field(i)->containing_oneof()) {
-      const FieldDescriptor* field = descriptor_->field(i);
-      fields.push_back(field);
-      fieldname_to_chunk[FieldName(field)] = i / 8;
-    }
-  }
-  OptimizePadding(&fields);
   // Emit some private and static members
-  runs_of_fields_ = vector< vector<string> >(1);
-  for (int i = 0; i < fields.size(); ++i) {
-    const FieldDescriptor* field = fields[i];
+  for (int i = 0; i < optimized_order_.size(); ++i) {
+    const FieldDescriptor* field = optimized_order_[i];
     const FieldGenerator& generator = field_generators_.get(field);
     generator.GenerateStaticMembers(printer);
     generator.GeneratePrivateMembers(printer);
-    if (CanClearByZeroing(field)) {
-      const string& fieldname = FieldName(field);
-      if (!runs_of_fields_.back().empty() &&
-          (fieldname_to_chunk[runs_of_fields_.back().back()] !=
-           fieldname_to_chunk[fieldname])) {
-        runs_of_fields_.push_back(vector<string>());
-      }
-      runs_of_fields_.back().push_back(fieldname);
-    } else if (!runs_of_fields_.back().empty()) {
-      runs_of_fields_.push_back(vector<string>());
-    }
   }
 
   // For each oneof generate a union
@@ -1395,86 +1287,44 @@
       "\n");
   }
 
+  if (num_weak_fields_) {
+    printer->Print(
+        "::google::protobuf::internal::WeakFieldMap _weak_field_map_;\n");
+  }
   // Generate _any_metadata_ for the Any type.
   if (IsAnyMessage(descriptor_)) {
     printer->Print(vars,
       "::google::protobuf::internal::AnyMetadata _any_metadata_;\n");
   }
 
-  // Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as
-  // friends so that they can access private static variables like
-  // default_instance_ and reflection_.
-  PrintHandlingOptionalStaticInitializers(
-    descriptor_->file(), printer,
-    // With static initializers.
-    "friend void $dllexport_decl$ $adddescriptorsname$();\n",
-    // Without.
-    "friend void $dllexport_decl$ $adddescriptorsname$_impl();\n",
-    // Vars.
-    "dllexport_decl", options_.dllexport_decl,
-    "adddescriptorsname",
-    GlobalAddDescriptorsName(descriptor_->file()->name()));
-
-  printer->Print(
-    "friend void $assigndescriptorsname$();\n"
-    "friend void $shutdownfilename$();\n"
-    "\n",
-    "assigndescriptorsname",
-      GlobalAssignDescriptorsName(descriptor_->file()->name()),
-    "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name()));
-
-  printer->Print(
-    "void InitAsDefaultInstance();\n"
-    "static $classname$* default_instance_;\n",
-    "classname", classname_);
+  // The TableStruct struct needs access to the private parts, in order to
+  // construct the offsets of all members.
+  printer->Print("friend struct ::$file_namespace$::TableStruct;\n",
+                 // Vars.
+                 "scc_name", scc_name_, "file_namespace",
+                 FileLevelNamespace(descriptor_));
 
   printer->Outdent();
-  printer->Print(vars, "};");
+  printer->Print("};");
   GOOGLE_DCHECK(!need_to_emit_cached_size);
 }
 
 void MessageGenerator::
-GenerateDependentInlineMethods(io::Printer* printer) {
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    // map entry message doesn't need inline methods. Since map entry message
-    // cannot be a top level class, we just need to avoid calling
-    // GenerateInlineMethods here.
-    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
-    nested_generators_[i]->GenerateDependentInlineMethods(printer);
-    printer->Print(kThinSeparator);
-    printer->Print("\n");
-  }
-
-  GenerateDependentFieldAccessorDefinitions(printer);
-}
-
-void MessageGenerator::
-GenerateInlineMethods(io::Printer* printer, bool is_inline) {
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    // map entry message doesn't need inline methods. Since map entry message
-    // cannot be a top level class, we just need to avoid calling
-    // GenerateInlineMethods here.
-    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
-    nested_generators_[i]->GenerateInlineMethods(printer, is_inline);
-    printer->Print(kThinSeparator);
-    printer->Print("\n");
-  }
-
-  GenerateFieldAccessorDefinitions(printer, is_inline);
+GenerateInlineMethods(io::Printer* printer) {
+  if (IsMapEntryMessage(descriptor_)) return;
+  GenerateFieldAccessorDefinitions(printer);
 
   // Generate oneof_case() functions.
   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
-    map<string, string> vars;
+    std::map<string, string> vars;
     vars["class_name"] = classname_;
     vars["camel_oneof_name"] = UnderscoresToCamelCase(
         descriptor_->oneof_decl(i)->name(), true);
     vars["oneof_name"] = descriptor_->oneof_decl(i)->name();
     vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
-    vars["inline"] = is_inline ? "inline " : "";
     printer->Print(
         vars,
-        "$inline$"
-        "$class_name$::$camel_oneof_name$Case $class_name$::"
+        "inline $class_name$::$camel_oneof_name$Case $class_name$::"
         "$oneof_name$_case() const {\n"
         "  return $class_name$::$camel_oneof_name$Case("
         "_oneof_case_[$oneof_index$]);\n"
@@ -1483,27 +1333,13 @@
 }
 
 void MessageGenerator::
-GenerateDescriptorDeclarations(io::Printer* printer) {
-  if (!IsMapEntryMessage(descriptor_)) {
-    printer->Print(
-      "const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n"
-      "const ::google::protobuf::internal::GeneratedMessageReflection*\n"
-      "  $name$_reflection_ = NULL;\n",
-      "name", classname_);
-  } else {
-    printer->Print(
-      "const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n",
-      "name", classname_);
-  }
-
-  // Generate oneof default instance for reflection usage.
-  if (descriptor_->oneof_decl_count() > 0) {
-    printer->Print("struct $name$OneofInstance {\n",
-                   "name", classname_);
+GenerateExtraDefaultFields(io::Printer* printer) {
+  // Generate oneof default instance and weak field instances for reflection
+  // usage.
+  if (descriptor_->oneof_decl_count() > 0 || num_weak_fields_ > 0) {
     for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
       for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
         const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
-        printer->Print("  ");
         if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
             (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
              EffectiveStringCType(field) != FieldOptions::STRING)) {
@@ -1512,309 +1348,465 @@
         field_generators_.get(field).GeneratePrivateMembers(printer);
       }
     }
-
-    printer->Print("}* $name$_default_oneof_instance_ = NULL;\n",
-                   "name", classname_);
-  }
-
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    nested_generators_[i]->GenerateDescriptorDeclarations(printer);
-  }
-
-  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
-    printer->Print(
-      "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
-      "name", ClassName(descriptor_->enum_type(i), false));
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      const FieldDescriptor* field = descriptor_->field(i);
+      if (field->options().weak()) {
+        printer->Print(
+            "  const ::google::protobuf::Message* $name$_;\n", "name", FieldName(field));
+      }
+    }
   }
 }
 
-void MessageGenerator::
-GenerateDescriptorInitializer(io::Printer* printer, int index) {
-  // TODO(kenton):  Passing the index to this method is redundant; just use
-  //   descriptor_->index() instead.
-  map<string, string> vars;
-  vars["classname"] = classname_;
-  vars["index"] = SimpleItoa(index);
-
-  // Obtain the descriptor from the parent's descriptor.
-  if (descriptor_->containing_type() == NULL) {
-    printer->Print(vars,
-      "$classname$_descriptor_ = file->message_type($index$);\n");
-  } else {
-    vars["parent"] = ClassName(descriptor_->containing_type(), false);
-    printer->Print(vars,
-      "$classname$_descriptor_ = "
-        "$parent$_descriptor_->nested_type($index$);\n");
+bool MessageGenerator::GenerateParseTable(io::Printer* printer, size_t offset,
+                                          size_t aux_offset) {
+  if (!table_driven_) {
+    printer->Print("{ NULL, NULL, 0, -1, -1, -1, -1, NULL, false },\n");
+    return false;
   }
 
-  if (IsMapEntryMessage(descriptor_)) return;
+  std::map<string, string> vars;
 
-  // Generate the offsets.
-  GenerateOffsets(printer);
+  vars["classname"] = ClassName(descriptor_);
+  vars["classtype"] = QualifiedClassName(descriptor_);
+  vars["offset"] = SimpleItoa(offset);
+  vars["aux_offset"] = SimpleItoa(aux_offset);
 
-  const bool pass_pool_and_factory = false;
-  vars["fn"] = pass_pool_and_factory ?
-      "new ::google::protobuf::internal::GeneratedMessageReflection" :
-      "::google::protobuf::internal::GeneratedMessageReflection"
-      "::NewGeneratedMessageReflection";
-  // Construct the reflection object.
+  int max_field_number = 0;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (max_field_number < field->number()) {
+      max_field_number = field->number();
+    }
+  }
+
+  vars["max_field_number"] = SimpleItoa(max_field_number);
+
+  printer->Print("{\n");
+  printer->Indent();
+
   printer->Print(vars,
-    "$classname$_reflection_ =\n"
-    "  $fn$(\n"
-    "    $classname$_descriptor_,\n"
-    "    $classname$::default_instance_,\n"
-    "    $classname$_offsets_,\n");
+      "TableStruct::entries + $offset$,\n"
+      "TableStruct::aux + $aux_offset$,\n"
+      "$max_field_number$,\n");
+
   if (!HasFieldPresence(descriptor_->file())) {
     // If we don't have field presence, then _has_bits_ does not exist.
-    printer->Print(vars,
-    "    -1,\n");
+    printer->Print(vars, "-1,\n");
   } else {
     printer->Print(vars,
-    "    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _has_bits_[0]),\n");
-  }
-
-  // Unknown field offset: either points to the unknown field set if embedded
-  // directly, or indicates that the unknown field set is stored as part of the
-  // internal metadata if not.
-  if (UseUnknownFieldSet(descriptor_->file())) {
-    printer->Print(vars,
-    "    -1,\n");
-  } else {
-    printer->Print(vars,
-    "    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
-      "$classname$, _unknown_fields_),\n");
-  }
-
-  if (descriptor_->extension_range_count() > 0) {
-    printer->Print(vars,
-      "    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
-        "$classname$, _extensions_),\n");
-  } else {
-    // No extensions.
-    printer->Print(vars,
-      "    -1,\n");
+                   "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n"
+                   "  $classtype$, _has_bits_),\n");
   }
 
   if (descriptor_->oneof_decl_count() > 0) {
     printer->Print(vars,
-    "    $classname$_default_oneof_instance_,\n"
-    "    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
-      "$classname$, _oneof_case_[0]),\n");
+                   "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n"
+                   "  $classtype$, _oneof_case_),\n");
+  } else {
+    printer->Print("-1,  // no _oneof_case_\n");
   }
 
-  if (pass_pool_and_factory) {
-    printer->Print(
-        "    ::google::protobuf::DescriptorPool::generated_pool(),\n");
-      printer->Print(vars,
-                     "    ::google::protobuf::MessageFactory::generated_factory(),\n");
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(vars,
+                   "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classtype$, "
+                   "_extensions_),\n");
+  } else {
+    printer->Print("-1,  // no _extensions_\n");
   }
 
+  // TODO(ckennelly): Consolidate this with the calculation for
+  // AuxillaryParseTableField.
+  vars["ns"] = Namespace(descriptor_);
+
   printer->Print(vars,
-    "    sizeof($classname$),\n");
+                 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n"
+                 "  $classtype$, _internal_metadata_),\n"
+                 "&$ns$::_$classname$_default_instance_,\n");
 
-  // Arena offset: either an offset to the metadata struct that contains the
-  // arena pointer and unknown field set (in a space-efficient way) if we use
-  // that implementation strategy, or an offset directly to the arena pointer if
-  // not (because e.g. we don't have an unknown field set).
-  if (UseUnknownFieldSet(descriptor_->file())) {
-    printer->Print(vars,
-    "    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
-    "$classname$, _internal_metadata_),\n");
+  if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+    printer->Print(vars, "true,\n");
   } else {
-    printer->Print(vars,
-    "    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
-    "$classname$, _arena_),\n");
+    printer->Print(vars, "false,\n");
   }
 
-  // is_default_instance_ offset.
-  if (HasFieldPresence(descriptor_->file())) {
-    printer->Print(vars,
-    "    -1);\n");
+  printer->Outdent();
+  printer->Print("},\n");
+  return true;
+}
+
+void MessageGenerator::GenerateSchema(io::Printer* printer, int offset,
+                                      int has_offset) {
+  std::map<string, string> vars;
+
+  vars["classname"] = QualifiedClassName(descriptor_);
+  vars["offset"] = SimpleItoa(offset);
+  vars["has_bits_offsets"] =
+      HasFieldPresence(descriptor_->file()) || IsMapEntryMessage(descriptor_)
+          ? SimpleItoa(offset + has_offset)
+          : "-1";
+
+  printer->Print(vars,
+                 "{ $offset$, $has_bits_offsets$, sizeof($classname$)},\n");
+}
+
+namespace {
+
+// TODO(gerbens) remove this after the next sync with GitHub code base.
+// Then the opensource testing has gained the functionality to compile
+// the CalcFieldNum given the symbols defined in generated-message-util.
+#ifdef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP
+// We need a clean version of CalcFieldNum that doesn't use new functionality
+// in the runtime, because this functionality is not yet in the opensource
+// runtime
+
+uint32 CalculateType(uint32 type, uint32 type_class) {
+  return (type - 1) + type_class * 20;
+}
+
+uint32 CalcFieldNum(const FieldGenerator&, const FieldDescriptor* field,
+                    const Options& options) {
+  bool is_a_map = IsMapEntryMessage(field->containing_type());
+  int type = field->type();
+  if (field->containing_oneof()) {
+    return CalculateType(type, 4);
+  }
+  if (field->is_packed()) {
+    return CalculateType(type, 3);
+  } else if (field->is_repeated()) {
+    return CalculateType(type, 2);
+  } else if (!HasFieldPresence(field->file()) &&
+             field->containing_oneof() == NULL && !is_a_map) {
+    return CalculateType(type, 1);
   } else {
-    printer->Print(vars,
-    "    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
-    "$classname$, _is_default_instance_));\n");
-  }
-
-  // Handle nested types.
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    nested_generators_[i]->GenerateDescriptorInitializer(printer, i);
-  }
-
-  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
-    enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
+    return CalculateType(type, 0);
   }
 }
 
-void MessageGenerator::
-GenerateTypeRegistrations(io::Printer* printer) {
-  // Register this message type with the message factory.
-  if (!IsMapEntryMessage(descriptor_)) {
-    printer->Print(
-      "::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n"
-      "    $classname$_descriptor_, &$classname$::default_instance());\n",
-      "classname", classname_);
+#else
+// We need to calculate for each field what function the table driven code
+// should use to serialize it. This returns the index in a lookup table.
+uint32 CalcFieldNum(const FieldGenerator& generator,
+                    const FieldDescriptor* field, const Options& options) {
+  bool is_a_map = IsMapEntryMessage(field->containing_type());
+  int type = field->type();
+  if (type == FieldDescriptor::TYPE_STRING ||
+      type == FieldDescriptor::TYPE_BYTES) {
+    if (generator.IsInlined()) {
+      type = internal::FieldMetadata::kInlinedType;
+    }
   }
-  else {
-    map<string, string> vars;
-    CollectMapInfo(descriptor_, &vars);
-    vars["classname"] = classname_;
+  if (field->containing_oneof()) {
+    return internal::FieldMetadata::CalculateType(
+        type, internal::FieldMetadata::kOneOf);
+  }
+  if (field->is_packed()) {
+    return internal::FieldMetadata::CalculateType(
+        type, internal::FieldMetadata::kPacked);
+  } else if (field->is_repeated()) {
+    return internal::FieldMetadata::CalculateType(
+        type, internal::FieldMetadata::kRepeated);
+  } else if (!HasFieldPresence(field->file()) &&
+             field->containing_oneof() == NULL && !is_a_map) {
+    return internal::FieldMetadata::CalculateType(
+        type, internal::FieldMetadata::kNoPresence);
+  } else {
+    return internal::FieldMetadata::CalculateType(
+        type, internal::FieldMetadata::kPresence);
+  }
+}
+#endif
 
-    const FieldDescriptor* val = descriptor_->FindFieldByName("value");
-    if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO2 &&
-        val->type() == FieldDescriptor::TYPE_ENUM) {
-      const EnumValueDescriptor* default_value = val->default_value_enum();
-      vars["default_enum_value"] = Int32ToString(default_value->number());
-    } else {
-      vars["default_enum_value"] = "0";
+int FindMessageIndexInFile(const Descriptor* descriptor) {
+  std::vector<const Descriptor*> flatten =
+      FlattenMessagesInFile(descriptor->file());
+  return std::find(flatten.begin(), flatten.end(), descriptor) -
+         flatten.begin();
+}
+
+}  // namespace
+
+int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) {
+  if (!options_.table_driven_serialization) {
+    return 0;
+  }
+
+  string full_classname = QualifiedClassName(descriptor_);
+
+  std::vector<const FieldDescriptor*> sorted = SortFieldsByNumber(descriptor_);
+  if (IsMapEntryMessage(descriptor_)) {
+    for (int i = 0; i < 2; i++) {
+      const FieldDescriptor* field = sorted[i];
+      const FieldGenerator& generator = field_generators_.get(field);
+
+      uint32 tag = internal::WireFormatLite::MakeTag(
+          field->number(), WireFormat::WireTypeForFieldType(field->type()));
+
+      std::map<string, string> vars;
+      vars["classname"] = QualifiedClassName(descriptor_);
+      vars["field_name"] = FieldName(field);
+      vars["tag"] = SimpleItoa(tag);
+      vars["hasbit"] = SimpleItoa(i);
+      vars["type"] = SimpleItoa(CalcFieldNum(generator, field, options_));
+      vars["ptr"] = "NULL";
+      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+        GOOGLE_CHECK(!IsMapEntryMessage(field->message_type()));
+        {
+          vars["ptr"] =
+              "::" + FileLevelNamespace(field->message_type()) +
+              "::TableStruct::serialization_table + " +
+              SimpleItoa(FindMessageIndexInFile(field->message_type()));
+        }
+      }
+      printer->Print(vars,
+                     "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
+                     "::google::protobuf::internal::MapEntryHelper<$classname$::"
+                     "SuperType>, $field_name$_), $tag$,"
+                     "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
+                     "::google::protobuf::internal::MapEntryHelper<$classname$::"
+                     "SuperType>, _has_bits_) * 8 + $hasbit$, $type$, "
+                     "$ptr$},\n");
+    }
+    return 2;
+  }
+  printer->Print(
+      "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, "
+      "_cached_size_), 0, 0, 0, NULL},\n",
+      "classname", full_classname);
+  std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
+  for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
+    sorted_extensions.push_back(descriptor_->extension_range(i));
+  }
+  std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+            ExtensionRangeSorter());
+  for (int i = 0, extension_idx = 0; /* no range */; i++) {
+    for (; extension_idx < sorted_extensions.size() &&
+           (i == sorted.size() ||
+            sorted_extensions[extension_idx]->start < sorted[i]->number());
+         extension_idx++) {
+      const Descriptor::ExtensionRange* range =
+          sorted_extensions[extension_idx];
+      printer->Print(
+          "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, "
+          "_extensions_), $start$, $end$, "
+          "::google::protobuf::internal::FieldMetadata::kSpecial, "
+          "reinterpret_cast<const "
+          "void*>(::google::protobuf::internal::ExtensionSerializer)},\n",
+          "classname", full_classname, "start", SimpleItoa(range->start), "end",
+          SimpleItoa(range->end));
+    }
+    if (i == sorted.size()) break;
+    const FieldDescriptor* field = sorted[i];
+
+    uint32 tag = internal::WireFormatLite::MakeTag(
+        field->number(), WireFormat::WireTypeForFieldType(field->type()));
+    if (field->is_packed()) {
+      tag = internal::WireFormatLite::MakeTag(
+          field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
     }
 
-    printer->Print(vars,
-      "::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n"
-      "      $classname$_descriptor_,\n"
-      "      ::google::protobuf::internal::MapEntry<\n"
-      "          $key$,\n"
-      "          $val$,\n"
-      "          $key_wire_type$,\n"
-      "          $val_wire_type$,\n"
-      "          $default_enum_value$>::CreateDefaultInstance(\n"
-      "              $classname$_descriptor_));\n");
-  }
+    string classfieldname = FieldName(field);
+    if (field->containing_oneof()) {
+      classfieldname = field->containing_oneof()->name();
+    }
+    std::map<string, string> vars;
+    vars["classname"] = full_classname;
+    vars["field_name"] = classfieldname;
+    vars["tag"] = SimpleItoa(tag);
+    vars["ptr"] = "NULL";
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      if (IsMapEntryMessage(field->message_type())) {
+        vars["idx"] = SimpleItoa(FindMessageIndexInFile(field->message_type()));
+        vars["fieldclassname"] = QualifiedClassName(field->message_type());
+        printer->Print(vars,
+                       "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($"
+                       "classname$, $field_name$_), $tag$, $idx$, "
+                       "::google::protobuf::internal::FieldMetadata::kSpecial, "
+                       "reinterpret_cast<const void*>(static_cast< "
+                       "::google::protobuf::internal::SpecialSerializer>("
+                       "::google::protobuf::internal::MapFieldSerializer< "
+                       "::google::protobuf::internal::MapEntryToMapField<"
+                       "$fieldclassname$>::MapFieldType, "
+                       "TableStruct::serialization_table>))},\n");
+        continue;
+      } else {
+        vars["ptr"] =
+            "::" + FileLevelNamespace(field->message_type()) +
+            "::TableStruct::serialization_table + " +
+            SimpleItoa(FindMessageIndexInFile(field->message_type()));
+      }
+    }
 
-  // Handle nested types.
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    nested_generators_[i]->GenerateTypeRegistrations(printer);
+    const FieldGenerator& generator = field_generators_.get(field);
+    vars["type"] = SimpleItoa(CalcFieldNum(generator, field, options_));
+
+
+    if (field->options().weak()) {
+      // TODO(gerbens) merge weak fields into ranges
+      printer->Print(vars,
+                     "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($"
+                     "classname$, _weak_field_map_), $tag$, $tag$, "
+                     "::google::protobuf::internal::FieldMetadata::kSpecial, "
+                     "reinterpret_cast<const "
+                     "void*>(::google::protobuf::internal::WeakFieldSerializer)},\n");
+    } else if (field->containing_oneof()) {
+      vars["oneofoffset"] =
+          SimpleItoa(sizeof(uint32) * field->containing_oneof()->index());
+      printer->Print(vars,
+                     "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($"
+                     "classname$, $field_name$_), $tag$, "
+                     "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($"
+                     "classname$, _oneof_case_) + $oneofoffset$, "
+                     "$type$, $ptr$},\n");
+    } else if (HasFieldPresence(descriptor_->file()) &&
+               has_bit_indices_[field->index()] != -1) {
+      vars["hasbitsoffset"] = SimpleItoa(has_bit_indices_[field->index()]);
+      printer->Print(vars,
+                     "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($"
+                     "classname$, $field_name$_), $tag$, "
+                     "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($"
+                     "classname$, _has_bits_) * 8 + $hasbitsoffset$, $type$, "
+                     "$ptr$},\n");
+    } else {
+      printer->Print(vars,
+                     "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($"
+                     "classname$, $field_name$_), $tag$, ~0u, $type$, "
+                     "$ptr$},\n");
+    }
   }
+  int num_field_metadata = 1 + sorted.size() + sorted_extensions.size();
+  num_field_metadata++;
+  string serializer = UseUnknownFieldSet(descriptor_->file(), options_)
+                          ? "::google::protobuf::internal::UnknownFieldSetSerializer"
+                          : "::google::protobuf::internal::UnknownFieldSerializerLite";
+  printer->Print(
+      "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, "
+      "_internal_metadata_), 0, ~0u, "
+      "::google::protobuf::internal::FieldMetadata::kSpecial, reinterpret_cast<const "
+      "void*>($serializer$)},\n",
+      "classname", full_classname, "serializer", serializer);
+  return num_field_metadata;
 }
 
-void MessageGenerator::
-GenerateDefaultInstanceAllocator(io::Printer* printer) {
-  // Construct the default instances of all fields, as they will be used
-  // when creating the default instance of the entire message.
+void MessageGenerator::GenerateFieldDefaultInstances(io::Printer* printer) {
+  // Construct the default instances for all fields that need one.
   for (int i = 0; i < descriptor_->field_count(); i++) {
     field_generators_.get(descriptor_->field(i))
                      .GenerateDefaultInstanceAllocator(printer);
   }
-
-  if (IsMapEntryMessage(descriptor_)) return;
-
-  // Construct the default instance.  We can't call InitAsDefaultInstance() yet
-  // because we need to make sure all default instances that this one might
-  // depend on are constructed first.
-  printer->Print(
-    "$classname$::default_instance_ = new $classname$();\n",
-    "classname", classname_);
-
-  if ((descriptor_->oneof_decl_count() > 0) &&
-      HasDescriptorMethods(descriptor_->file())) {
-    printer->Print(
-    "$classname$_default_oneof_instance_ = new $classname$OneofInstance();\n",
-    "classname", classname_);
-  }
-
-  // Handle nested types.
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    nested_generators_[i]->GenerateDefaultInstanceAllocator(printer);
-  }
-
 }
 
 void MessageGenerator::
 GenerateDefaultInstanceInitializer(io::Printer* printer) {
-  printer->Print(
-    "$classname$::default_instance_->InitAsDefaultInstance();\n",
-    "classname", classname_);
-
-  // Register extensions.
-  for (int i = 0; i < descriptor_->extension_count(); i++) {
-    extension_generators_[i]->GenerateRegistration(printer);
-  }
-
-  // Handle nested types.
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    // map entry message doesn't need to initialize default instance manually.
-    // Since map entry message cannot be a top level class, we just need to
-    // avoid calling DefaultInstanceInitializer here.
-    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
-    nested_generators_[i]->GenerateDefaultInstanceInitializer(printer);
-  }
-}
-
-void MessageGenerator::
-GenerateShutdownCode(io::Printer* printer) {
-  printer->Print(
-    "delete $classname$::default_instance_;\n",
-    "classname", classname_);
-
-  if (HasDescriptorMethods(descriptor_->file())) {
-    if (descriptor_->oneof_decl_count() > 0) {
-      printer->Print(
-        "delete $classname$_default_oneof_instance_;\n",
-        "classname", classname_);
-    }
-    printer->Print(
-      "delete $classname$_reflection_;\n",
-      "classname", classname_);
-  }
-
-  // Handle default instances of fields.
+  // The default instance needs all of its embedded message pointers
+  // cross-linked to other default instances.  We can't do this initialization
+  // in the constructor because some other default instances may not have been
+  // constructed yet at that time.
+  // TODO(kenton):  Maybe all message fields (even for non-default messages)
+  //   should be initialized to point at default instances rather than NULL?
   for (int i = 0; i < descriptor_->field_count(); i++) {
-    field_generators_.get(descriptor_->field(i))
-                     .GenerateShutdownCode(printer);
-  }
+    const FieldDescriptor* field = descriptor_->field(i);
 
-  // Handle nested types.
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
-    nested_generators_[i]->GenerateShutdownCode(printer);
+    if (!field->is_repeated() &&
+        field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+        (field->containing_oneof() == NULL ||
+         HasDescriptorMethods(descriptor_->file(), options_))) {
+      string name;
+      if (field->containing_oneof() || field->options().weak()) {
+        name = "_" + classname_ + "_default_instance_.";
+      } else {
+        name =
+            "_" + classname_ + "_default_instance_._instance.get_mutable()->";
+      }
+      name += FieldName(field);
+      printer->Print(
+          "$ns$::$name$_ = const_cast< $type$*>(\n"
+          "    $type$::internal_default_instance());\n",
+          // Vars.
+          "name", name, "type", FieldMessageTypeName(field), "ns",
+          Namespace(descriptor_));
+    } else if (field->containing_oneof() &&
+               HasDescriptorMethods(descriptor_->file(), options_)) {
+      field_generators_.get(descriptor_->field(i))
+          .GenerateConstructorCode(printer);
+    }
   }
 }
 
 void MessageGenerator::
 GenerateClassMethods(io::Printer* printer) {
-  // mutable_unknown_fields wrapper function for LazyStringOutputStream
-  // callback.
-  if (!UseUnknownFieldSet(descriptor_->file())) {
+  if (IsMapEntryMessage(descriptor_)) {
     printer->Print(
-        "static ::std::string* MutableUnknownFieldsFor$classname$(\n"
-        "    $classname$* ptr) {\n"
-        "  return ptr->mutable_unknown_fields();\n"
-        "}\n"
-        "\n",
+        "$classname$::$classname$() {}\n"
+        "$classname$::$classname$(::google::protobuf::Arena* arena) : "
+        "SuperType(arena) {}\n"
+        "void $classname$::MergeFrom(const $classname$& other) {\n"
+        "  MergeFromInternal(other);\n"
+        "}\n",
         "classname", classname_);
+    if (HasDescriptorMethods(descriptor_->file(), options_)) {
+      printer->Print(
+          "::google::protobuf::Metadata $classname$::GetMetadata() const {\n"
+          "  ::$file_namespace$::protobuf_AssignDescriptorsOnce();\n"
+          "  return ::$file_namespace$::file_level_metadata[$index$];\n"
+          "}\n"
+          "void $classname$::MergeFrom(\n"
+          "    const ::google::protobuf::Message& other) {\n"
+          "  ::google::protobuf::Message::MergeFrom(other);\n"
+          "}\n"
+          "\n",
+          "file_namespace", FileLevelNamespace(descriptor_),
+          "classname", classname_, "index",
+          SimpleItoa(index_in_file_messages_));
+    }
+    return;
   }
+
+  // TODO(gerbens) Remove this function. With a little bit of cleanup and
+  // refactoring this is superfluous.
+  printer->Print("void $classname$::InitAsDefaultInstance() {\n", "classname",
+                 classname_);
+  printer->Indent();
+  GenerateDefaultInstanceInitializer(printer);
+  printer->Outdent();
+  printer->Print("}\n");
+
   if (IsAnyMessage(descriptor_)) {
     printer->Print(
       "void $classname$::PackFrom(const ::google::protobuf::Message& message) {\n"
       "  _any_metadata_.PackFrom(message);\n"
       "}\n"
       "\n"
+      "void $classname$::PackFrom(const ::google::protobuf::Message& message,\n"
+      "                           const ::std::string& type_url_prefix) {\n"
+      "  _any_metadata_.PackFrom(message, type_url_prefix);\n"
+      "}\n"
+      "\n"
       "bool $classname$::UnpackTo(::google::protobuf::Message* message) const {\n"
       "  return _any_metadata_.UnpackTo(message);\n"
       "}\n"
+      "bool $classname$::ParseAnyTypeUrl(const string& type_url,\n"
+      "                                  string* full_type_name) {\n"
+      "  return ::google::protobuf::internal::ParseAnyTypeUrl(type_url,\n"
+      "                                             full_type_name);\n"
+      "}\n"
       "\n",
       "classname", classname_);
   }
 
-  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
-    enum_generators_[i]->GenerateMethods(printer);
-  }
-
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    // map entry message doesn't need class methods. Since map entry message
-    // cannot be a top level class, we just need to avoid calling
-    // GenerateClassMethods here.
-    if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
-    nested_generators_[i]->GenerateClassMethods(printer);
-    printer->Print("\n");
-    printer->Print(kThinSeparator);
-    printer->Print("\n");
-  }
-
   // Generate non-inline field definitions.
   for (int i = 0; i < descriptor_->field_count(); i++) {
-    field_generators_.get(descriptor_->field(i))
+    const FieldDescriptor* field = descriptor_->field(i);
+    field_generators_.get(field)
                      .GenerateNonInlineAccessorDefinitions(printer);
+    if (IsCrossFileMaybeMap(field)) {
+      std::map<string, string> vars;
+      SetCommonFieldVariables(field, &vars, options_);
+      if (field->containing_oneof()) {
+        SetCommonOneofFieldVariables(field, &vars);
+      }
+      GenerateFieldClear(field, vars, false, printer);
+    }
   }
 
   // Generate field number constants.
@@ -1830,11 +1822,6 @@
     "#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900\n"
     "\n");
 
-  // Define extension identifiers.
-  for (int i = 0; i < descriptor_->extension_count(); i++) {
-    extension_generators_[i]->GenerateDefinition(printer);
-  }
-
   GenerateStructors(printer);
   printer->Print("\n");
 
@@ -1843,7 +1830,7 @@
     printer->Print("\n");
   }
 
-  if (HasGeneratedMethods(descriptor_->file())) {
+  if (HasGeneratedMethods(descriptor_->file(), options_)) {
     GenerateClear(printer);
     printer->Print("\n");
 
@@ -1853,7 +1840,7 @@
     GenerateSerializeWithCachedSizes(printer);
     printer->Print("\n");
 
-    if (HasFastArraySerialization(descriptor_->file())) {
+    if (HasFastArraySerialization(descriptor_->file(), options_)) {
       GenerateSerializeWithCachedSizesToArray(printer);
       printer->Print("\n");
     }
@@ -1874,17 +1861,26 @@
   GenerateSwap(printer);
   printer->Print("\n");
 
-  if (HasDescriptorMethods(descriptor_->file())) {
+  if (options_.table_driven_serialization) {
     printer->Print(
-      "::google::protobuf::Metadata $classname$::GetMetadata() const {\n"
-      "  protobuf_AssignDescriptorsOnce();\n"
-      "  ::google::protobuf::Metadata metadata;\n"
-      "  metadata.descriptor = $classname$_descriptor_;\n"
-      "  metadata.reflection = $classname$_reflection_;\n"
-      "  return metadata;\n"
-      "}\n"
-      "\n",
-      "classname", classname_);
+        "const void* $classname$::InternalGetTable() const {\n"
+        "  return ::$file_namespace$::TableStruct::serialization_table + "
+        "$index$;\n"
+        "}\n"
+        "\n",
+        "classname", classname_, "index", SimpleItoa(index_in_file_messages_),
+        "file_namespace", FileLevelNamespace(descriptor_));
+  }
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
+    printer->Print(
+        "::google::protobuf::Metadata $classname$::GetMetadata() const {\n"
+        "  $file_namespace$::protobuf_AssignDescriptorsOnce();\n"
+        "  return ::"
+        "$file_namespace$::file_level_metadata[kIndexInFileMessages];\n"
+        "}\n"
+        "\n",
+        "classname", classname_, "file_namespace",
+        FileLevelNamespace(descriptor_));
   } else {
     printer->Print(
       "::std::string $classname$::GetTypeName() const {\n"
@@ -1897,42 +1893,271 @@
 
 }
 
-void MessageGenerator::
-GenerateOffsets(io::Printer* printer) {
-  printer->Print(
-    "static const int $classname$_offsets_[$field_count$] = {\n",
-    "classname", classname_,
-    "field_count", SimpleItoa(max(
-        1, descriptor_->field_count() + descriptor_->oneof_decl_count())));
-  printer->Indent();
+size_t MessageGenerator::GenerateParseOffsets(io::Printer* printer) {
+  if (!table_driven_) {
+    return 0;
+  }
+
+  // Field "0" is special:  We use it in our switch statement of processing
+  // types to handle the successful end tag case.
+  printer->Print("{0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},\n");
+  int last_field_number = 1;
+
+  std::vector<const FieldDescriptor*> ordered_fields =
+      SortFieldsByNumber(descriptor_);
 
   for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = descriptor_->field(i);
-    if (field->containing_oneof()) {
+    const FieldDescriptor* field = ordered_fields[i];
+    GOOGLE_CHECK_GE(field->number(), last_field_number);
+
+    for (; last_field_number < field->number(); last_field_number++) {
       printer->Print(
-          "PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET("
-          "$classname$_default_oneof_instance_, $name$_),\n",
-          "classname", classname_,
-          "name", FieldName(field));
+          "{ 0, 0, ::google::protobuf::internal::kInvalidMask,\n"
+          "  ::google::protobuf::internal::kInvalidMask, 0, 0 },\n");
+    }
+    last_field_number++;
+
+    unsigned char normal_wiretype, packed_wiretype, processing_type;
+    normal_wiretype = WireFormat::WireTypeForFieldType(field->type());
+
+    if (field->is_packable()) {
+      packed_wiretype = WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
+    } else {
+      packed_wiretype = internal::kNotPackedMask;
+    }
+
+    processing_type = static_cast<unsigned>(field->type());
+    const FieldGenerator& generator = field_generators_.get(field);
+    if (field->type() == FieldDescriptor::TYPE_STRING) {
+      switch (EffectiveStringCType(field)) {
+        case FieldOptions::STRING:
+        default: {
+          if (generator.IsInlined()) {
+            processing_type = internal::TYPE_STRING_INLINED;
+            break;
+          }
+          break;
+        }
+      }
+    } else if (field->type() == FieldDescriptor::TYPE_BYTES) {
+      switch (EffectiveStringCType(field)) {
+        case FieldOptions::STRING:
+        default:
+          if (generator.IsInlined()) {
+            processing_type = internal::TYPE_BYTES_INLINED;
+            break;
+          }
+          break;
+      }
+    }
+
+    processing_type |= static_cast<unsigned>(
+        field->is_repeated() ?  internal::kRepeatedMask : 0);
+    processing_type |= static_cast<unsigned>(
+        field->containing_oneof() ? internal::kOneofMask : 0);
+
+    if (field->is_map()) {
+      processing_type = internal::TYPE_MAP;
+    }
+
+    const unsigned char tag_size =
+      WireFormat::TagSize(field->number(), field->type());
+
+    std::map<string, string> vars;
+    vars["classname"] = QualifiedClassName(descriptor_);
+    if (field->containing_oneof() != NULL) {
+      vars["name"] = field->containing_oneof()->name();
+      vars["presence"] = SimpleItoa(field->containing_oneof()->index());
+    } else {
+      vars["name"] = FieldName(field);
+      vars["presence"] = SimpleItoa(has_bit_indices_[field->index()]);
+    }
+    vars["nwtype"] = SimpleItoa(normal_wiretype);
+    vars["pwtype"] = SimpleItoa(packed_wiretype);
+    vars["ptype"] = SimpleItoa(processing_type);
+    vars["tag_size"] = SimpleItoa(tag_size);
+
+    printer->Print(vars,
+      "{\n"
+      "  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n"
+      "    $classname$, $name$_),\n"
+      "  static_cast<::google::protobuf::uint32>($presence$),\n"
+      "  $nwtype$, $pwtype$, $ptype$, $tag_size$\n"
+      "},\n");
+  }
+
+  return last_field_number;
+}
+
+size_t MessageGenerator::GenerateParseAuxTable(io::Printer* printer) {
+  if (!table_driven_) {
+    return 0;
+  }
+
+  std::vector<const FieldDescriptor*> ordered_fields =
+      SortFieldsByNumber(descriptor_);
+
+  printer->Print("::google::protobuf::internal::AuxillaryParseTableField(),\n");
+  int last_field_number = 1;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = ordered_fields[i];
+
+    GOOGLE_CHECK_GE(field->number(), last_field_number);
+    for (; last_field_number < field->number(); last_field_number++) {
+      printer->Print("::google::protobuf::internal::AuxillaryParseTableField(),\n");
+    }
+
+    std::map<string, string> vars;
+    SetCommonFieldVariables(field, &vars, options_);
+
+    switch (field->cpp_type()) {
+      case FieldDescriptor::CPPTYPE_ENUM:
+        vars["type"] = ClassName(field->enum_type(), true);
+        printer->Print(
+            vars,
+            "{::google::protobuf::internal::AuxillaryParseTableField::enum_aux{"
+            "$type$_IsValid}},\n");
+        last_field_number++;
+        break;
+      case FieldDescriptor::CPPTYPE_MESSAGE: {
+        if (field->is_map()) {
+          vars["classname"] = QualifiedClassName(field->message_type());
+          printer->Print(vars,
+                         "{::google::protobuf::internal::AuxillaryParseTableField::map_"
+                         "aux{&::google::protobuf::internal::ParseMap<$classname$>}},\n");
+          last_field_number++;
+          break;
+        } else {
+          vars["classname"] = ClassName(field->message_type(), false);
+        }
+        vars["ns"] = Namespace(field->message_type());
+        vars["type"] = FieldMessageTypeName(field);
+        vars["file_namespace"] =
+            FileLevelNamespace(field->message_type());
+
+        printer->Print(
+            vars,
+            "{::google::protobuf::internal::AuxillaryParseTableField::message_aux{\n"
+            "  &$ns$::_$classname$_default_instance_}},\n");
+        last_field_number++;
+        break;
+      }
+      case FieldDescriptor::CPPTYPE_STRING:
+        switch (EffectiveStringCType(field)) {
+          case FieldOptions::STRING:
+            vars["default"] =
+                field->default_value_string().empty()
+                    ? "&::google::protobuf::internal::fixed_address_empty_string"
+                    : "&" + Namespace(field) + " ::" + classname_ +
+                          "::" + MakeDefaultName(field);
+            break;
+          case FieldOptions::CORD:
+          case FieldOptions::STRING_PIECE:
+            vars["default"] =
+                "\"" + CEscape(field->default_value_string()) + "\"";
+            break;
+        }
+        vars["full_name"] = field->full_name();
+        printer->Print(vars,
+            "{::google::protobuf::internal::AuxillaryParseTableField::string_aux{\n"
+            "  $default$,\n"
+            "  \"$full_name$\"\n"
+            "}},\n");
+        last_field_number++;
+        break;
+      default:
+        break;
+    }
+  }
+
+  return last_field_number;
+}
+
+std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(
+    io::Printer* printer) {
+  std::map<string, string> variables;
+  string full_classname = QualifiedClassName(descriptor_);
+  variables["classname"] = full_classname;
+
+  if (HasFieldPresence(descriptor_->file()) || IsMapEntryMessage(descriptor_)) {
+    printer->Print(
+        variables,
+        "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, "
+        "_has_bits_),\n");
+  } else {
+    printer->Print("~0u,  // no _has_bits_\n");
+  }
+  printer->Print(variables,
+                 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, "
+                 "_internal_metadata_),\n");
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(
+        variables,
+        "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, "
+        "_extensions_),\n");
+  } else {
+    printer->Print("~0u,  // no _extensions_\n");
+  }
+  if (descriptor_->oneof_decl_count() > 0) {
+    printer->Print(variables,
+                   "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
+                   "$classname$, _oneof_case_[0]),\n");
+  } else {
+    printer->Print("~0u,  // no _oneof_case_\n");
+  }
+  if (num_weak_fields_ > 0) {
+    printer->Print(variables,
+                   "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$,"
+                   " _weak_field_map_),\n");
+  } else {
+    printer->Print("~0u,  // no _weak_field_map_\n");
+  }
+  const int kNumGenericOffsets = 5;  // the number of fixed offsets above
+  const size_t offsets = kNumGenericOffsets +
+                         descriptor_->field_count() +
+                         descriptor_->oneof_decl_count();
+  size_t entries = offsets;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (field->containing_oneof() || field->options().weak()) {
+      printer->Print("offsetof($classname$DefaultTypeInternal, $name$_)",
+                     "classname", full_classname, "name", FieldName(field));
     } else {
       printer->Print(
-          "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, "
-                                                 "$name$_),\n",
-          "classname", classname_,
-          "name", FieldName(field));
+          "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_)",
+          "classname", full_classname, "name", FieldName(field));
     }
+
+    uint32 tag = field_generators_.get(field).CalculateFieldTag();
+    if (tag != 0) {
+      printer->Print(" | $tag$", "tag", SimpleItoa(tag));
+    }
+
+    printer->Print(",\n");
   }
 
   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
     const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
     printer->Print(
-      "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n",
-      "classname", classname_,
-      "name", oneof->name());
+        "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n",
+        "classname", full_classname, "name", oneof->name());
   }
 
-  printer->Outdent();
-  printer->Print("};\n");
+  if (IsMapEntryMessage(descriptor_)) {
+    entries += 2;
+    printer->Print(
+        "0,\n"
+        "1,\n");
+  } else if (HasFieldPresence(descriptor_->file())) {
+    entries += has_bit_indices_.size();
+    for (int i = 0; i < has_bit_indices_.size(); i++) {
+      const string index = has_bit_indices_[i] >= 0 ?
+        SimpleItoa(has_bit_indices_[i]) : "~0u";
+      printer->Print("$index$,\n", "index", index);
+    }
+  }
+
+  return std::make_pair(entries, offsets);
 }
 
 void MessageGenerator::
@@ -1942,33 +2167,8 @@
     "classname", classname_);
   printer->Indent();
 
-  if (!HasFieldPresence(descriptor_->file())) {
-    printer->Print(
-      "  _is_default_instance_ = false;\n");
-  }
-
-  printer->Print(StrCat(
-      uses_string_ ? "::google::protobuf::internal::GetEmptyString();\n" : "",
-      "_cached_size_ = 0;\n").c_str());
-
-  if (PreserveUnknownFields(descriptor_) &&
-      !UseUnknownFieldSet(descriptor_->file())) {
-    printer->Print(
-        "_unknown_fields_.UnsafeSetDefault(\n"
-        "    &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n");
-  }
-
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    if (!descriptor_->field(i)->containing_oneof()) {
-      field_generators_.get(descriptor_->field(i))
-          .GenerateConstructorCode(printer);
-    }
-  }
-
-  if (HasFieldPresence(descriptor_->file())) {
-    printer->Print(
-      "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
-  }
+  std::vector<bool> processed(optimized_order_.size(), false);
+  GenerateConstructorBody(printer, processed, false);
 
   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
     printer->Print(
@@ -1987,35 +2187,14 @@
     "classname", classname_);
   printer->Indent();
   if (SupportsArenas(descriptor_)) {
-    // Do nothing when the message is allocated in an arena.
     printer->Print(
-      "if (GetArenaNoVirtual() != NULL) {\n"
-      "  return;\n"
-      "}\n"
-      "\n");
+      "GOOGLE_DCHECK(GetArenaNoVirtual() == NULL);\n");
   }
-
-  // Write the desctructor for _unknown_fields_ in lite runtime.
-  if (PreserveUnknownFields(descriptor_) &&
-      !UseUnknownFieldSet(descriptor_->file())) {
-    if (SupportsArenas(descriptor_)) {
-      printer->Print(
-          "_unknown_fields_.Destroy(\n"
-          "    &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n"
-          "    GetArenaNoVirtual());\n");
-    } else {
-      printer->Print(
-          "_unknown_fields_.DestroyNoArena(\n"
-          "    &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n");
-    }
-  }
-
   // Write the destructors for each field except oneof members.
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    if (!descriptor_->field(i)->containing_oneof()) {
-      field_generators_.get(descriptor_->field(i))
-                       .GenerateDestructorCode(printer);
-    }
+  // optimized_order_ does not contain oneof fields.
+  for (int i = 0; i < optimized_order_.size(); i++) {
+    const FieldDescriptor* field = optimized_order_[i];
+    field_generators_.get(field).GenerateDestructorCode(printer);
   }
 
   // Generate code to destruct oneofs. Clearing should do the work.
@@ -2027,34 +2206,11 @@
         "oneof_name", descriptor_->oneof_decl(i)->name());
   }
 
-  PrintHandlingOptionalStaticInitializers(
-    descriptor_->file(), printer,
-    // With static initializers.
-    "if (this != default_instance_) {\n",
-    // Without.
-    "if (this != &default_instance()) {\n");
-
-  // We need to delete all embedded messages.
-  // TODO(kenton):  If we make unset messages point at default instances
-  //   instead of NULL, then it would make sense to move this code into
-  //   MessageFieldGenerator::GenerateDestructorCode().
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = descriptor_->field(i);
-
-    if (!field->is_repeated() &&
-        field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
-      // Skip oneof members
-      if (!field->containing_oneof()) {
-        printer->Print(
-            "  delete $name$_;\n",
-            "name", FieldName(field));
-      }
-    }
+  if (num_weak_fields_) {
+    printer->Print("_weak_field_map_.ClearAll();\n");
   }
-
   printer->Outdent();
   printer->Print(
-    "  }\n"
     "}\n"
     "\n");
 }
@@ -2079,12 +2235,37 @@
       "classname", classname_);
 
   bool need_registration = false;
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    if (field_generators_.get(descriptor_->field(i))
+  // Process non-oneof fields first.
+  for (int i = 0; i < optimized_order_.size(); i++) {
+    const FieldDescriptor* field = optimized_order_[i];
+    if (field_generators_.get(field)
                          .GenerateArenaDestructorCode(printer)) {
       need_registration = true;
     }
   }
+
+  // Process oneof fields.
+  //
+  // Note:  As of 10/5/2016, GenerateArenaDestructorCode does not emit anything
+  // and returns false for oneof fields.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
+
+    for (int j = 0; j < oneof->field_count(); j++) {
+      const FieldDescriptor* field = oneof->field(j);
+      if (field_generators_.get(field)
+                           .GenerateArenaDestructorCode(printer)) {
+        need_registration = true;
+      }
+    }
+  }
+  if (num_weak_fields_) {
+    // _this is the object being destructed (we are inside a static method
+    // here).
+    printer->Print("_this->_weak_field_map_.ClearAll();\n");
+    need_registration = true;
+  }
+
   printer->Outdent();
   printer->Print(
       "}\n");
@@ -2105,147 +2286,247 @@
   }
 }
 
+void MessageGenerator::GenerateConstructorBody(io::Printer* printer,
+                                               std::vector<bool> processed,
+                                               bool copy_constructor) const {
+  const FieldDescriptor* last_start = NULL;
+  // RunMap maps from fields that start each run to the number of fields in that
+  // run.  This is optimized for the common case that there are very few runs in
+  // a message and that most of the eligible fields appear together.
+  typedef hash_map<const FieldDescriptor*, size_t> RunMap;
+  RunMap runs;
+
+  for (int i = 0; i < optimized_order_.size(); ++i) {
+    const FieldDescriptor* field = optimized_order_[i];
+    if ((copy_constructor && IsPOD(field)) ||
+        (!copy_constructor && CanConstructByZeroing(field, options_))) {
+      if (last_start == NULL) {
+        last_start = field;
+      }
+
+      runs[last_start]++;
+    } else {
+      last_start = NULL;
+    }
+  }
+
+  string pod_template;
+  if (copy_constructor) {
+    pod_template =
+        "::memcpy(&$first$_, &from.$first$_,\n"
+        "  static_cast<size_t>(reinterpret_cast<char*>(&$last$_) -\n"
+        "  reinterpret_cast<char*>(&$first$_)) + sizeof($last$_));\n";
+  } else {
+    pod_template =
+        "::memset(&$first$_, 0, static_cast<size_t>(\n"
+        "    reinterpret_cast<char*>(&$last$_) -\n"
+        "    reinterpret_cast<char*>(&$first$_)) + sizeof($last$_));\n";
+  }
+
+  for (int i = 0; i < optimized_order_.size(); ++i) {
+    if (processed[i]) {
+      continue;
+    }
+
+    const FieldDescriptor* field = optimized_order_[i];
+    RunMap::const_iterator it = runs.find(field);
+
+    // We only apply the memset technique to runs of more than one field, as
+    // assignment is better than memset for generated code clarity.
+    if (it != runs.end() && it->second > 1) {
+      // Use a memset, then skip run_length fields.
+      const size_t run_length = it->second;
+      const string first_field_name = FieldName(field);
+      const string last_field_name =
+          FieldName(optimized_order_[i + run_length - 1]);
+
+      printer->Print(pod_template.c_str(),
+        "first", first_field_name,
+        "last", last_field_name);
+
+      i += run_length - 1;
+      // ++i at the top of the loop.
+    } else {
+      if (copy_constructor) {
+        field_generators_.get(field).GenerateCopyConstructorCode(printer);
+      } else {
+        field_generators_.get(field).GenerateConstructorCode(printer);
+      }
+    }
+  }
+}
+
 void MessageGenerator::
 GenerateStructors(io::Printer* printer) {
   string superclass;
-  if (use_dependent_base_) {
-    superclass =
-        DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">";
-  } else {
-    superclass = SuperClassName(descriptor_);
-  }
+  superclass = SuperClassName(descriptor_, options_);
   string initializer_with_arena = superclass + "()";
 
   if (descriptor_->extension_range_count() > 0) {
     initializer_with_arena += ",\n  _extensions_(arena)";
   }
 
-  if (UseUnknownFieldSet(descriptor_->file())) {
-    initializer_with_arena += ",\n  _internal_metadata_(arena)";
-  } else {
-    initializer_with_arena += ",\n  _arena_ptr_(arena)";
-  }
+  initializer_with_arena += ",\n  _internal_metadata_(arena)";
 
   // Initialize member variables with arena constructor.
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    bool has_arena_constructor = descriptor_->field(i)->is_repeated();
+  for (int i = 0; i < optimized_order_.size(); i++) {
+    const FieldDescriptor* field = optimized_order_[i];
+
+    bool has_arena_constructor = field->is_repeated();
     if (has_arena_constructor) {
       initializer_with_arena += string(",\n  ") +
-          FieldName(descriptor_->field(i)) + string("_(arena)");
+          FieldName(field) + string("_(arena)");
     }
   }
 
   if (IsAnyMessage(descriptor_)) {
-    initializer_with_arena += ",\n  _any_metadata_(&type_url, &value_)";
+    initializer_with_arena += ",\n  _any_metadata_(&type_url_, &value_)";
+  }
+  if (num_weak_fields_ > 0) {
+    initializer_with_arena += ", _weak_field_map_(arena)";
   }
 
-  string initializer_null;
-  initializer_null = (UseUnknownFieldSet(descriptor_->file()) ?
-    ", _internal_metadata_(NULL)" : ", _arena_ptr_(NULL)");
+  string initializer_null = superclass + "(), _internal_metadata_(NULL)";
   if (IsAnyMessage(descriptor_)) {
     initializer_null += ", _any_metadata_(&type_url_, &value_)";
   }
+  if (num_weak_fields_ > 0) {
+    initializer_null += ", _weak_field_map_(nullptr)";
+  }
 
   printer->Print(
       "$classname$::$classname$()\n"
-      "  : $superclass$()$initializer$ {\n"
+      "  : $initializer$ {\n"
+      "  ::google::protobuf::internal::InitSCC(\n"
+      "      &$file_namespace$::scc_info_$scc_name$.base);\n"
       "  SharedCtor();\n"
       "  // @@protoc_insertion_point(constructor:$full_name$)\n"
       "}\n",
-      "classname", classname_,
-      "superclass", superclass,
-      "full_name", descriptor_->full_name(),
-      "initializer", initializer_null);
+      "classname", classname_, "full_name", descriptor_->full_name(),
+      "scc_name", scc_name_, "initializer", initializer_null, "file_namespace",
+      FileLevelNamespace(descriptor_));
 
   if (SupportsArenas(descriptor_)) {
     printer->Print(
-        "\n"
         "$classname$::$classname$(::google::protobuf::Arena* arena)\n"
         "  : $initializer$ {\n"
+        "  "
+        "::google::protobuf::internal::InitSCC(&$file_namespace$::scc_info_$scc_name$."
+        "base);\n"
         "  SharedCtor();\n"
         "  RegisterArenaDtor(arena);\n"
         "  // @@protoc_insertion_point(arena_constructor:$full_name$)\n"
         "}\n",
-        "initializer", initializer_with_arena,
-        "classname", classname_,
-        "superclass", superclass,
-        "full_name", descriptor_->full_name());
+        "initializer", initializer_with_arena, "classname", classname_,
+        "superclass", superclass, "full_name", descriptor_->full_name(),
+        "scc_name", scc_name_, "file_namespace",
+        FileLevelNamespace(descriptor_));
   }
 
-  printer->Print(
-    "\n"
-    "void $classname$::InitAsDefaultInstance() {\n",
-    "classname", classname_);
-
-  if (!HasFieldPresence(descriptor_->file())) {
-    printer->Print(
-      "  _is_default_instance_ = true;\n");
-  }
-
-  // The default instance needs all of its embedded message pointers
-  // cross-linked to other default instances.  We can't do this initialization
-  // in the constructor because some other default instances may not have been
-  // constructed yet at that time.
-  // TODO(kenton):  Maybe all message fields (even for non-default messages)
-  //   should be initialized to point at default instances rather than NULL?
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = descriptor_->field(i);
-
-    if (!field->is_repeated() &&
-        field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
-        (field->containing_oneof() == NULL ||
-         HasDescriptorMethods(descriptor_->file()))) {
-      string name;
-      if (field->containing_oneof()) {
-        name = classname_ + "_default_oneof_instance_->";
-      }
-      name += FieldName(field);
-      PrintHandlingOptionalStaticInitializers(
-        descriptor_->file(), printer,
-        // With static initializers.
-        "  $name$_ = const_cast< $type$*>(&$type$::default_instance());\n",
-        // Without.
-        "  $name$_ = const_cast< $type$*>(\n"
-        "      $type$::internal_default_instance());\n",
-        // Vars.
-        "name", name,
-        "type", FieldMessageTypeName(field));
-    } else if (field->containing_oneof() &&
-               HasDescriptorMethods(descriptor_->file())) {
-      field_generators_.get(descriptor_->field(i))
-          .GenerateConstructorCode(printer);
-    }
-  }
-  printer->Print(
-    "}\n"
-    "\n");
-
   // Generate the copy constructor.
-  printer->Print(
-    "$classname$::$classname$(const $classname$& from)\n"
-    "  : $superclass$()",
-    "classname", classname_,
-    "superclass", superclass,
-    "full_name", descriptor_->full_name());
-  if (UseUnknownFieldSet(descriptor_->file())) {
+  if (UsingImplicitWeakFields(descriptor_->file(), options_)) {
+    // If we are in lite mode and using implicit weak fields, we generate a
+    // one-liner copy constructor that delegates to MergeFrom. This saves some
+    // code size and also cuts down on the complexity of implicit weak fields.
+    // We might eventually want to do this for all lite protos.
     printer->Print(
-        ",\n    _internal_metadata_(NULL)");
-  } else if (!UseUnknownFieldSet(descriptor_->file())) {
-    printer->Print(",\n    _arena_ptr_(NULL)");
+      "$classname$::$classname$(const $classname$& from)\n"
+      "  : $classname$() {\n"
+      "  MergeFrom(from);\n"
+      "}\n",
+      "classname", classname_);
+  } else {
+    printer->Print(
+      "$classname$::$classname$(const $classname$& from)\n"
+      "  : $superclass$()",
+      "classname", classname_,
+      "superclass", superclass,
+      "full_name", descriptor_->full_name());
+    printer->Indent();
+    printer->Indent();
+    printer->Indent();
+
+    printer->Print(
+        ",\n_internal_metadata_(NULL)");
+
+    if (HasFieldPresence(descriptor_->file())) {
+        printer->Print(",\n_has_bits_(from._has_bits_)");
+    }
+
+    std::vector<bool> processed(optimized_order_.size(), false);
+    for (int i = 0; i < optimized_order_.size(); ++i) {
+      const FieldDescriptor* field = optimized_order_[i];
+
+      if (!(field->is_repeated() && !(field->is_map()))
+          ) {
+        continue;
+      }
+
+      processed[i] = true;
+      printer->Print(",\n$name$_(from.$name$_)",
+                     "name", FieldName(field));
+    }
+
+    if (IsAnyMessage(descriptor_)) {
+      printer->Print(",\n_any_metadata_(&type_url_, &value_)");
+    }
+    if (num_weak_fields_ > 0) {
+      printer->Print(",\n_weak_field_map_(from._weak_field_map_)");
+    }
+
+    printer->Outdent();
+    printer->Outdent();
+    printer->Print(" {\n");
+
+    printer->Print(
+        "_internal_metadata_.MergeFrom(from._internal_metadata_);\n");
+
+    if (descriptor_->extension_range_count() > 0) {
+      printer->Print("_extensions_.MergeFrom(from._extensions_);\n");
+    }
+
+    GenerateConstructorBody(printer, processed, true);
+
+    // Copy oneof fields. Oneof field requires oneof case check.
+    for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
+      printer->Print(
+          "clear_has_$oneofname$();\n"
+          "switch (from.$oneofname$_case()) {\n",
+          "oneofname", descriptor_->oneof_decl(i)->name());
+      printer->Indent();
+      for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+        const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+        printer->Print(
+            "case k$field_name$: {\n",
+            "field_name", UnderscoresToCamelCase(field->name(), true));
+        printer->Indent();
+        field_generators_.get(field).GenerateMergingCode(printer);
+        printer->Print(
+            "break;\n");
+        printer->Outdent();
+        printer->Print(
+            "}\n");
+      }
+      printer->Print(
+          "case $cap_oneof_name$_NOT_SET: {\n"
+          "  break;\n"
+          "}\n",
+          "oneof_index",
+          SimpleItoa(descriptor_->oneof_decl(i)->index()),
+          "cap_oneof_name",
+          ToUpper(descriptor_->oneof_decl(i)->name()));
+      printer->Outdent();
+      printer->Print(
+          "}\n");
+    }
+
+    printer->Outdent();
+    printer->Print(
+      "  // @@protoc_insertion_point(copy_constructor:$full_name$)\n"
+      "}\n"
+      "\n",
+      "full_name", descriptor_->full_name());
   }
-  if (IsAnyMessage(descriptor_)) {
-    printer->Print(",\n    _any_metadata_(&type_url_, &value_)");
-  }
-  printer->Print(" {\n");
-  printer->Print(
-    "  SharedCtor();\n"
-    "  MergeFrom(from);\n"
-    "  // @@protoc_insertion_point(copy_constructor:$full_name$)\n"
-    "}\n"
-    "\n",
-    "classname", classname_,
-    "superclass", superclass,
-    "full_name", descriptor_->full_name());
 
   // Generate the shared constructor code.
   GenerateSharedConstructorCode(printer);
@@ -2270,67 +2551,46 @@
 
   // Generate SetCachedSize.
   printer->Print(
-    "void $classname$::SetCachedSize(int size) const {\n"
-    "  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
-    "  _cached_size_ = size;\n"
-    "  GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
-    "}\n",
-    "classname", classname_);
+      "void $classname$::SetCachedSize(int size) const {\n"
+      "  _cached_size_.Set(size);\n"
+      "}\n",
+      "classname", classname_);
 
   // Only generate this member if it's not disabled.
-  if (HasDescriptorMethods(descriptor_->file()) &&
+  if (HasDescriptorMethods(descriptor_->file(), options_) &&
       !descriptor_->options().no_standard_descriptor_accessor()) {
     printer->Print(
-      "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n"
-      "  protobuf_AssignDescriptorsOnce();\n"
-      "  return $classname$_descriptor_;\n"
-      "}\n"
-      "\n",
-      "classname", classname_,
-      "adddescriptorsname",
-      GlobalAddDescriptorsName(descriptor_->file()->name()));
+        "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n"
+        "  ::$file_namespace$::protobuf_AssignDescriptorsOnce();\n"
+        "  return ::"
+        "$file_namespace$::file_level_metadata[kIndexInFileMessages]."
+        "descriptor;\n"
+        "}\n"
+        "\n",
+        "classname", classname_, "file_namespace",
+        FileLevelNamespace(descriptor_));
   }
 
   printer->Print(
-    "const $classname$& $classname$::default_instance() {\n",
-    "classname", classname_);
+      "const $classname$& $classname$::default_instance() {\n"
+      "  "
+      "::google::protobuf::internal::InitSCC(&$file_namespace$::scc_info_$scc_name$.base)"
+      ";\n"
+      "  return *internal_default_instance();\n"
+      "}\n\n",
+      "classname", classname_, "scc_name", scc_name_, "file_namespace",
+      FileLevelNamespace(descriptor_));
+}
 
-  PrintHandlingOptionalStaticInitializers(
-    descriptor_->file(), printer,
-    // With static initializers.
-    "  if (default_instance_ == NULL) $adddescriptorsname$();\n",
-    // Without.
-    "  $adddescriptorsname$();\n",
-    // Vars.
-    "adddescriptorsname",
-    GlobalAddDescriptorsName(descriptor_->file()->name()));
-
+void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* printer) {
   printer->Print(
-    "  return *default_instance_;\n"
-    "}\n"
-    "\n"
-    "$classname$* $classname$::default_instance_ = NULL;\n"
-    "\n",
-    "classname", classname_);
-
-  if (SupportsArenas(descriptor_)) {
-    printer->Print(
-      "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n"
-      "  return ::google::protobuf::Arena::CreateMessage<$classname$>(arena);\n"
+      "template<> "
+      "GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE "
+      "$classname$* Arena::CreateMaybeMessage< $classname$ >(Arena* arena) {\n"
+      "  return Arena::$create_func$Internal< $classname$ >(arena);\n"
       "}\n",
-      "classname", classname_);
-  } else {
-    printer->Print(
-      "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n"
-      "  $classname$* n = new $classname$;\n"
-      "  if (arena != NULL) {\n"
-      "    arena->Own(n);\n"
-      "  }\n"
-      "  return n;\n"
-      "}\n",
-      "classname", classname_);
-  }
-
+      "classname", QualifiedClassName(descriptor_),
+      "create_func", MessageCreateFunction(descriptor_));
 }
 
 // Return the number of bits set in n, a non-negative integer.
@@ -2343,161 +2603,216 @@
   return result;
 }
 
+bool MessageGenerator::MaybeGenerateOptionalFieldCondition(
+    io::Printer* printer, const FieldDescriptor* field,
+    int expected_has_bits_index) {
+  int has_bit_index = has_bit_indices_[field->index()];
+  if (!field->options().weak() &&
+      expected_has_bits_index == has_bit_index / 32) {
+    const string mask =
+        StrCat(strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
+    printer->Print(
+        "if (cached_has_bits & 0x$mask$u) {\n",
+        "mask", mask);
+    return true;
+  }
+  return false;
+}
+
 void MessageGenerator::
 GenerateClear(io::Printer* printer) {
-  printer->Print("void $classname$::Clear() {\n",
-                 "classname", classname_);
+  // Performance tuning parameters
+  const int kMaxUnconditionalPrimitiveBytesClear = 4;
+
+  printer->Print(
+      "void $classname$::Clear() {\n"
+      "// @@protoc_insertion_point(message_clear_start:$full_name$)\n",
+      "classname", classname_, "full_name", descriptor_->full_name());
   printer->Indent();
 
+  printer->Print(
+      // TODO(jwb): It would be better to avoid emitting this if it is not used,
+      // rather than emitting a workaround for the resulting warning.
+      "::google::protobuf::uint32 cached_has_bits = 0;\n"
+      "// Prevent compiler warnings about cached_has_bits being unused\n"
+      "(void) cached_has_bits;\n\n");
+
+  int cached_has_bit_index = -1;
+
   // Step 1: Extensions
   if (descriptor_->extension_range_count() > 0) {
     printer->Print("_extensions_.Clear();\n");
   }
 
-  // Step 2: Everything but extensions, repeateds, unions.
-  // These are handled in chunks of 8.  The first chunk is
-  // the non-extensions-non-repeateds-non-unions in
-  //  descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7),
-  // and the second chunk is the same for
-  //  descriptor_->field(8), descriptor_->field(9), ... descriptor_->field(15),
-  // etc.
-  set<int> step2_indices;
-  hash_map<string, int> fieldname_to_chunk;
-  hash_map<int, string> memsets_for_chunk;
-  hash_map<int, int> memset_field_count_for_chunk;
-  hash_set<string> handled;  // fields that appear anywhere in memsets_for_chunk
-  hash_map<int, uint32> fields_mask_for_chunk;
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = descriptor_->field(i);
-    if (!field->is_repeated() && !field->containing_oneof()) {
-      step2_indices.insert(i);
-      int chunk = i / 8;
-      fieldname_to_chunk[FieldName(field)] = chunk;
-      fields_mask_for_chunk[chunk] |= static_cast<uint32>(1) << (i % 32);
+  int unconditional_budget = kMaxUnconditionalPrimitiveBytesClear;
+  for (int i = 0; i < optimized_order_.size(); i++) {
+    const FieldDescriptor* field = optimized_order_[i];
+
+    if (!CanInitializeByZeroing(field)) {
+      continue;
+    }
+
+    unconditional_budget -= EstimateAlignmentSize(field);
+  }
+
+  std::vector<std::vector<const FieldDescriptor*> > chunks_frag = CollectFields(
+      optimized_order_,
+      MatchRepeatedAndHasByteAndZeroInits(
+          &has_bit_indices_, HasFieldPresence(descriptor_->file())));
+
+  // Merge next non-zero initializable chunk if it has the same has_byte index
+  // and not meeting unconditional clear condition.
+  std::vector<std::vector<const FieldDescriptor*> > chunks;
+  if (!HasFieldPresence(descriptor_->file())) {
+    // Don't bother with merging without has_bit field.
+    chunks = chunks_frag;
+  } else {
+    // Note that only the next chunk is considered for merging.
+    for (int i = 0; i < chunks_frag.size(); i++) {
+      chunks.push_back(chunks_frag[i]);
+      const FieldDescriptor* field = chunks_frag[i].front();
+      const FieldDescriptor* next_field =
+          (i + 1) < chunks_frag.size() ? chunks_frag[i + 1].front() : nullptr;
+      if (CanInitializeByZeroing(field) &&
+          (chunks_frag[i].size() == 1 || unconditional_budget < 0) &&
+          next_field != nullptr &&
+          has_bit_indices_[field->index()] / 8 ==
+              has_bit_indices_[next_field->index()] / 8) {
+        GOOGLE_CHECK(!CanInitializeByZeroing(next_field));
+        // Insert next chunk to the current one and skip next chunk.
+        chunks.back().insert(chunks.back().end(), chunks_frag[i + 1].begin(),
+                             chunks_frag[i + 1].end());
+        i++;
+      }
     }
   }
 
-  // Step 2a: Greedily seek runs of fields that can be cleared by memset-to-0.
-  // The generated code uses two macros to help it clear runs of fields:
-  // ZR_HELPER_(f1) - ZR_HELPER_(f0) computes the difference, in bytes, of the
-  // positions of two fields in the Message.
-  // ZR_ zeroes a non-empty range of fields via memset.
-  const char* macros =
-      "#define ZR_HELPER_(f) reinterpret_cast<char*>(\\\n"
-      "  &reinterpret_cast<$classname$*>(16)->f)\n\n"
-      "#define ZR_(first, last) do {\\\n"
-      "  ::memset(&first, 0,\\\n"
-      "           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\\\n"
-      "} while (0)\n\n";
-  for (int i = 0; i < runs_of_fields_.size(); i++) {
-    const vector<string>& run = runs_of_fields_[i];
-    if (run.size() < 2) continue;
-    const string& first_field_name = run[0];
-    const string& last_field_name = run.back();
-    int chunk = fieldname_to_chunk[run[0]];
-    memsets_for_chunk[chunk].append(
-      "ZR_(" + first_field_name + "_, " + last_field_name + "_);\n");
-    for (int j = 0; j < run.size(); j++) {
-      GOOGLE_DCHECK_EQ(chunk, fieldname_to_chunk[run[j]]);
-      handled.insert(run[j]);
+  for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
+    std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
+    GOOGLE_CHECK(!chunk.empty());
+
+    // Step 2: Repeated fields don't use _has_bits_; emit code to clear them
+    // here.
+    if (chunk.front()->is_repeated()) {
+      for (int i = 0; i < chunk.size(); i++) {
+        const FieldDescriptor* field = chunk[i];
+        const FieldGenerator& generator = field_generators_.get(field);
+
+        generator.GenerateMessageClearingCode(printer);
+      }
+      continue;
     }
-    memset_field_count_for_chunk[chunk] += run.size();
-  }
-  const bool macros_are_needed = handled.size() > 0;
-  if (macros_are_needed) {
-    printer->Outdent();
-    printer->Print(macros,
-                   "classname", classname_);
-    printer->Indent();
-  }
-  // Step 2b: Finish step 2, ignoring fields handled in step 2a.
-  int last_index = -1;
-  bool chunk_block_in_progress = false;
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    if (step2_indices.count(i) == 0) continue;
-    const FieldDescriptor* field = descriptor_->field(i);
-    const string fieldname = FieldName(field);
-    if (i / 8 != last_index / 8 || last_index < 0) {
-      // End previous chunk, if there was one.
-      if (chunk_block_in_progress) {
+
+    // Step 3: Non-repeated fields that can be cleared by memset-to-0, then
+    // non-repeated, non-zero initializable fields.
+    int last_chunk = HasFieldPresence(descriptor_->file())
+                         ? has_bit_indices_[chunk.front()->index()] / 8
+                         : 0;
+    int last_chunk_start = 0;
+    int memset_run_start = -1;
+    int memset_run_end = -1;
+
+    for (int i = 0; i < chunk.size(); i++) {
+      const FieldDescriptor* field = chunk[i];
+      if (CanInitializeByZeroing(field)) {
+        if (memset_run_start == -1) {
+          memset_run_start = i;
+        }
+        memset_run_end = i;
+      }
+    }
+
+    const bool have_outer_if =
+        HasFieldPresence(descriptor_->file()) && chunk.size() > 1 &&
+        (memset_run_end != chunk.size() - 1 || unconditional_budget < 0);
+
+    if (have_outer_if) {
+      uint32 last_chunk_mask = GenChunkMask(chunk, has_bit_indices_);
+      const int count = popcnt(last_chunk_mask);
+
+      // Check (up to) 8 has_bits at a time if we have more than one field in
+      // this chunk.  Due to field layout ordering, we may check
+      // _has_bits_[last_chunk * 8 / 32] multiple times.
+      GOOGLE_DCHECK_LE(2, count);
+      GOOGLE_DCHECK_GE(8, count);
+
+      if (cached_has_bit_index != last_chunk / 4) {
+        cached_has_bit_index = last_chunk / 4;
+        printer->Print("cached_has_bits = _has_bits_[$idx$];\n", "idx",
+                       SimpleItoa(cached_has_bit_index));
+      }
+      printer->Print("if (cached_has_bits & $mask$u) {\n", "mask",
+                     SimpleItoa(last_chunk_mask));
+      printer->Indent();
+    }
+
+    if (memset_run_start != -1) {
+      if (memset_run_start == memset_run_end) {
+        // For clarity, do not memset a single field.
+        const FieldGenerator& generator =
+            field_generators_.get(chunk[memset_run_start]);
+        generator.GenerateMessageClearingCode(printer);
+      } else {
+        const string first_field_name = FieldName(chunk[memset_run_start]);
+        const string last_field_name = FieldName(chunk[memset_run_end]);
+
+        printer->Print(
+            "::memset(&$first$_, 0, static_cast<size_t>(\n"
+            "    reinterpret_cast<char*>(&$last$_) -\n"
+            "    reinterpret_cast<char*>(&$first$_)) + sizeof($last$_));\n",
+            "first", first_field_name, "last", last_field_name);
+      }
+
+      // Advance last_chunk_start to skip over the fields we zeroed/memset.
+      last_chunk_start = memset_run_end + 1;
+    }
+
+    // Go back and emit clears for each of the fields we processed.
+    for (int j = last_chunk_start; j < chunk.size(); j++) {
+      const FieldDescriptor* field = chunk[j];
+      const string fieldname = FieldName(field);
+      const FieldGenerator& generator = field_generators_.get(field);
+
+      // It's faster to just overwrite primitive types, but we should only
+      // clear strings and messages if they were set.
+      //
+      // TODO(kenton):  Let the CppFieldGenerator decide this somehow.
+      bool should_check_bit =
+          field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
+          field->cpp_type() == FieldDescriptor::CPPTYPE_STRING;
+
+      bool have_enclosing_if = false;
+      if (should_check_bit &&
+          // If no field presence, then always clear strings/messages as well.
+          HasFieldPresence(descriptor_->file())) {
+        if (!field->options().weak() &&
+            cached_has_bit_index != (has_bit_indices_[field->index()] / 32)) {
+          cached_has_bit_index = (has_bit_indices_[field->index()] / 32);
+          printer->Print("cached_has_bits = _has_bits_[$new_index$];\n",
+                         "new_index", SimpleItoa(cached_has_bit_index));
+        }
+        if (!MaybeGenerateOptionalFieldCondition(printer, field,
+                                                 cached_has_bit_index)) {
+          printer->Print("if (has_$name$()) {\n", "name", fieldname);
+        }
+        printer->Indent();
+        have_enclosing_if = true;
+      }
+
+      generator.GenerateMessageClearingCode(printer);
+
+      if (have_enclosing_if) {
         printer->Outdent();
         printer->Print("}\n");
-        chunk_block_in_progress = false;
       }
-      // Start chunk.
-      const string& memsets = memsets_for_chunk[i / 8];
-      uint32 mask = fields_mask_for_chunk[i / 8];
-      int count = popcnt(mask);
-      GOOGLE_DCHECK_GE(count, 1);
-      if (count == 1 ||
-          (count <= 4 && count == memset_field_count_for_chunk[i / 8])) {
-        // No "if" here because the chunk is trivial.
-      } else {
-        if (HasFieldPresence(descriptor_->file())) {
-          printer->Print(
-            "if (_has_bits_[$index$ / 32] & $mask$u) {\n",
-            "index", SimpleItoa(i / 8 * 8),
-            "mask", SimpleItoa(mask));
-          printer->Indent();
-          chunk_block_in_progress = true;
-        }
-      }
-      printer->Print(memsets.c_str());
-    }
-    last_index = i;
-    if (handled.count(fieldname) > 0) continue;
-
-    // It's faster to just overwrite primitive types, but we should
-    // only clear strings and messages if they were set.
-    // TODO(kenton):  Let the CppFieldGenerator decide this somehow.
-    bool should_check_bit =
-      field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
-      field->cpp_type() == FieldDescriptor::CPPTYPE_STRING;
-
-    bool have_enclosing_if = false;
-    if (should_check_bit &&
-        // If no field presence, then always clear strings/messages as well.
-        HasFieldPresence(descriptor_->file())) {
-      printer->Print("if (has_$name$()) {\n", "name", fieldname);
-      printer->Indent();
-      have_enclosing_if = true;
     }
 
-    if (use_dependent_base_ && IsFieldDependent(field)) {
-      printer->Print("clear_$name$();\n", "name", fieldname);
-    } else {
-      field_generators_.get(field).GenerateClearingCode(printer);
-    }
-
-    if (have_enclosing_if) {
+    if (have_outer_if) {
       printer->Outdent();
       printer->Print("}\n");
     }
   }
 
-  if (chunk_block_in_progress) {
-    printer->Outdent();
-    printer->Print("}\n");
-  }
-  if (macros_are_needed) {
-    printer->Outdent();
-    printer->Print("\n#undef ZR_HELPER_\n#undef ZR_\n\n");
-    printer->Indent();
-  }
-
-  // Step 3: Repeated fields don't use _has_bits_; emit code to clear them here.
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = descriptor_->field(i);
-
-    if (field->is_repeated()) {
-      if (use_dependent_base_ && IsFieldDependent(field)) {
-        printer->Print("clear_$name$();\n", "name", FieldName(field));
-      } else {
-        field_generators_.get(field).GenerateClearingCode(printer);
-      }
-    }
-  }
-
   // Step 4: Unions.
   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
     printer->Print(
@@ -2505,32 +2820,17 @@
         "oneof_name", descriptor_->oneof_decl(i)->name());
   }
 
-  if (HasFieldPresence(descriptor_->file())) {
-    // Step 5: Everything else.
-    printer->Print(
-      "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
+  if (num_weak_fields_) {
+    printer->Print("_weak_field_map_.ClearAll();\n");
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    if (UseUnknownFieldSet(descriptor_->file())) {
-      printer->Print(
-        "if (_internal_metadata_.have_unknown_fields()) {\n"
-        "  mutable_unknown_fields()->Clear();\n"
-        "}\n");
-    } else {
-      if (SupportsArenas(descriptor_)) {
-        printer->Print(
-          "_unknown_fields_.ClearToEmpty(\n"
-          "    &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n"
-          "    GetArenaNoVirtual());\n");
-      } else {
-        printer->Print(
-          "_unknown_fields_.ClearToEmptyNoArena(\n"
-          "    &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n");
-      }
-    }
+  if (HasFieldPresence(descriptor_->file())) {
+    // Step 5: Everything else.
+    printer->Print("_has_bits_.Clear();\n");
   }
 
+  printer->Print("_internal_metadata_.Clear();\n");
+
   printer->Outdent();
   printer->Print("}\n");
 }
@@ -2539,16 +2839,19 @@
 GenerateOneofClear(io::Printer* printer) {
   // Generated function clears the active field and union case (e.g. foo_case_).
   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
-    map<string, string> oneof_vars;
+    std::map<string, string> oneof_vars;
     oneof_vars["classname"] = classname_;
     oneof_vars["oneofname"] = descriptor_->oneof_decl(i)->name();
+    oneof_vars["full_name"] = descriptor_->full_name();
     string message_class;
 
     printer->Print(oneof_vars,
-        "void $classname$::clear_$oneofname$() {\n");
+                   "void $classname$::clear_$oneofname$() {\n"
+                   "// @@protoc_insertion_point(one_of_clear_start:"
+                   "$full_name$)\n");
     printer->Indent();
     printer->Print(oneof_vars,
-        "switch($oneofname$_case()) {\n");
+        "switch ($oneofname$_case()) {\n");
     printer->Indent();
     for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
       const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
@@ -2602,10 +2905,13 @@
         "  if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {\n"
         "    InternalSwap(other);\n"
         "  } else {\n"
-        "    $classname$ temp;\n"
-        "    temp.MergeFrom(*this);\n"
-        "    CopyFrom(*other);\n"
-        "    other->CopyFrom(temp);\n"
+        "    $classname$* temp = New(GetArenaNoVirtual());\n"
+        "    temp->MergeFrom(*other);\n"
+        "    other->CopyFrom(*this);\n"
+        "    InternalSwap(temp);\n"
+        "    if (GetArenaNoVirtual() == NULL) {\n"
+        "      delete temp;\n"
+        "    }\n"
         "  }\n"
         "}\n"
         "void $classname$::UnsafeArenaSwap($classname$* other) {\n"
@@ -2627,45 +2933,40 @@
   printer->Print("void $classname$::InternalSwap($classname$* other) {\n",
                  "classname", classname_);
   printer->Indent();
+  printer->Print("using std::swap;\n");
 
-  if (HasGeneratedMethods(descriptor_->file())) {
-    for (int i = 0; i < descriptor_->field_count(); i++) {
-      const FieldDescriptor* field = descriptor_->field(i);
+  if (HasGeneratedMethods(descriptor_->file(), options_)) {
+    for (int i = 0; i < optimized_order_.size(); i++) {
+      // optimized_order_ does not contain oneof fields, but the field
+      // generators for these fields do not emit swapping code on their own.
+      const FieldDescriptor* field = optimized_order_[i];
       field_generators_.get(field).GenerateSwappingCode(printer);
     }
 
     for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
       printer->Print(
-        "std::swap($oneof_name$_, other->$oneof_name$_);\n"
-        "std::swap(_oneof_case_[$i$], other->_oneof_case_[$i$]);\n",
+        "swap($oneof_name$_, other->$oneof_name$_);\n"
+        "swap(_oneof_case_[$i$], other->_oneof_case_[$i$]);\n",
         "oneof_name", descriptor_->oneof_decl(i)->name(),
         "i", SimpleItoa(i));
     }
 
     if (HasFieldPresence(descriptor_->file())) {
-      for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) {
-        printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n",
+      for (int i = 0; i < HasBitsSize() / 4; ++i) {
+        printer->Print("swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n",
                        "i", SimpleItoa(i));
       }
     }
 
-    if (PreserveUnknownFields(descriptor_)) {
-      if (UseUnknownFieldSet(descriptor_->file())) {
-        printer->Print(
-          "_internal_metadata_.Swap(&other->_internal_metadata_);\n");
-      } else {
-        printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n");
-      }
-    } else {
-      // Still swap internal_metadata as it may contain more than just
-      // unknown fields.
-      printer->Print(
-        "_internal_metadata_.Swap(&other->_internal_metadata_);\n");
-    }
-    printer->Print("std::swap(_cached_size_, other->_cached_size_);\n");
+    printer->Print("_internal_metadata_.Swap(&other->_internal_metadata_);\n");
+
     if (descriptor_->extension_range_count() > 0) {
       printer->Print("_extensions_.Swap(&other->_extensions_);\n");
     }
+    if (num_weak_fields_) {
+      printer->Print(
+          "_weak_field_map_.UnsafeArenaSwap(&other->_weak_field_map_);\n");
+    }
   } else {
     printer->Print("GetReflection()->Swap(this, other);");
   }
@@ -2676,13 +2977,15 @@
 
 void MessageGenerator::
 GenerateMergeFrom(io::Printer* printer) {
-  if (HasDescriptorMethods(descriptor_->file())) {
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
     // Generate the generalized MergeFrom (aka that which takes in the Message
     // base class as a parameter).
     printer->Print(
-      "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n"
-      "  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
-      "classname", classname_);
+        "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n"
+        "// @@protoc_insertion_point(generalized_merge_from_start:"
+        "$full_name$)\n"
+        "  GOOGLE_DCHECK_NE(&from, this);\n",
+        "classname", classname_, "full_name", descriptor_->full_name());
     printer->Indent();
 
     // Cast the message to the proper type. If we find that the message is
@@ -2690,15 +2993,19 @@
     // system, as the GOOGLE_CHECK above ensured that we have the same descriptor
     // for each message.
     printer->Print(
-      "const $classname$* source = \n"
+      "const $classname$* source =\n"
       "    ::google::protobuf::internal::DynamicCastToGenerated<const $classname$>(\n"
       "        &from);\n"
       "if (source == NULL) {\n"
+      "// @@protoc_insertion_point(generalized_merge_from_cast_fail:"
+      "$full_name$)\n"
       "  ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n"
       "} else {\n"
+      "// @@protoc_insertion_point(generalized_merge_from_cast_success:"
+      "$full_name$)\n"
       "  MergeFrom(*source);\n"
       "}\n",
-      "classname", classname_);
+      "classname", classname_, "full_name", descriptor_->full_name());
 
     printer->Outdent();
     printer->Print("}\n\n");
@@ -2715,18 +3022,166 @@
 
   // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast.
   printer->Print(
-    "void $classname$::MergeFrom(const $classname$& from) {\n"
-    "  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
-    "classname", classname_);
+      "void $classname$::MergeFrom(const $classname$& from) {\n"
+      "// @@protoc_insertion_point(class_specific_merge_from_start:"
+      "$full_name$)\n"
+      "  GOOGLE_DCHECK_NE(&from, this);\n",
+      "classname", classname_, "full_name", descriptor_->full_name());
   printer->Indent();
 
-  // Merge Repeated fields. These fields do not require a
-  // check as we can simply iterate over them.
-  for (int i = 0; i < descriptor_->field_count(); ++i) {
-    const FieldDescriptor* field = descriptor_->field(i);
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print("_extensions_.MergeFrom(from._extensions_);\n");
+  }
 
-    if (field->is_repeated()) {
-      field_generators_.get(field).GenerateMergingCode(printer);
+  printer->Print(
+    "_internal_metadata_.MergeFrom(from._internal_metadata_);\n"
+    "::google::protobuf::uint32 cached_has_bits = 0;\n"
+    "(void) cached_has_bits;\n\n");
+
+  // cached_has_bit_index maintains that:
+  //   cached_has_bits = from._has_bits_[cached_has_bit_index]
+  // for cached_has_bit_index >= 0
+  int cached_has_bit_index = -1;
+
+  int last_i = -1;
+  for (int i = 0; i < optimized_order_.size(); ) {
+    // Detect infinite loops.
+    GOOGLE_CHECK_NE(i, last_i);
+    last_i = i;
+
+    // Merge Repeated fields. These fields do not require a
+    // check as we can simply iterate over them.
+    for (; i < optimized_order_.size(); i++) {
+      const FieldDescriptor* field = optimized_order_[i];
+      if (!field->is_repeated()) {
+        break;
+      }
+
+      const FieldGenerator& generator = field_generators_.get(field);
+      generator.GenerateMergingCode(printer);
+    }
+
+    // Merge Optional and Required fields (after a _has_bit_ check).
+    int last_chunk = -1;
+    int last_chunk_start = -1;
+    int last_chunk_end = -1;
+    uint32 last_chunk_mask = 0;
+    for (; i < optimized_order_.size(); i++) {
+      const FieldDescriptor* field = optimized_order_[i];
+      if (field->is_repeated()) {
+        break;
+      }
+
+      // "index" defines where in the _has_bits_ the field appears.
+      // "i" is our loop counter within optimized_order_.
+      int index = HasFieldPresence(descriptor_->file()) ?
+          has_bit_indices_[field->index()] : 0;
+      int chunk = index / 8;
+
+      if (last_chunk == -1) {
+        last_chunk = chunk;
+        last_chunk_start = i;
+      } else if (chunk != last_chunk) {
+        // Emit the fields for this chunk so far.
+        break;
+      }
+
+      last_chunk_end = i;
+      last_chunk_mask |= static_cast<uint32>(1) << (index % 32);
+    }
+
+    if (last_chunk != -1) {
+      GOOGLE_DCHECK_NE(-1, last_chunk_start);
+      GOOGLE_DCHECK_NE(-1, last_chunk_end);
+      GOOGLE_DCHECK_NE(0, last_chunk_mask);
+
+      const int count = popcnt(last_chunk_mask);
+      const bool have_outer_if = HasFieldPresence(descriptor_->file()) &&
+          (last_chunk_start != last_chunk_end);
+
+      if (have_outer_if) {
+        // Check (up to) 8 has_bits at a time if we have more than one field in
+        // this chunk.  Due to field layout ordering, we may check
+        // _has_bits_[last_chunk * 8 / 32] multiple times.
+        GOOGLE_DCHECK_LE(2, count);
+        GOOGLE_DCHECK_GE(8, count);
+
+        if (cached_has_bit_index != last_chunk / 4) {
+          int new_index = last_chunk / 4;
+          printer->Print("cached_has_bits = from._has_bits_[$new_index$];\n",
+                         "new_index", SimpleItoa(new_index));
+          cached_has_bit_index = new_index;
+        }
+
+        printer->Print(
+          "if (cached_has_bits & $mask$u) {\n",
+          "mask", SimpleItoa(last_chunk_mask));
+        printer->Indent();
+      }
+
+      // Go back and emit clears for each of the fields we processed.
+      bool deferred_has_bit_changes = false;
+      for (int j = last_chunk_start; j <= last_chunk_end; j++) {
+        const FieldDescriptor* field = optimized_order_[j];
+        const FieldGenerator& generator = field_generators_.get(field);
+
+        bool have_enclosing_if = false;
+        if (HasFieldPresence(descriptor_->file())) {
+          // Attempt to use the state of cached_has_bits, if possible.
+          int has_bit_index = has_bit_indices_[field->index()];
+          if (!field->options().weak() &&
+              cached_has_bit_index == has_bit_index / 32) {
+            const string mask = StrCat(
+                strings::Hex(1u << (has_bit_index % 32),
+                strings::ZERO_PAD_8));
+
+            printer->Print(
+                "if (cached_has_bits & 0x$mask$u) {\n", "mask", mask);
+          } else {
+            printer->Print(
+              "if (from.has_$name$()) {\n",
+              "name", FieldName(field));
+          }
+
+          printer->Indent();
+          have_enclosing_if = true;
+        } else {
+          // Merge semantics without true field presence: primitive fields are
+          // merged only if non-zero (numeric) or non-empty (string).
+          have_enclosing_if = EmitFieldNonDefaultCondition(
+              printer, "from.", field);
+        }
+
+        if (have_outer_if && IsPOD(field)) {
+          // GenerateCopyConstructorCode for enum and primitive scalar fields
+          // does not do _has_bits_ modifications.  We defer _has_bits_
+          // manipulation until the end of the outer if.
+          //
+          // This can reduce the number of loads/stores by up to 7 per 8 fields.
+          deferred_has_bit_changes = true;
+          generator.GenerateCopyConstructorCode(printer);
+        } else {
+          generator.GenerateMergingCode(printer);
+        }
+
+        if (have_enclosing_if) {
+          printer->Outdent();
+          printer->Print("}\n");
+        }
+      }
+
+      if (have_outer_if) {
+        if (deferred_has_bit_changes) {
+          // Flush the has bits for the primitives we deferred.
+          GOOGLE_CHECK_LE(0, cached_has_bit_index);
+          printer->Print(
+              "_has_bits_[$index$] |= cached_has_bits;\n",
+              "index", SimpleItoa(cached_has_bit_index));
+        }
+
+        printer->Outdent();
+        printer->Print("}\n");
+      }
     }
   }
 
@@ -2759,76 +3214,8 @@
     printer->Print(
         "}\n");
   }
-
-  // Merge Optional and Required fields (after a _has_bit check).
-  int last_index = -1;
-
-  for (int i = 0; i < descriptor_->field_count(); ++i) {
-    const FieldDescriptor* field = descriptor_->field(i);
-
-    if (!field->is_repeated() && !field->containing_oneof()) {
-      if (HasFieldPresence(descriptor_->file())) {
-        // 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(
-            "if (from._has_bits_[$index$ / 32] & "
-            "(0xffu << ($index$ % 32))) {\n",
-            "index", SimpleItoa(field->index()));
-          printer->Indent();
-        }
-      }
-
-      last_index = i;
-
-      bool have_enclosing_if = false;
-      if (HasFieldPresence(descriptor_->file())) {
-        printer->Print(
-          "if (from.has_$name$()) {\n",
-          "name", FieldName(field));
-        printer->Indent();
-        have_enclosing_if = true;
-      } else {
-        // Merge semantics without true field presence: primitive fields are
-        // merged only if non-zero (numeric) or non-empty (string).
-        have_enclosing_if = EmitFieldNonDefaultCondition(
-            printer, "from.", field);
-      }
-
-      field_generators_.get(field).GenerateMergingCode(printer);
-
-      if (have_enclosing_if) {
-        printer->Outdent();
-        printer->Print("}\n");
-      }
-    }
-  }
-
-  if (HasFieldPresence(descriptor_->file()) &&
-      last_index >= 0) {
-    printer->Outdent();
-    printer->Print("}\n");
-  }
-
-  if (descriptor_->extension_range_count() > 0) {
-    printer->Print("_extensions_.MergeFrom(from._extensions_);\n");
-  }
-
-  if (PreserveUnknownFields(descriptor_)) {
-    if (UseUnknownFieldSet(descriptor_->file())) {
-      printer->Print(
-        "if (from._internal_metadata_.have_unknown_fields()) {\n"
-        "  mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n"
-        "}\n");
-    } else {
-      printer->Print(
-        "if (!from.unknown_fields().empty()) {\n"
-        "  mutable_unknown_fields()->append(from.unknown_fields());\n"
-        "}\n");
-    }
+  if (num_weak_fields_) {
+    printer->Print("_weak_field_map_.MergeFrom(from._weak_field_map_);\n");
   }
 
   printer->Outdent();
@@ -2837,12 +3224,14 @@
 
 void MessageGenerator::
 GenerateCopyFrom(io::Printer* printer) {
-  if (HasDescriptorMethods(descriptor_->file())) {
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
     // Generate the generalized CopyFrom (aka that which takes in the Message
     // base class as a parameter).
     printer->Print(
-      "void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n",
-      "classname", classname_);
+        "void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n"
+        "// @@protoc_insertion_point(generalized_copy_from_start:"
+        "$full_name$)\n",
+        "classname", classname_, "full_name", descriptor_->full_name());
     printer->Indent();
 
     printer->Print(
@@ -2856,8 +3245,10 @@
 
   // Generate the class-specific CopyFrom.
   printer->Print(
-    "void $classname$::CopyFrom(const $classname$& from) {\n",
-    "classname", classname_);
+      "void $classname$::CopyFrom(const $classname$& from) {\n"
+      "// @@protoc_insertion_point(class_specific_copy_from_start:"
+      "$full_name$)\n",
+      "classname", classname_, "full_name", descriptor_->full_name());
   printer->Indent();
 
   printer->Print(
@@ -2871,47 +3262,74 @@
 
 void MessageGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) {
+  std::map<string, string> vars;
+  SetUnknkownFieldsVariable(descriptor_, options_, &vars);
   if (descriptor_->options().message_set_wire_format()) {
     // Special-case MessageSet.
-    printer->Print(
+    vars["classname"] = classname_;
+    printer->Print(vars,
       "bool $classname$::MergePartialFromCodedStream(\n"
-      "    ::google::protobuf::io::CodedInputStream* input) {\n",
-      "classname", classname_);
-
-    PrintHandlingOptionalStaticInitializers(
-      descriptor_->file(), printer,
-      // With static initializers.
-      "  return _extensions_.ParseMessageSet(input, default_instance_,\n"
-      "                                      mutable_unknown_fields());\n",
-      // Without.
-      "  return _extensions_.ParseMessageSet(input, &default_instance(),\n"
-      "                                      mutable_unknown_fields());\n",
-      // Vars.
-      "classname", classname_);
-
-    printer->Print(
+      "    ::google::protobuf::io::CodedInputStream* input) {\n"
+      "  return _extensions_.ParseMessageSet(input,\n"
+      "      internal_default_instance(), $mutable_unknown_fields$);\n"
       "}\n");
     return;
   }
+  std::vector<const FieldDescriptor*> ordered_fields =
+      SortFieldsByNumber(descriptor_);
 
   printer->Print(
     "bool $classname$::MergePartialFromCodedStream(\n"
-    "    ::google::protobuf::io::CodedInputStream* input) {\n"
-    "#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure\n"
-    "  ::google::protobuf::uint32 tag;\n",
+    "    ::google::protobuf::io::CodedInputStream* input) {\n",
     "classname", classname_);
 
-  if (!UseUnknownFieldSet(descriptor_->file())) {
-    // Use LazyStringOutputString to avoid initializing unknown fields string
-    // unless it is actually needed. For the same reason, disable eager refresh
-    // on the CodedOutputStream.
+  if (table_driven_) {
+    printer->Indent();
+
+    const string lite = UseUnknownFieldSet(descriptor_->file(), options_) ?
+        "" : "Lite";
+
     printer->Print(
-      "  ::google::protobuf::io::LazyStringOutputStream unknown_fields_string(\n"
-      "      ::google::protobuf::internal::NewPermanentCallback(\n"
-      "          &MutableUnknownFieldsFor$classname$, this));\n"
-      "  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n"
-      "      &unknown_fields_string, false);\n",
-      "classname", classname_);
+        "return ::google::protobuf::internal::MergePartialFromCodedStream$lite$(\n"
+        "    this,\n"
+        "    ::$file_namespace$::TableStruct::schema[\n"
+        "      $classname$::kIndexInFileMessages],\n"
+        "    input);\n",
+        "classname", classname_, "file_namespace",
+        FileLevelNamespace(descriptor_), "lite", lite);
+
+    printer->Outdent();
+
+    printer->Print("}\n");
+    return;
+  }
+
+  if (SupportsArenas(descriptor_)) {
+    for (int i = 0; i < ordered_fields.size(); i++) {
+      const FieldDescriptor* field = ordered_fields[i];
+      const FieldGenerator& field_generator = field_generators_.get(field);
+      if (field_generator.MergeFromCodedStreamNeedsArena()) {
+        printer->Print(
+          "  ::google::protobuf::Arena* arena = GetArenaNoVirtual();\n");
+        break;
+      }
+    }
+  }
+
+  printer->Print(
+      "#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto "
+      "failure\n"
+      "  ::google::protobuf::uint32 tag;\n");
+
+  if (!UseUnknownFieldSet(descriptor_->file(), options_)) {
+    printer->Print(
+        "  ::google::protobuf::internal::LiteUnknownFieldSetter unknown_fields_setter(\n"
+        "      &_internal_metadata_);\n"
+        "  ::google::protobuf::io::StringOutputStream unknown_fields_output(\n"
+        "      unknown_fields_setter.buffer());\n"
+        "  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n"
+        "      &unknown_fields_output, false);\n",
+        "classname", classname_);
   }
 
   printer->Print(
@@ -2922,19 +3340,57 @@
   printer->Print("for (;;) {\n");
   printer->Indent();
 
-  google::protobuf::scoped_array<const FieldDescriptor * > ordered_fields(
-      SortFieldsByNumber(descriptor_));
-  uint32 maxtag = descriptor_->field_count() == 0 ? 0 :
-      WireFormat::MakeTag(ordered_fields[descriptor_->field_count() - 1]);
+  // To calculate the maximum tag to expect, we look at the highest-numbered
+  // field. We need to be prepared to handle more than one wire type if that
+  // field is a packable repeated field, so to simplify things we assume the
+  // highest possible wire type of 5.
+  uint32 maxtag =
+      ordered_fields.empty() ? 0 : ordered_fields.back()->number() * 8 + 5;
   const int kCutoff0 = 127;               // fits in 1-byte varint
   const int kCutoff1 = (127 << 7) + 127;  // fits in 2-byte varint
-  printer->Print("::std::pair< ::google::protobuf::uint32, bool> p = "
-                 "input->ReadTagWithCutoff($max$);\n"
+
+  // We need to capture the last tag when parsing if this is a Group type, as
+  // our caller will verify (via CodedInputStream::LastTagWas) that the correct
+  // closing tag was received.
+  bool capture_last_tag = false;
+  const Descriptor* parent = descriptor_->containing_type();
+  if (parent) {
+    for (int i = 0; i < parent->field_count(); i++) {
+      const FieldDescriptor* field = parent->field(i);
+      if (field->type() == FieldDescriptor::TYPE_GROUP &&
+          field->message_type() == descriptor_) {
+        capture_last_tag = true;
+        break;
+      }
+    }
+
+    for (int i = 0; i < parent->extension_count(); i++) {
+      const FieldDescriptor* field = parent->extension(i);
+      if (field->type() == FieldDescriptor::TYPE_GROUP &&
+          field->message_type() == descriptor_) {
+        capture_last_tag = true;
+        break;
+      }
+    }
+  }
+
+  for (int i = 0; i < descriptor_->file()->extension_count(); i++) {
+    const FieldDescriptor* field = descriptor_->file()->extension(i);
+    if (field->type() == FieldDescriptor::TYPE_GROUP &&
+        field->message_type() == descriptor_) {
+      capture_last_tag = true;
+      break;
+    }
+  }
+
+  printer->Print("::std::pair<::google::protobuf::uint32, bool> p = "
+                 "input->ReadTagWithCutoffNoLastTag($max$u);\n"
                  "tag = p.first;\n"
                  "if (!p.second) goto handle_unusual;\n",
                  "max", SimpleItoa(maxtag <= kCutoff0 ? kCutoff0 :
                                    (maxtag <= kCutoff1 ? kCutoff1 :
                                     maxtag)));
+
   if (descriptor_->field_count() > 0) {
     // We don't even want to print the switch() if we have no fields because
     // MSVC dislikes switch() statements that contain only a default value.
@@ -2944,29 +3400,20 @@
     // of each case.  However, this is actually a bit slower in practice as it
     // creates a jump table that is 8x larger and sparser, and meanwhile the
     // if()s are highly predictable.
+    //
+    // Historically, we inserted checks to peek at the next tag on the wire and
+    // jump directly to the next case statement.  While this avoids the jump
+    // table that the switch uses, it greatly increases code size (20-60%) and
+    // inserts branches that may fail (especially for real world protos that
+    // interleave--in field number order--hot and cold fields).  Loadtests
+    // confirmed that removing this optimization is performance neutral.
     printer->Print("switch (::google::protobuf::internal::WireFormatLite::"
                    "GetTagFieldNumber(tag)) {\n");
 
     printer->Indent();
 
-    // Find repeated messages and groups now, to simplify what follows.
-    hash_set<int> fields_with_parse_loop;
-    for (int i = 0; i < descriptor_->field_count(); i++) {
+    for (int i = 0; i < ordered_fields.size(); i++) {
       const FieldDescriptor* field = ordered_fields[i];
-      if (field->is_repeated() &&
-          (field->type() == FieldDescriptor::TYPE_MESSAGE ||
-           field->type() == FieldDescriptor::TYPE_GROUP)) {
-        fields_with_parse_loop.insert(i);
-      }
-    }
-
-    // need_label is true if we generated "goto parse_$name$" while handling the
-    // previous field.
-    bool need_label = false;
-    for (int i = 0; i < descriptor_->field_count(); i++) {
-      const FieldDescriptor* field = ordered_fields[i];
-      const bool loops = fields_with_parse_loop.count(i) > 0;
-      const bool next_field_loops = fields_with_parse_loop.count(i + 1) > 0;
 
       PrintFieldComment(printer, field);
 
@@ -2977,21 +3424,11 @@
       const FieldGenerator& field_generator = field_generators_.get(field);
 
       // Emit code to parse the common, expected case.
-      printer->Print("if (tag == $commontag$) {\n",
-                     "commontag", SimpleItoa(WireFormat::MakeTag(field)));
-
-      if (need_label ||
-          (field->is_repeated() && !field->is_packed() && !loops)) {
-        printer->Print(
-            " parse_$name$:\n",
-            "name", field->name());
-      }
-      if (loops) {
-        printer->Print(
-          "  DO_(input->IncrementRecursionDepth());\n"
-          " parse_loop_$name$:\n",
-          "name", field->name());
-      }
+      printer->Print(
+        "if (static_cast< ::google::protobuf::uint8>(tag) ==\n"
+        "    static_cast< ::google::protobuf::uint8>($truncated$u /* $full$ & 0xFF */)) {\n",
+        "truncated", SimpleItoa(WireFormat::MakeTag(field) & 0xFF),
+        "full", SimpleItoa(WireFormat::MakeTag(field)));
 
       printer->Indent();
       if (field->is_packed()) {
@@ -3005,20 +3442,30 @@
       if (field->is_packed()) {
         internal::WireFormatLite::WireType wiretype =
             WireFormat::WireTypeForFieldType(field->type());
-        printer->Print("} else if (tag == $uncommontag$) {\n",
-                       "uncommontag", SimpleItoa(
-                           internal::WireFormatLite::MakeTag(
-                               field->number(), wiretype)));
+        const uint32 tag = internal::WireFormatLite::MakeTag(
+            field->number(), wiretype);
+        printer->Print(
+            "} else if (\n"
+            "    static_cast< ::google::protobuf::uint8>(tag) ==\n"
+            "    static_cast< ::google::protobuf::uint8>($truncated$u /* $full$ & 0xFF */)) {\n",
+            "truncated", SimpleItoa(tag & 0xFF),
+            "full", SimpleItoa(tag));
+
         printer->Indent();
         field_generator.GenerateMergeFromCodedStream(printer);
         printer->Outdent();
       } else if (field->is_packable() && !field->is_packed()) {
         internal::WireFormatLite::WireType wiretype =
             internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
-        printer->Print("} else if (tag == $uncommontag$) {\n",
-                       "uncommontag", SimpleItoa(
-                           internal::WireFormatLite::MakeTag(
-                               field->number(), wiretype)));
+         const uint32 tag = internal::WireFormatLite::MakeTag(
+            field->number(), wiretype);
+
+        printer->Print(
+            "} else if (\n"
+            "    static_cast< ::google::protobuf::uint8>(tag) ==\n"
+            "    static_cast< ::google::protobuf::uint8>($truncated$u /* $full$ & 0xFF */)) {\n",
+            "truncated", SimpleItoa(tag & 0xFF),
+            "full", SimpleItoa(tag));
         printer->Indent();
         field_generator.GenerateMergeFromCodedStreamWithPacking(printer);
         printer->Outdent();
@@ -3029,64 +3476,12 @@
         "  goto handle_unusual;\n"
         "}\n");
 
-      // switch() is slow since it can't be predicted well.  Insert some if()s
-      // here that attempt to predict the next tag.
-      // For non-packed repeated fields, expect the same tag again.
-      if (loops) {
-        printer->Print(
-          "if (input->ExpectTag($tag$)) goto parse_loop_$name$;\n",
-          "tag", SimpleItoa(WireFormat::MakeTag(field)),
-          "name", field->name());
-      } else if (field->is_repeated() && !field->is_packed()) {
-        printer->Print(
-          "if (input->ExpectTag($tag$)) goto parse_$name$;\n",
-          "tag", SimpleItoa(WireFormat::MakeTag(field)),
-          "name", field->name());
-      }
-
-      // Have we emitted "if (input->ExpectTag($next_tag$)) ..." yet?
-      bool emitted_goto_next_tag = false;
-
-      // For repeated messages/groups, we need to decrement recursion depth,
-      // unless the next tag is also for a repeated message/group.
-      if (loops) {
-        if (next_field_loops) {
-          const FieldDescriptor* next_field = ordered_fields[i + 1];
-          printer->Print(
-            "if (input->ExpectTag($next_tag$)) goto parse_loop_$next_name$;\n",
-            "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)),
-            "next_name", next_field->name());
-          emitted_goto_next_tag = true;
-        }
-        printer->Print(
-          "input->UnsafeDecrementRecursionDepth();\n");
-      }
-
-      // If there are more fields, expect the next one.
-      need_label = false;
-      if (!emitted_goto_next_tag) {
-        if (i + 1 == descriptor_->field_count()) {
-          // Expect EOF.
-          // TODO(kenton):  Expect group end-tag?
-          printer->Print(
-            "if (input->ExpectAtEnd()) goto success;\n");
-        } else {
-          const FieldDescriptor* next_field = ordered_fields[i + 1];
-          printer->Print(
-            "if (input->ExpectTag($next_tag$)) goto parse_$next_name$;\n",
-            "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)),
-            "next_name", next_field->name());
-          need_label = true;
-        }
-      }
-
       printer->Print(
         "break;\n");
 
       printer->Outdent();
       printer->Print("}\n\n");
     }
-
     printer->Print("default: {\n");
     printer->Indent();
   }
@@ -3095,12 +3490,20 @@
   printer->Print("handle_unusual:\n");
   printer->Indent();
   // If tag is 0 or an end-group tag then this must be the end of the message.
-  printer->Print(
-    "if (tag == 0 ||\n"
-    "    ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n"
-    "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n"
-    "  goto success;\n"
-    "}\n");
+  if (capture_last_tag) {
+    printer->Print(
+      "if (tag == 0 ||\n"
+      "    ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n"
+      "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n"
+      "  input->SetLastTag(tag);\n"
+      "  goto success;\n"
+      "}\n");
+  } else {
+    printer->Print(
+      "if (tag == 0) {\n"
+      "  goto success;\n"
+      "}\n");
+  }
 
   // Handle extension ranges.
   if (descriptor_->extension_range_count() > 0) {
@@ -3128,33 +3531,16 @@
       }
     }
     printer->Print(") {\n");
-    if (PreserveUnknownFields(descriptor_)) {
-      if (UseUnknownFieldSet(descriptor_->file())) {
-        PrintHandlingOptionalStaticInitializers(
-          descriptor_->file(), printer,
-          // With static initializers.
-          "  DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
-          "                              mutable_unknown_fields()));\n",
-          // Without.
-          "  DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
-          "                              mutable_unknown_fields()));\n");
-      } else {
-        PrintHandlingOptionalStaticInitializers(
-          descriptor_->file(), printer,
-          // With static initializers.
-          "  DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
-          "                              &unknown_fields_stream));\n",
-          // Without.
-          "  DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
-          "                              &unknown_fields_stream));\n");
-      }
+    if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+      printer->Print(vars,
+        "  DO_(_extensions_.ParseField(tag, input,\n"
+        "      internal_default_instance(),\n"
+        "      $mutable_unknown_fields$));\n");
     } else {
-      PrintHandlingOptionalStaticInitializers(
-        descriptor_->file(), printer,
-        // With static initializers.
-        "  DO_(_extensions_.ParseField(tag, input, default_instance_);\n",
-        // Without.
-        "  DO_(_extensions_.ParseField(tag, input, &default_instance());\n");
+      printer->Print(
+        "  DO_(_extensions_.ParseField(tag, input,\n"
+        "      internal_default_instance(),\n"
+        "      &unknown_fields_stream));\n");
     }
     printer->Print(
       "  continue;\n"
@@ -3162,19 +3548,14 @@
   }
 
   // We really don't recognize this tag.  Skip it.
-  if (PreserveUnknownFields(descriptor_)) {
-    if (UseUnknownFieldSet(descriptor_->file())) {
-      printer->Print(
+  if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+    printer->Print(vars,
         "DO_(::google::protobuf::internal::WireFormat::SkipField(\n"
-        "      input, tag, mutable_unknown_fields()));\n");
-    } else {
-      printer->Print(
-        "DO_(::google::protobuf::internal::WireFormatLite::SkipField(\n"
-        "    input, tag, &unknown_fields_stream));\n");
-    }
+        "      input, tag, $mutable_unknown_fields$));\n");
   } else {
     printer->Print(
-      "DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));\n");
+        "DO_(::google::protobuf::internal::WireFormatLite::SkipField(\n"
+        "    input, tag, &unknown_fields_stream));\n");
   }
 
   if (descriptor_->field_count() > 0) {
@@ -3199,15 +3580,69 @@
     "}\n", "full_name", descriptor_->full_name());
 }
 
+void MessageGenerator::GenerateSerializeOneofFields(
+    io::Printer* printer, const std::vector<const FieldDescriptor*>& fields,
+    bool to_array) {
+  GOOGLE_CHECK(!fields.empty());
+  if (fields.size() == 1) {
+    GenerateSerializeOneField(printer, fields[0], to_array, -1);
+    return;
+  }
+  // We have multiple mutually exclusive choices.  Emit a switch statement.
+  const OneofDescriptor* oneof = fields[0]->containing_oneof();
+  printer->Print(
+    "switch ($oneofname$_case()) {\n",
+    "oneofname", oneof->name());
+  printer->Indent();
+  for (int i = 0; i < fields.size(); i++) {
+    const FieldDescriptor* field = fields[i];
+    printer->Print(
+      "case k$field_name$:\n",
+      "field_name", UnderscoresToCamelCase(field->name(), true));
+    printer->Indent();
+    if (to_array) {
+      field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(
+          printer);
+    } else {
+      field_generators_.get(field).GenerateSerializeWithCachedSizes(printer);
+    }
+    printer->Print(
+      "break;\n");
+    printer->Outdent();
+  }
+  printer->Outdent();
+  // Doing nothing is an option.
+  printer->Print(
+    "  default: ;\n"
+    "}\n");
+}
+
 void MessageGenerator::GenerateSerializeOneField(
-    io::Printer* printer, const FieldDescriptor* field, bool to_array) {
-  PrintFieldComment(printer, field);
+    io::Printer* printer, const FieldDescriptor* field, bool to_array,
+    int cached_has_bits_index) {
+  if (!field->options().weak()) {
+    // For weakfields, PrintFieldComment is called during iteration.
+    PrintFieldComment(printer, field);
+  }
 
   bool have_enclosing_if = false;
-  if (!field->is_repeated() && HasFieldPresence(descriptor_->file())) {
-    printer->Print(
-      "if (has_$name$()) {\n",
-      "name", FieldName(field));
+  if (field->options().weak()) {
+  } else if (!field->is_repeated() && HasFieldPresence(descriptor_->file())) {
+    // Attempt to use the state of cached_has_bits, if possible.
+    int has_bit_index = has_bit_indices_[field->index()];
+    if (cached_has_bits_index == has_bit_index / 32) {
+      const string mask = StrCat(
+          strings::Hex(1u << (has_bit_index % 32),
+          strings::ZERO_PAD_8));
+
+      printer->Print(
+          "if (cached_has_bits & 0x$mask$u) {\n", "mask", mask);
+    } else {
+      printer->Print(
+        "if (has_$name$()) {\n",
+        "name", FieldName(field));
+    }
+
     printer->Indent();
     have_enclosing_if = true;
   } else if (!HasFieldPresence(descriptor_->file())) {
@@ -3231,15 +3666,15 @@
 void MessageGenerator::GenerateSerializeOneExtensionRange(
     io::Printer* printer, const Descriptor::ExtensionRange* range,
     bool to_array) {
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["start"] = SimpleItoa(range->start);
   vars["end"] = SimpleItoa(range->end);
   printer->Print(vars,
     "// Extension range [$start$, $end$)\n");
   if (to_array) {
     printer->Print(vars,
-      "target = _extensions_.SerializeWithCachedSizesToArray(\n"
-      "    $start$, $end$, target);\n\n");
+      "target = _extensions_.InternalSerializeWithCachedSizesToArray(\n"
+      "    $start$, $end$, deterministic, target);\n\n");
   } else {
     printer->Print(vars,
       "_extensions_.SerializeWithCachedSizes(\n"
@@ -3256,14 +3691,17 @@
       "    ::google::protobuf::io::CodedOutputStream* output) const {\n"
       "  _extensions_.SerializeMessageSetWithCachedSizes(output);\n",
       "classname", classname_);
-    GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file()));
-    printer->Print(
+    GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_));
+    std::map<string, string> vars;
+    SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+    printer->Print(vars,
       "  ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n"
-      "      unknown_fields(), output);\n");
+      "      $unknown_fields$, output);\n");
     printer->Print(
       "}\n");
     return;
   }
+  if (options_.table_driven_serialization) return;
 
   printer->Print(
     "void $classname$::SerializeWithCachedSizes(\n"
@@ -3291,16 +3729,19 @@
   if (descriptor_->options().message_set_wire_format()) {
     // Special-case MessageSet.
     printer->Print(
-      "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n"
-      "    ::google::protobuf::uint8* target) const {\n"
-      "  target =\n"
-      "      _extensions_.SerializeMessageSetWithCachedSizesToArray(target);\n",
+      "::google::protobuf::uint8* $classname$::InternalSerializeWithCachedSizesToArray(\n"
+      "    bool deterministic, ::google::protobuf::uint8* target) const {\n"
+      "  target = _extensions_."
+      "InternalSerializeMessageSetWithCachedSizesToArray(\n"
+      "               deterministic, target);\n",
       "classname", classname_);
-    GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file()));
-    printer->Print(
+    GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_));
+    std::map<string, string> vars;
+    SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+    printer->Print(vars,
       "  target = ::google::protobuf::internal::WireFormat::\n"
       "             SerializeUnknownMessageSetItemsToArray(\n"
-      "               unknown_fields(), target);\n");
+      "               $unknown_fields$, target);\n");
     printer->Print(
       "  return target;\n"
       "}\n");
@@ -3308,11 +3749,12 @@
   }
 
   printer->Print(
-    "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n"
-    "    ::google::protobuf::uint8* target) const {\n",
+    "::google::protobuf::uint8* $classname$::InternalSerializeWithCachedSizesToArray(\n"
+    "    bool deterministic, ::google::protobuf::uint8* target) const {\n",
     "classname", classname_);
   printer->Indent();
 
+  printer->Print("(void)deterministic; // Unused\n");
   printer->Print(
     "// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n",
     "full_name", descriptor_->full_name());
@@ -3331,86 +3773,188 @@
 
 void MessageGenerator::
 GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
-  google::protobuf::scoped_array<const FieldDescriptor * > ordered_fields(
-      SortFieldsByNumber(descriptor_));
+  // If there are multiple fields in a row from the same oneof then we
+  // coalesce them and emit a switch statement.  This is more efficient
+  // because it lets the C++ compiler know this is a "at most one can happen"
+  // situation. If we emitted "if (has_x()) ...; if (has_y()) ..." the C++
+  // compiler's emitted code might check has_y() even when has_x() is true.
+  class LazySerializerEmitter {
+   public:
+    LazySerializerEmitter(MessageGenerator* mg, io::Printer* printer,
+                          bool to_array)
+        : mg_(mg),
+          printer_(printer),
+          to_array_(to_array),
+          eager_(!HasFieldPresence(mg->descriptor_->file())),
+          cached_has_bit_index_(-1) {}
 
-  vector<const Descriptor::ExtensionRange*> sorted_extensions;
+    ~LazySerializerEmitter() { Flush(); }
+
+    // If conditions allow, try to accumulate a run of fields from the same
+    // oneof, and handle them at the next Flush().
+    void Emit(const FieldDescriptor* field) {
+      if (eager_ || MustFlush(field)) {
+        Flush();
+      }
+      if (field->containing_oneof() == NULL) {
+        // TODO(ckennelly): Defer non-oneof fields similarly to oneof fields.
+
+        if (!field->options().weak() && !field->is_repeated() && !eager_) {
+          // We speculatively load the entire _has_bits_[index] contents, even
+          // if it is for only one field.  Deferring non-oneof emitting would
+          // allow us to determine whether this is going to be useful.
+          int has_bit_index = mg_->has_bit_indices_[field->index()];
+          if (cached_has_bit_index_ != has_bit_index / 32) {
+            // Reload.
+            int new_index = has_bit_index / 32;
+
+            printer_->Print(
+                "cached_has_bits = _has_bits_[$new_index$];\n",
+                "new_index", SimpleItoa(new_index));
+
+            cached_has_bit_index_ = new_index;
+          }
+        }
+
+        mg_->GenerateSerializeOneField(
+            printer_, field, to_array_, cached_has_bit_index_);
+      } else {
+        v_.push_back(field);
+      }
+    }
+
+    void Flush() {
+      if (!v_.empty()) {
+        mg_->GenerateSerializeOneofFields(printer_, v_, to_array_);
+        v_.clear();
+      }
+    }
+
+   private:
+    // If we have multiple fields in v_ then they all must be from the same
+    // oneof.  Would adding field to v_ break that invariant?
+    bool MustFlush(const FieldDescriptor* field) {
+      return !v_.empty() &&
+             v_[0]->containing_oneof() != field->containing_oneof();
+    }
+
+    MessageGenerator* mg_;
+    io::Printer* printer_;
+    const bool to_array_;
+    const bool eager_;
+    std::vector<const FieldDescriptor*> v_;
+
+    // cached_has_bit_index_ maintains that:
+    //   cached_has_bits = from._has_bits_[cached_has_bit_index_]
+    // for cached_has_bit_index_ >= 0
+    int cached_has_bit_index_;
+  };
+
+  std::vector<const FieldDescriptor*> ordered_fields =
+      SortFieldsByNumber(descriptor_);
+
+  std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
   for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
     sorted_extensions.push_back(descriptor_->extension_range(i));
   }
   std::sort(sorted_extensions.begin(), sorted_extensions.end(),
             ExtensionRangeSorter());
+  if (num_weak_fields_) {
+    printer->Print(
+        "::google::protobuf::internal::WeakFieldMap::FieldWriter field_writer("
+        "_weak_field_map_);\n");
+  }
+
+  printer->Print(
+      "::google::protobuf::uint32 cached_has_bits = 0;\n"
+      "(void) cached_has_bits;\n\n");
 
   // Merge the fields and the extension ranges, both sorted by field number.
-  int i, j;
-  for (i = 0, j = 0;
-       i < descriptor_->field_count() || j < sorted_extensions.size();
-       ) {
-    if (i == descriptor_->field_count()) {
-      GenerateSerializeOneExtensionRange(printer,
-                                         sorted_extensions[j++],
-                                         to_array);
-    } else if (j == sorted_extensions.size()) {
-      GenerateSerializeOneField(printer, ordered_fields[i++], to_array);
-    } else if (ordered_fields[i]->number() < sorted_extensions[j]->start) {
-      GenerateSerializeOneField(printer, ordered_fields[i++], to_array);
-    } else {
-      GenerateSerializeOneExtensionRange(printer,
-                                         sorted_extensions[j++],
-                                         to_array);
+  {
+    LazySerializerEmitter e(this, printer, to_array);
+    const FieldDescriptor* last_weak_field = nullptr;
+    int i, j;
+    for (i = 0, j = 0;
+         i < ordered_fields.size() || j < sorted_extensions.size();) {
+      if ((j == sorted_extensions.size()) ||
+          (i < descriptor_->field_count() &&
+           ordered_fields[i]->number() < sorted_extensions[j]->start)) {
+        const FieldDescriptor* field = ordered_fields[i++];
+        if (field->options().weak()) {
+          last_weak_field = field;
+          PrintFieldComment(printer, field);
+        } else {
+          if (last_weak_field != nullptr) {
+            e.Emit(last_weak_field);
+            last_weak_field = nullptr;
+          }
+          e.Emit(field);
+        }
+      } else  {
+        if (last_weak_field != nullptr) {
+          e.Emit(last_weak_field);
+          last_weak_field = nullptr;
+        }
+        e.Flush();
+        GenerateSerializeOneExtensionRange(printer,
+                                           sorted_extensions[j++],
+                                           to_array);
+      }
+    }
+    if (last_weak_field != nullptr) {
+      e.Emit(last_weak_field);
     }
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    if (UseUnknownFieldSet(descriptor_->file())) {
-      printer->Print("if (_internal_metadata_.have_unknown_fields()) {\n");
-      printer->Indent();
-      if (to_array) {
-        printer->Print(
-          "target = "
-              "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n"
-          "    unknown_fields(), target);\n");
-      } else {
-        printer->Print(
-          "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n"
-          "    unknown_fields(), output);\n");
-      }
-      printer->Outdent();
-
-      printer->Print(
-        "}\n");
+  std::map<string, string> vars;
+  SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+  if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+    printer->Print(vars,
+      "if ($have_unknown_fields$) {\n");
+    printer->Indent();
+    if (to_array) {
+      printer->Print(vars,
+        "target = "
+        "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n"
+        "    $unknown_fields$, target);\n");
     } else {
-      printer->Print(
-        "output->WriteRaw(unknown_fields().data(),\n"
-        "                 static_cast<int>(unknown_fields().size()));\n");
+      printer->Print(vars,
+        "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n"
+        "    $unknown_fields$, output);\n");
     }
+    printer->Outdent();
+
+    printer->Print("}\n");
+  } else {
+    printer->Print(vars,
+      "output->WriteRaw($unknown_fields$.data(),\n"
+      "                 static_cast<int>($unknown_fields$.size()));\n");
   }
 }
 
-static vector<uint32> RequiredFieldsBitMask(const Descriptor* desc) {
-  vector<uint32> result;
-  uint32 mask = 0;
-  for (int i = 0; i < desc->field_count(); i++) {
-    if (i > 0 && i % 32 == 0) {
-      result.push_back(mask);
-      mask = 0;
+std::vector<uint32> MessageGenerator::RequiredFieldsBitMask() const {
+  const int array_size = HasBitsSize();
+  std::vector<uint32> masks(array_size, 0);
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    if (!field->is_required()) {
+      continue;
     }
-    if (desc->field(i)->is_required()) {
-      mask |= (1 << (i & 31));
-    }
+
+    const int has_bit_index = has_bit_indices_[field->index()];
+    masks[has_bit_index / 32] |=
+        static_cast<uint32>(1) << (has_bit_index % 32);
   }
-  if (mask != 0) {
-    result.push_back(mask);
-  }
-  return result;
+  return masks;
 }
 
 // Create an expression that evaluates to
 //  "for all i, (_has_bits_[i] & masks[i]) == masks[i]"
 // masks is allowed to be shorter than _has_bits_, but at least one element of
 // masks must be non-zero.
-static string ConditionalToCheckBitmasks(const vector<uint32>& masks) {
-  vector<string> parts;
+static string ConditionalToCheckBitmasks(const std::vector<uint32>& masks) {
+  std::vector<string> parts;
   for (int i = 0; i < masks.size(); i++) {
     if (masks[i] == 0) continue;
     string m = StrCat("0x", strings::Hex(masks[i], strings::ZERO_PAD_8));
@@ -3419,8 +3963,9 @@
   }
   GOOGLE_CHECK(!parts.empty());
   // If we have multiple parts, each expected to be 0, then bitwise-or them.
-  string result = parts.size() == 1 ? parts[0] :
-      StrCat("(", Join(parts, "\n       | "), ")");
+  string result = parts.size() == 1
+                      ? parts[0]
+                      : StrCat("(", Join(parts, "\n       | "), ")");
   return result + " == 0";
 }
 
@@ -3428,22 +3973,24 @@
 GenerateByteSize(io::Printer* printer) {
   if (descriptor_->options().message_set_wire_format()) {
     // Special-case MessageSet.
+    GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_));
+    std::map<string, string> vars;
+    SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+    vars["classname"] = classname_;
+    vars["full_name"] = descriptor_->full_name();
     printer->Print(
-      "int $classname$::ByteSize() const {\n"
-      "  int total_size = _extensions_.MessageSetByteSize();\n",
-      "classname", classname_);
-    GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file()));
-    printer->Print(
-      "if (_internal_metadata_.have_unknown_fields()) {\n"
-      "  total_size += ::google::protobuf::internal::WireFormat::\n"
-      "      ComputeUnknownMessageSetItemsSize(unknown_fields());\n"
-      "}\n");
-    printer->Print(
-      "  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
-      "  _cached_size_ = total_size;\n"
-      "  GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
-      "  return total_size;\n"
-      "}\n");
+        vars,
+        "size_t $classname$::ByteSizeLong() const {\n"
+        "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n"
+        "  size_t total_size = _extensions_.MessageSetByteSize();\n"
+        "  if ($have_unknown_fields$) {\n"
+        "    total_size += ::google::protobuf::internal::WireFormat::\n"
+        "        ComputeUnknownMessageSetItemsSize($unknown_fields$);\n"
+        "  }\n"
+        "  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);\n"
+        "  SetCachedSize(cached_size);\n"
+        "  return total_size;\n"
+        "}\n");
     return;
   }
 
@@ -3451,12 +3998,14 @@
     // Emit a function (rarely used, we hope) that handles the required fields
     // by checking for each one individually.
     printer->Print(
-        "int $classname$::RequiredFieldsByteSizeFallback() const {\n",
-        "classname", classname_);
+        "size_t $classname$::RequiredFieldsByteSizeFallback() const {\n"
+        "// @@protoc_insertion_point(required_fields_byte_size_fallback_start:"
+        "$full_name$)\n",
+        "classname", classname_, "full_name", descriptor_->full_name());
     printer->Indent();
-    printer->Print("int total_size = 0;\n");
-    for (int i = 0; i < descriptor_->field_count(); i++) {
-      const FieldDescriptor* field = descriptor_->field(i);
+    printer->Print("size_t total_size = 0;\n");
+    for (int i = 0; i < optimized_order_.size(); i++) {
+      const FieldDescriptor* field = optimized_order_[i];
       if (field->is_required()) {
         printer->Print("\n"
                        "if (has_$name$()) {\n",
@@ -3475,25 +4024,49 @@
   }
 
   printer->Print(
-    "int $classname$::ByteSize() const {\n",
-    "classname", classname_);
+      "size_t $classname$::ByteSizeLong() const {\n"
+      "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n",
+      "classname", classname_, "full_name", descriptor_->full_name());
   printer->Indent();
   printer->Print(
-    "int total_size = 0;\n"
+    "size_t total_size = 0;\n"
     "\n");
 
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(
+      "total_size += _extensions_.ByteSize();\n"
+      "\n");
+  }
+
+  std::map<string, string> vars;
+  SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+  if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+    printer->Print(vars,
+      "if ($have_unknown_fields$) {\n"
+      "  total_size +=\n"
+      "    ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n"
+      "      $unknown_fields$);\n"
+      "}\n");
+  } else {
+    printer->Print(vars,
+      "total_size += $unknown_fields$.size();\n"
+      "\n");
+  }
+
   // Handle required fields (if any).  We expect all of them to be
   // present, so emit one conditional that checks for that.  If they are all
   // present then the fast path executes; otherwise the slow path executes.
   if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) {
     // The fast path works if all required fields are present.
-    vector<uint32> masks_for_has_bits = RequiredFieldsBitMask(descriptor_);
+    const std::vector<uint32> masks_for_has_bits = RequiredFieldsBitMask();
     printer->Print((string("if (") +
                     ConditionalToCheckBitmasks(masks_for_has_bits) +
                     ") {  // All required fields are present.\n").c_str());
     printer->Indent();
-    for (int i = 0; i < descriptor_->field_count(); i++) {
-      const FieldDescriptor* field = descriptor_->field(i);
+    // Oneof fields cannot be required, so optimized_order_ contains all of the
+    // fields that we need to potentially emit.
+    for (int i = 0; i < optimized_order_.size(); i++) {
+      const FieldDescriptor* field = optimized_order_[i];
       if (!field->is_required()) continue;
       PrintFieldComment(printer, field);
       field_generators_.get(field).GenerateByteSize(printer);
@@ -3505,8 +4078,8 @@
                    "}\n");
   } else {
     // num_required_fields_ <= 1: no need to be tricky
-    for (int i = 0; i < descriptor_->field_count(); i++) {
-      const FieldDescriptor* field = descriptor_->field(i);
+    for (int i = 0; i < optimized_order_.size(); i++) {
+      const FieldDescriptor* field = optimized_order_[i];
       if (!field->is_required()) continue;
       PrintFieldComment(printer, field);
       printer->Print("if (has_$name$()) {\n",
@@ -3518,98 +4091,97 @@
     }
   }
 
-  // Handle optional fields (worry below about repeateds, oneofs, etc.).
-  // These are handled in chunks of 8.  The first chunk is
-  // the non-requireds-non-repeateds-non-unions-non-extensions in
-  //  descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7),
-  // and the second chunk is the same for
-  //  descriptor_->field(8), descriptor_->field(9), ... descriptor_->field(15),
-  // etc.
-  hash_map<int, uint32> fields_mask_for_chunk;
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = descriptor_->field(i);
-    if (!field->is_required() && !field->is_repeated() &&
-        !field->containing_oneof()) {
-      fields_mask_for_chunk[i / 8] |= static_cast<uint32>(1) << (i % 32);
-    }
-  }
+  std::vector<std::vector<const FieldDescriptor*> > chunks = CollectFields(
+      optimized_order_,
+      MatchRepeatedAndHasByteAndRequired(
+          &has_bit_indices_, HasFieldPresence(descriptor_->file())));
 
-  int last_index = -1;
-  bool chunk_block_in_progress = false;
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = descriptor_->field(i);
-    if (!field->is_required() && !field->is_repeated() &&
-        !field->containing_oneof()) {
-      // See above in GenerateClear for an explanation of this.
-      // TODO(kenton):  Share code?  Unclear how to do so without
-      //   over-engineering.
-      if (i / 8 != last_index / 8 || last_index < 0) {
-        // End previous chunk, if there was one.
-        if (chunk_block_in_progress) {
-          printer->Outdent();
-          printer->Print("}\n");
-          chunk_block_in_progress = false;
-        }
-        // Start chunk.
-        uint32 mask = fields_mask_for_chunk[i / 8];
-        int count = popcnt(mask);
-        GOOGLE_DCHECK_GE(count, 1);
-        if (count == 1) {
-          // No "if" here because the chunk is trivial.
-        } else {
-          if (HasFieldPresence(descriptor_->file())) {
-            printer->Print(
-              "if (_has_bits_[$index$ / 32] & $mask$u) {\n",
-              "index", SimpleItoa(i),
-              "mask", SimpleItoa(mask));
-            printer->Indent();
-            chunk_block_in_progress = true;
-          }
-        }
+  // Remove chunks with required fields.
+  chunks.erase(std::remove_if(chunks.begin(), chunks.end(), IsRequired),
+               chunks.end());
+
+  for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
+    const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
+    GOOGLE_CHECK(!chunk.empty());
+
+    // Handle repeated fields.
+    if (chunk.front()->is_repeated()) {
+      for (int i = 0; i < chunk.size(); i++) {
+        const FieldDescriptor* field = chunk[i];
+
+        PrintFieldComment(printer, field);
+        const FieldGenerator& generator = field_generators_.get(field);
+        generator.GenerateByteSize(printer);
+        printer->Print("\n");
       }
-      last_index = i;
+      continue;
+    }
+
+    // Handle optional (non-repeated/oneof) fields.
+    //
+    // These are handled in chunks of 8.  The first chunk is
+    // the non-requireds-non-repeateds-non-unions-non-extensions in
+    //  descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7),
+    // and the second chunk is the same for
+    //  descriptor_->field(8), descriptor_->field(9), ...
+    //  descriptor_->field(15),
+    // etc.
+    int last_chunk = HasFieldPresence(descriptor_->file())
+                         ? has_bit_indices_[chunk.front()->index()] / 8
+                         : 0;
+    GOOGLE_DCHECK_NE(-1, last_chunk);
+
+    const bool have_outer_if =
+        HasFieldPresence(descriptor_->file()) && chunk.size() > 1;
+
+    if (have_outer_if) {
+      uint32 last_chunk_mask = GenChunkMask(chunk, has_bit_indices_);
+      const int count = popcnt(last_chunk_mask);
+
+      // Check (up to) 8 has_bits at a time if we have more than one field in
+      // this chunk.  Due to field layout ordering, we may check
+      // _has_bits_[last_chunk * 8 / 32] multiple times.
+      GOOGLE_DCHECK_LE(2, count);
+      GOOGLE_DCHECK_GE(8, count);
+
+      printer->Print("if (_has_bits_[$index$ / 32] & $mask$u) {\n", "index",
+                     SimpleItoa(last_chunk * 8), "mask",
+                     SimpleItoa(last_chunk_mask));
+      printer->Indent();
+    }
+
+    // Go back and emit checks for each of the fields we processed.
+    for (int j = 0; j < chunk.size(); j++) {
+      const FieldDescriptor* field = chunk[j];
+      const FieldGenerator& generator = field_generators_.get(field);
 
       PrintFieldComment(printer, field);
 
       bool have_enclosing_if = false;
       if (HasFieldPresence(descriptor_->file())) {
-        printer->Print(
-          "if (has_$name$()) {\n",
-          "name", FieldName(field));
+        printer->Print("if (has_$name$()) {\n", "name", FieldName(field));
         printer->Indent();
         have_enclosing_if = true;
       } else {
         // Without field presence: field is serialized only if it has a
         // non-default value.
-        have_enclosing_if = EmitFieldNonDefaultCondition(
-            printer, "this->", field);
+        have_enclosing_if =
+            EmitFieldNonDefaultCondition(printer, "this->", field);
       }
 
-      field_generators_.get(field).GenerateByteSize(printer);
+      generator.GenerateByteSize(printer);
 
       if (have_enclosing_if) {
         printer->Outdent();
         printer->Print(
-          "}\n"
-          "\n");
+            "}\n"
+            "\n");
       }
     }
-  }
 
-  if (chunk_block_in_progress) {
-    printer->Outdent();
-    printer->Print("}\n");
-  }
-
-  // Repeated fields don't use _has_bits_ so we count them in a separate
-  // pass.
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = descriptor_->field(i);
-
-    if (field->is_repeated()) {
-      PrintFieldComment(printer, field);
-      field_generators_.get(field).GenerateByteSize(printer);
-      printer->Print("\n");
+    if (have_outer_if) {
+      printer->Outdent();
+      printer->Print("}\n");
     }
   }
 
@@ -3645,37 +4217,23 @@
         "}\n");
   }
 
-  if (descriptor_->extension_range_count() > 0) {
-    printer->Print(
-      "total_size += _extensions_.ByteSize();\n"
-      "\n");
+  if (num_weak_fields_) {
+    // TagSize + MessageSize
+    printer->Print("total_size += _weak_field_map_.ByteSizeLong();\n");
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    if (UseUnknownFieldSet(descriptor_->file())) {
-      printer->Print(
-        "if (_internal_metadata_.have_unknown_fields()) {\n"
-        "  total_size +=\n"
-        "    ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n"
-        "      unknown_fields());\n"
-        "}\n");
-    } else {
-      printer->Print(
-        "total_size += unknown_fields().size();\n"
-        "\n");
-    }
-  }
-
-  // We update _cached_size_ even though this is a const method.  In theory,
-  // this is not thread-compatible, because concurrent writes have undefined
-  // results.  In practice, since any concurrent writes will be writing the
-  // exact same value, it works on all common processors.  In a future version
-  // of C++, _cached_size_ should be made into an atomic<int>.
+  // We update _cached_size_ even though this is a const method.  Because
+  // const methods might be called concurrently this needs to be atomic
+  // operations or the program is undefined.  In practice, since any concurrent
+  // writes will be writing the exact same value, normal writes will work on
+  // all common processors. We use a dedicated wrapper class to abstract away
+  // the underlying atomic. This makes it easier on platforms where even relaxed
+  // memory order might have perf impact to replace it with ordinary loads and
+  // stores.
   printer->Print(
-    "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
-    "_cached_size_ = total_size;\n"
-    "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
-    "return total_size;\n");
+      "int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);\n"
+      "SetCachedSize(cached_size);\n"
+      "return total_size;\n");
 
   printer->Outdent();
   printer->Print("}\n");
@@ -3688,68 +4246,131 @@
     "classname", classname_);
   printer->Indent();
 
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(
+      "if (!_extensions_.IsInitialized()) {\n"
+      "  return false;\n"
+      "}\n\n");
+  }
+
   if (HasFieldPresence(descriptor_->file())) {
     // Check that all required fields in this message are set.  We can do this
     // most efficiently by checking 32 "has bits" at a time.
-    int has_bits_array_size = (descriptor_->field_count() + 31) / 32;
-    for (int i = 0; i < has_bits_array_size; i++) {
-      uint32 mask = 0;
-      for (int bit = 0; bit < 32; bit++) {
-        int index = i * 32 + bit;
-        if (index >= descriptor_->field_count()) break;
-        const FieldDescriptor* field = descriptor_->field(index);
+    const std::vector<uint32> masks = RequiredFieldsBitMask();
 
-        if (field->is_required()) {
-          mask |= 1 << bit;
-        }
+    for (int i = 0; i < masks.size(); i++) {
+      uint32 mask = masks[i];
+      if (mask == 0) {
+        continue;
       }
 
-      if (mask != 0) {
-        printer->Print(
-          "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n",
-          "i", SimpleItoa(i),
-          "mask", StrCat(strings::Hex(mask, strings::ZERO_PAD_8)));
-      }
+      // TODO(ckennelly): Consider doing something similar to ByteSizeLong(),
+      // where we check all of the required fields in a single branch (assuming
+      // that we aren't going to benefit from early termination).
+      printer->Print(
+        "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n",
+        "i", SimpleItoa(i),
+        "mask", StrCat(strings::Hex(mask, strings::ZERO_PAD_8)));
     }
   }
 
-  // Now check that all embedded messages are initialized.
-  printer->Print("\n");
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = descriptor_->field(i);
+  // Now check that all non-oneof embedded messages are initialized.
+  for (int i = 0; i < optimized_order_.size(); i++) {
+    const FieldDescriptor* field = optimized_order_[i];
+    // TODO(ckennelly): Push this down into a generator?
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
-        !ShouldIgnoreRequiredFieldCheck(field) &&
-        HasRequiredFields(field->message_type())) {
+        !ShouldIgnoreRequiredFieldCheck(field, options_) &&
+        scc_analyzer_->HasRequiredFields(field->message_type())) {
       if (field->is_repeated()) {
-        printer->Print(
-          "if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))"
-          " return false;\n",
-          "name", FieldName(field));
-      } else {
-        if (field->options().weak() || !field->containing_oneof()) {
-          // For weak fields, use the data member (::google::protobuf::Message*) instead
-          // of the getter to avoid a link dependency on the weak message type
-          // which is only forward declared.
+        if (IsImplicitWeakField(field, options_, scc_analyzer_)) {
           printer->Print(
-              "if (has_$name$()) {\n"
-              "  if (!this->$name$_->IsInitialized()) return false;\n"
-              "}\n",
+            "if (!::google::protobuf::internal::AllAreInitializedWeak(this->$name$_))"
+            " return false;\n",
             "name", FieldName(field));
         } else {
           printer->Print(
+            "if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))"
+            " return false;\n",
+            "name", FieldName(field));
+        }
+      } else if (field->options().weak()) {
+        continue;
+      } else {
+        GOOGLE_CHECK(!field->containing_oneof());
+        printer->Print(
+            "if (has_$name$()) {\n"
+            "  if (!this->$name$_->IsInitialized()) return false;\n"
+            "}\n",
+            "name", FieldName(field));
+      }
+    }
+  }
+  if (num_weak_fields_) {
+    // For Weak fields.
+    printer->Print("if (!_weak_field_map_.IsInitialized()) return false;\n");
+  }
+  // Go through the oneof fields, emitting a switch if any might have required
+  // fields.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
+
+    bool has_required_fields = false;
+    for (int j = 0; j < oneof->field_count(); j++) {
+      const FieldDescriptor* field = oneof->field(j);
+
+      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+          !ShouldIgnoreRequiredFieldCheck(field, options_) &&
+          scc_analyzer_->HasRequiredFields(field->message_type())) {
+        has_required_fields = true;
+        break;
+      }
+    }
+
+    if (!has_required_fields) {
+      continue;
+    }
+
+    printer->Print(
+        "switch ($oneofname$_case()) {\n",
+        "oneofname", oneof->name());
+    printer->Indent();
+    for (int j = 0; j < oneof->field_count(); j++) {
+      const FieldDescriptor* field = oneof->field(j);
+      printer->Print(
+          "case k$field_name$: {\n",
+          "field_name", UnderscoresToCamelCase(field->name(), true));
+      printer->Indent();
+
+      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+          !ShouldIgnoreRequiredFieldCheck(field, options_) &&
+          scc_analyzer_->HasRequiredFields(field->message_type())) {
+        GOOGLE_CHECK(!(field->options().weak() || !field->containing_oneof()));
+        if (field->options().weak()) {
+          // Just skip.
+        } else {
+          printer->Print(
             "if (has_$name$()) {\n"
             "  if (!this->$name$().IsInitialized()) return false;\n"
             "}\n",
             "name", FieldName(field));
         }
       }
-    }
-  }
 
-  if (descriptor_->extension_range_count() > 0) {
+      printer->Print(
+          "break;\n");
+      printer->Outdent();
+      printer->Print(
+          "}\n");
+    }
     printer->Print(
-      "\n"
-      "if (!_extensions_.IsInitialized()) return false;");
+        "case $cap_oneof_name$_NOT_SET: {\n"
+        "  break;\n"
+        "}\n",
+        "cap_oneof_name",
+        ToUpper(oneof->name()));
+    printer->Outdent();
+    printer->Print(
+        "}\n");
   }
 
   printer->Outdent();
@@ -3758,7 +4379,6 @@
     "}\n");
 }
 
-
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index 8e19a3f..ca2ca2c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -36,12 +36,11 @@
 #define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
 
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 #include <set>
 #include <string>
 #include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/cpp_message_layout_helper.h>
 #include <google/protobuf/compiler/cpp/cpp_options.h>
 
 namespace google {
@@ -61,73 +60,70 @@
 class MessageGenerator {
  public:
   // See generator.cc for the meaning of dllexport_decl.
-  MessageGenerator(const Descriptor* descriptor, const Options& options);
+  MessageGenerator(const Descriptor* descriptor, int index_in_file_messages,
+                   const Options& options, SCCAnalyzer* scc_analyzer);
   ~MessageGenerator();
 
+  // Append the two types of nested generators to the corresponding vector.
+  void AddGenerators(std::vector<EnumGenerator*>* enum_generators,
+                     std::vector<ExtensionGenerator*>* extension_generators);
+
   // Header stuff.
 
-  // Return names for foward declarations of this class and all its nested
-  // types.
-  void FillMessageForwardDeclarations(set<string>* class_names);
-  void FillEnumForwardDeclarations(set<string>* enum_names);
-
-  // Generate definitions of all nested enums (must come before class
-  // definitions because those classes use the enums definitions).
-  void GenerateEnumDefinitions(io::Printer* printer);
-
-  // Generate specializations of GetEnumDescriptor<MyEnum>().
-  // Precondition: in ::google::protobuf namespace.
-  void GenerateGetEnumDescriptorSpecializations(io::Printer* printer);
+  // Return names for forward declarations of this class and all its nested
+  // types. A given key in {class,enum}_names will map from a class name to the
+  // descriptor that was responsible for its inclusion in the map. This can be
+  // used to associate the descriptor with the code generated for it.
+  void FillMessageForwardDeclarations(
+      std::map<string, const Descriptor*>* class_names);
 
   // Generate definitions for this class and all its nested types.
   void GenerateClassDefinition(io::Printer* printer);
 
   // Generate definitions of inline methods (placed at the end of the header
   // file).
-  void GenerateInlineMethods(io::Printer* printer, bool is_inline);
-
-  // Dependent methods are always inline.
-  void GenerateDependentInlineMethods(io::Printer* printer);
+  void GenerateInlineMethods(io::Printer* printer);
 
   // Source file stuff.
 
-  // Generate code which declares all the global descriptor pointers which
-  // will be initialized by the methods below.
-  void GenerateDescriptorDeclarations(io::Printer* printer);
+  // Generate extra fields
+  void GenerateExtraDefaultFields(io::Printer* printer);
 
-  // Generate code that initializes the global variable storing the message's
-  // descriptor.
-  void GenerateDescriptorInitializer(io::Printer* printer, int index);
-
-  // Generate code that calls MessageFactory::InternalRegisterGeneratedMessage()
-  // for all types.
-  void GenerateTypeRegistrations(io::Printer* printer);
-
-  // Generates code that allocates the message's default instance.
-  void GenerateDefaultInstanceAllocator(io::Printer* printer);
+  // Generates code that creates default instances for fields.
+  void GenerateFieldDefaultInstances(io::Printer* printer);
 
   // Generates code that initializes the message's default instance.  This
   // is separate from allocating because all default instances must be
   // allocated before any can be initialized.
   void GenerateDefaultInstanceInitializer(io::Printer* printer);
 
-  // Generates code that should be run when ShutdownProtobufLibrary() is called,
-  // to delete all dynamically-allocated objects.
-  void GenerateShutdownCode(io::Printer* printer);
-
   // Generate all non-inline methods for this class.
   void GenerateClassMethods(io::Printer* printer);
 
+  // Generate source file code that should go outside any namespace.
+  void GenerateSourceInProto2Namespace(io::Printer* printer);
+
  private:
   // Generate declarations and definitions of accessors for fields.
-  void GenerateDependentBaseClassDefinition(io::Printer* printer);
-  void GenerateDependentFieldAccessorDeclarations(io::Printer* printer);
   void GenerateFieldAccessorDeclarations(io::Printer* printer);
-  void GenerateDependentFieldAccessorDefinitions(io::Printer* printer);
-  void GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline);
+  void GenerateFieldAccessorDefinitions(io::Printer* printer);
 
-  // Generate the field offsets array.
-  void GenerateOffsets(io::Printer* printer);
+  // Generate the table-driven parsing array.  Returns the number of entries
+  // generated.
+  size_t GenerateParseOffsets(io::Printer* printer);
+  size_t GenerateParseAuxTable(io::Printer* printer);
+  // Generates a ParseTable entry.  Returns whether the proto uses table-driven
+  // parsing.
+  bool GenerateParseTable(io::Printer* printer, size_t offset,
+                          size_t aux_offset);
+
+  // Generate the field offsets array.  Returns the a pair of the total numer
+  // of entries generated and the index of the first has_bit entry.
+  std::pair<size_t, size_t> GenerateOffsets(io::Printer* printer);
+  void GenerateSchema(io::Printer* printer, int offset, int has_offset);
+  // For each field generates a table entry describing the field for the
+  // table driven serializer.
+  int GenerateFieldMetadata(io::Printer* printer);
 
   // Generate constructors and destructor.
   void GenerateStructors(io::Printer* printer);
@@ -143,6 +139,13 @@
   // Generate the arena-specific destructor code.
   void GenerateArenaDestructorCode(io::Printer* printer);
 
+  // Helper for GenerateClear and others.  Optionally emits a condition that
+  // assumes the existence of the cached_has_bits variable, and returns true if
+  // the condition was printed.
+  bool MaybeGenerateOptionalFieldCondition(io::Printer* printer,
+                                           const FieldDescriptor* field,
+                                           int expected_has_bits_index);
+
   // Generate standard Message methods.
   void GenerateClear(io::Printer* printer);
   void GenerateOneofClear(io::Printer* printer);
@@ -158,41 +161,71 @@
   void GenerateIsInitialized(io::Printer* printer);
 
   // Helpers for GenerateSerializeWithCachedSizes().
+  //
+  // cached_has_bit_index maintains that:
+  //   cached_has_bits = _has_bits_[cached_has_bit_index]
+  // for cached_has_bit_index >= 0
   void GenerateSerializeOneField(io::Printer* printer,
                                  const FieldDescriptor* field,
-                                 bool unbounded);
+                                 bool unbounded,
+                                 int cached_has_bits_index);
+  // Generate a switch statement to serialize 2+ fields from the same oneof.
+  // Or, if fields.size() == 1, just call GenerateSerializeOneField().
+  void GenerateSerializeOneofFields(
+      io::Printer* printer, const std::vector<const FieldDescriptor*>& fields,
+      bool to_array);
   void GenerateSerializeOneExtensionRange(
       io::Printer* printer, const Descriptor::ExtensionRange* range,
       bool unbounded);
 
-
   // Generates has_foo() functions and variables for singular field has-bits.
   void GenerateSingularFieldHasBits(const FieldDescriptor* field,
-                                    map<string, string> vars,
+                                    std::map<string, string> vars,
                                     io::Printer* printer);
   // Generates has_foo() functions and variables for oneof field has-bits.
-  void GenerateOneofHasBits(io::Printer* printer, bool is_inline);
+  void GenerateOneofHasBits(io::Printer* printer);
   // Generates has_foo_bar() functions for oneof members.
   void GenerateOneofMemberHasBits(const FieldDescriptor* field,
-                                  const map<string, string>& vars,
+                                  const std::map<string, string>& vars,
                                   io::Printer* printer);
   // Generates the clear_foo() method for a field.
   void GenerateFieldClear(const FieldDescriptor* field,
-                          const map<string, string>& vars,
+                          const std::map<string, string>& vars,
+                          bool is_inline,
                           io::Printer* printer);
 
+  void GenerateConstructorBody(io::Printer* printer,
+                               std::vector<bool> already_processed,
+                               bool copy_constructor) const;
+
+  size_t HasBitsSize() const;
+  std::vector<uint32> RequiredFieldsBitMask() const;
+
   const Descriptor* descriptor_;
+  int index_in_file_messages_;
   string classname_;
   Options options_;
   FieldGeneratorMap field_generators_;
-  vector< vector<string> > runs_of_fields_;  // that might be trivially cleared
-  google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > nested_generators_;
-  google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_;
-  google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
+  // optimized_order_ is the order we layout the message's fields in the class.
+  // This is reused to initialize the fields in-order for cache efficiency.
+  //
+  // optimized_order_ excludes oneof fields and weak fields.
+  std::vector<const FieldDescriptor *> optimized_order_;
+  std::vector<int> has_bit_indices_;
+  int max_has_bit_index_;
+  std::unique_ptr<std::unique_ptr<EnumGenerator> []> enum_generators_;
+  std::unique_ptr<std::unique_ptr<ExtensionGenerator> []> extension_generators_;
   int num_required_fields_;
-  bool uses_string_;
-  bool use_dependent_base_;
+  int num_weak_fields_;
+  // table_driven_ indicates the generated message uses table-driven parsing.
+  bool table_driven_;
 
+  std::unique_ptr<MessageLayoutHelper> message_layout_helper_;
+
+  SCCAnalyzer* scc_analyzer_;
+  string scc_name_;
+
+  friend class FileGenerator;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
 };
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index b454589..c1e15c5 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -35,6 +35,7 @@
 #include <google/protobuf/compiler/cpp/cpp_message_field.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/io/printer.h>
+
 #include <google/protobuf/stubs/strutil.h>
 
 namespace google {
@@ -44,153 +45,161 @@
 
 namespace {
 
+// When we are generating code for implicit weak fields, we need to insert some
+// additional casts. These functions return the casted expression if
+// implicit_weak_field is true but otherwise return the original expression.
+// Ordinarily a static_cast is enough to cast google::protobuf::MessageLite* to a class
+// deriving from it, but we need a reinterpret_cast in cases where the generated
+// message is forward-declared but its full definition is not visible.
+string StaticCast(const string& type, const string& expression,
+                  bool implicit_weak_field) {
+  if (implicit_weak_field) {
+    return "static_cast< " + type + " >(" + expression + ")";
+  } else {
+    return expression;
+  }
+}
+
+string ReinterpretCast(const string& type, const string& expression,
+                       bool implicit_weak_field) {
+  if (implicit_weak_field) {
+    return "reinterpret_cast< " + type + " >(" + expression + ")";
+  } else {
+    return expression;
+  }
+}
+
 void SetMessageVariables(const FieldDescriptor* descriptor,
-                         map<string, string>* variables,
-                         const Options& options) {
+                         const Options& options, bool implicit_weak,
+                         std::map<string, string>* variables) {
   SetCommonFieldVariables(descriptor, variables, options);
   (*variables)["type"] = FieldMessageTypeName(descriptor);
-  if (descriptor->options().weak() || !descriptor->containing_oneof()) {
-    (*variables)["non_null_ptr_to_name"] =
-        StrCat("this->", (*variables)["name"], "_");
-  }
-  (*variables)["stream_writer"] = (*variables)["declared_type"] +
-      (HasFastArraySerialization(descriptor->message_type()->file()) ?
-       "MaybeToArray" :
-       "");
+  (*variables)["casted_member"] = ReinterpretCast(
+      (*variables)["type"] + "*", (*variables)["name"] + "_", implicit_weak);
+  (*variables)["type_default_instance"] =
+      DefaultInstanceName(descriptor->message_type());
+  (*variables)["type_reference_function"] =
+      implicit_weak
+          ? ("  " + ReferenceFunctionName(descriptor->message_type()) + "();\n")
+          : "";
+  (*variables)["stream_writer"] =
+      (*variables)["declared_type"] +
+      (HasFastArraySerialization(descriptor->message_type()->file(), options)
+           ? "MaybeToArray"
+           : "");
   // NOTE: Escaped here to unblock proto1->proto2 migration.
   // TODO(liujisi): Extend this to apply for other conflicting methods.
   (*variables)["release_name"] =
       SafeFunctionName(descriptor->containing_type(),
                        descriptor, "release_");
   (*variables)["full_name"] = descriptor->full_name();
-  if (options.proto_h && IsFieldDependent(descriptor)) {
-    (*variables)["dependent_type"] = "T::" + DependentTypeName(descriptor);
-    (*variables)["dependent_typename"] =
-        "typename T::" + DependentTypeName(descriptor);
-  } else {
-    (*variables)["dependent_type"] = FieldMessageTypeName(descriptor);
-    (*variables)["dependent_typename"] = FieldMessageTypeName(descriptor);
-  }
 }
 
 }  // namespace
 
 // ===================================================================
 
-MessageFieldGenerator::
-MessageFieldGenerator(const FieldDescriptor* descriptor,
-                      const Options& options)
-  : descriptor_(descriptor),
-    dependent_field_(options.proto_h && IsFieldDependent(descriptor)) {
-  SetMessageVariables(descriptor, &variables_, options);
+MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
+                                             const Options& options,
+                                             SCCAnalyzer* scc_analyzer)
+    : FieldGenerator(options),
+      descriptor_(descriptor),
+      implicit_weak_field_(
+          IsImplicitWeakField(descriptor, options, scc_analyzer)) {
+  SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_);
 }
 
 MessageFieldGenerator::~MessageFieldGenerator() {}
 
 void MessageFieldGenerator::
 GeneratePrivateMembers(io::Printer* printer) const {
-  printer->Print(variables_, "$type$* $name$_;\n");
-}
-
-void MessageFieldGenerator::
-GenerateGetterDeclaration(io::Printer* printer) const {
-  printer->Print(variables_,
-      "const $type$& $name$() const$deprecation$;\n");
-}
-
-void MessageFieldGenerator::
-GenerateDependentAccessorDeclarations(io::Printer* printer) const {
-  if (!dependent_field_) {
-    return;
+  if (implicit_weak_field_) {
+    printer->Print(variables_, "::google::protobuf::MessageLite* $name$_;\n");
+  } else {
+    printer->Print(variables_, "$type$* $name$_;\n");
   }
-  // Arena manipulation code is out-of-line in the derived message class.
-  printer->Print(variables_,
-    "$type$* mutable_$name$()$deprecation$;\n"
-    "$type$* $release_name$()$deprecation$;\n"
-    "void set_allocated_$name$($type$* $name$)$deprecation$;\n");
 }
 
 void MessageFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
-  if (SupportsArenas(descriptor_)) {
+  if (implicit_weak_field_) {
+    // These private accessors are used by MergeFrom and
+    // MergePartialFromCodedStream, and their purpose is to provide access to
+    // the field without creating a strong dependency on the message type.
     printer->Print(variables_,
        "private:\n"
-       "void _slow_mutable_$name$()$deprecation$;\n");
-    if (SupportsArenas(descriptor_->message_type())) {
-      printer->Print(variables_,
-       "void _slow_set_allocated_$name$(\n"
-       "    ::google::protobuf::Arena* message_arena, $type$** $name$)$deprecation$;\n");
-    }
+       "const ::google::protobuf::MessageLite& _internal_$name$() const;\n"
+       "::google::protobuf::MessageLite* _internal_mutable_$name$();\n"
+       "public:\n");
+  } else {
+    // This inline accessor directly returns member field and is used in
+    // Serialize such that AFDO profile correctly captures access information to
+    // message fields under serialize.
     printer->Print(variables_,
-       "$type$* _slow_$release_name$()$deprecation$;\n"
+       "private:\n"
+       "const $type$& _internal_$name$() const;\n"
        "public:\n");
   }
-  GenerateGetterDeclaration(printer);
-  if (!dependent_field_) {
-    printer->Print(variables_,
-      "$type$* mutable_$name$()$deprecation$;\n"
-      "$type$* $release_name$()$deprecation$;\n"
-      "void set_allocated_$name$($type$* $name$)$deprecation$;\n");
-  }
+  printer->Print(variables_,
+      "$deprecated_attr$const $type$& $name$() const;\n");
+  printer->Annotate("name", descriptor_);
+  printer->Print(variables_, "$deprecated_attr$$type$* $release_name$();\n");
+  printer->Annotate("release_name", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$$type$* ${$mutable_$name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$void ${$set_allocated_$name$$}$"
+                 "($type$* $name$);\n");
+  printer->Annotate("{", "}", descriptor_);
   if (SupportsArenas(descriptor_)) {
     printer->Print(variables_,
-      "$type$* unsafe_arena_release_$name$()$deprecation$;\n"
-      "void unsafe_arena_set_allocated_$name$(\n"
-      "    $type$* $name$)$deprecation$;\n");
+                   "$deprecated_attr$void "
+                   "${$unsafe_arena_set_allocated_$name$$}$(\n"
+                   "    $type$* $name$);\n");
+    printer->Annotate("{", "}", descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecated_attr$$type$* ${$unsafe_arena_release_$name$$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 }
 
 void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
     io::Printer* printer) const {
-  if (SupportsArenas(descriptor_)) {
+  if (implicit_weak_field_) {
     printer->Print(variables_,
-      "void $classname$::_slow_mutable_$name$() {\n");
-      if (SupportsArenas(descriptor_->message_type())) {
-        printer->Print(variables_,
-          "  $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
-          "      GetArenaNoVirtual());\n");
-      } else {
-        printer->Print(variables_,
-          "  $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
-          "      GetArenaNoVirtual());\n");
-      }
-    printer->Print(variables_,
-      "}\n"
-      "$type$* $classname$::_slow_$release_name$() {\n"
-      "  if ($name$_ == NULL) {\n"
-      "    return NULL;\n"
+      "const ::google::protobuf::MessageLite& $classname$::_internal_$name$() const {\n"
+      "  if ($name$_ != NULL) {\n"
+      "    return *$name$_;\n"
+      "  } else if (&$type_default_instance$ != NULL) {\n"
+      "    return *reinterpret_cast<const ::google::protobuf::MessageLite*>(\n"
+      "        &$type_default_instance$);\n"
       "  } else {\n"
-      "    $type$* temp = new $type$;\n"
-      "    temp->MergeFrom(*$name$_);\n"
-      "    $name$_ = NULL;\n"
-      "    return temp;\n"
+      "    return "
+      "*::google::protobuf::internal::ImplicitWeakMessage::default_instance();\n"
       "  }\n"
-      "}\n"
-      "$type$* $classname$::unsafe_arena_release_$name$() {\n"
-      "  $clear_hasbit$\n"
-      "  $type$* temp = $name$_;\n"
-      "  $name$_ = NULL;\n"
-      "  return temp;\n"
       "}\n");
-    if (SupportsArenas(descriptor_->message_type())) {
-      // NOTE: the same logic is mirrored in weak_message_field.cc. Any
-      // arena-related semantics changes should be made in both places.
+  }
+  if (SupportsArenas(descriptor_)) {
+    if (implicit_weak_field_) {
       printer->Print(variables_,
-          "void $classname$::_slow_set_allocated_$name$(\n"
-          "    ::google::protobuf::Arena* message_arena, $type$** $name$) {\n"
-          "    if (message_arena != NULL && \n"
-          "        ::google::protobuf::Arena::GetArena(*$name$) == NULL) {\n"
-          "      message_arena->Own(*$name$);\n"
-          "    } else if (message_arena !=\n"
-          "               ::google::protobuf::Arena::GetArena(*$name$)) {\n"
-          "      $type$* new_$name$ = \n"
-          "            ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
-          "            message_arena);\n"
-          "      new_$name$->CopyFrom(**$name$);\n"
-          "      *$name$ = new_$name$;\n"
-          "    }\n"
-          "}\n");
+        "::google::protobuf::MessageLite* $classname$::_internal_mutable_$name$() {\n"
+        "  $set_hasbit$\n"
+        "  if ($name$_ == NULL) {\n"
+        "    if (&$type_default_instance$ == NULL) {\n"
+        "      $name$_ = ::google::protobuf::Arena::CreateMessage<\n"
+        "          ::google::protobuf::internal::ImplicitWeakMessage>(\n"
+        "              GetArenaNoVirtual());\n"
+        "    } else {\n"
+        "      $name$_ = reinterpret_cast<const ::google::protobuf::MessageLite*>(\n"
+        "          &$type_default_instance$)->New(GetArenaNoVirtual());\n"
+        "    }\n"
+        "  }\n"
+        "  return $name$_;\n"
+        "}\n");
     }
+
     printer->Print(variables_,
       "void $classname$::unsafe_arena_set_allocated_$name$(\n"
       "    $type$* $name$) {\n"
@@ -208,281 +217,198 @@
       "  // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
       ":$full_name$)\n"
       "}\n");
+  } else if (implicit_weak_field_) {
+    printer->Print(variables_,
+        "::google::protobuf::MessageLite* $classname$::_internal_mutable_$name$() {\n"
+        "  $set_hasbit$\n"
+        "  if ($name$_ == NULL) {\n"
+        "    if (&$type_default_instance$ == NULL) {\n"
+        "      $name$_ = new ::google::protobuf::internal::ImplicitWeakMessage;\n"
+        "    } else {\n"
+        "      $name$_ = reinterpret_cast<const ::google::protobuf::MessageLite*>(\n"
+        "          &$type_default_instance$)->New();\n"
+        "    }\n"
+        "  }\n"
+        "  return $name$_;\n"
+        "}\n");
   }
 }
 
 void MessageFieldGenerator::
-GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
-  if (!dependent_field_) {
-    return;
-  }
-
-  map<string, string> variables(variables_);
-  // For the CRTP base class, all mutation methods are dependent, and so
-  // they must be in the header.
-  variables["dependent_classname"] =
-      DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
-  variables["this_message"] = DependentBaseDownCast();
-  if (!variables["set_hasbit"].empty()) {
-    variables["set_hasbit"] =
-        variables["this_message"] + variables["set_hasbit"];
-  }
-  if (!variables["clear_hasbit"].empty()) {
-    variables["clear_hasbit"] =
-        variables["this_message"] + variables["clear_hasbit"];
-  }
-
-  if (SupportsArenas(descriptor_)) {
-    printer->Print(variables,
-      "template <class T>\n"
-      "inline $type$* $dependent_classname$::mutable_$name$() {\n"
-      "  $set_hasbit$\n"
-      "  $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
-      "  if ($name$_ == NULL) {\n"
-      "    $this_message$_slow_mutable_$name$();\n"
-      "  }\n"
-      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
-      "  return $name$_;\n"
-      "}\n"
-      "template <class T>\n"
-      "inline $type$* $dependent_classname$::$release_name$() {\n"
-      "  $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
-      "  $clear_hasbit$\n"
-      "  if ($this_message$GetArenaNoVirtual() != NULL) {\n"
-      "    return $this_message$_slow_$release_name$();\n"
-      "  } else {\n"
-      "    $dependent_typename$* temp = $name$_;\n"
-      "    $name$_ = NULL;\n"
-      "    return temp;\n"
-      "  }\n"
-      "}\n"
-      "template <class T>\n"
-      "inline void $dependent_classname$::"
-      "set_allocated_$name$($type$* $name$) {\n"
-      "  ::google::protobuf::Arena* message_arena = $this_message$GetArenaNoVirtual();\n"
-      "  $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
-      "  if (message_arena == NULL) {\n"
-      "    delete $name$_;\n"
-      "  }\n"
-      "  if ($name$ != NULL) {\n");
-    if (SupportsArenas(descriptor_->message_type())) {
-      // If we're on an arena and the incoming message is not, simply Own() it
-      // rather than copy to the arena -- either way we need a heap dealloc,
-      // so we might as well defer it. Otherwise, if incoming message is on a
-      // different ownership domain (specific arena, or the heap) than we are,
-      // copy to our arena (or heap, as the case may be).
-      printer->Print(variables,
-        "    $this_message$_slow_set_allocated_$name$(message_arena, "
-        "&$name$);\n");
-    } else {
-      printer->Print(variables,
-        "    if (message_arena != NULL) {\n"
-        "      message_arena->Own($name$);\n"
-        "    }\n");
-    }
-    printer->Print(variables,
-      "  }\n"
-      "  $name$_ = $name$;\n"
-      "  if ($name$) {\n"
-      "    $set_hasbit$\n"
-      "  } else {\n"
-      "    $clear_hasbit$\n"
-      "  }\n"
-      // TODO(dlj): move insertion points to message class.
-      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
-      "}\n");
-  } else {
-    printer->Print(variables,
-      "template <class T>\n"
-      "inline $type$* $dependent_classname$::mutable_$name$() {\n"
-      "  $set_hasbit$\n"
-      "  $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
-      "  if ($name$_ == NULL) {\n"
-      "    $name$_ = new $dependent_typename$;\n"
-      "  }\n"
-      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
-      "  return $name$_;\n"
-      "}\n"
-      "template <class T>\n"
-      "inline $type$* $dependent_classname$::$release_name$() {\n"
-      "  $clear_hasbit$\n"
-      "  $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
-      "  $dependent_typename$* temp = $name$_;\n"
-      "  $name$_ = NULL;\n"
-      "  return temp;\n"
-      "}\n"
-      "template <class T>\n"
-      "inline void $dependent_classname$::"
-      "set_allocated_$name$($type$* $name$) {\n"
-      "  $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
-      "  delete $name$_;\n");
-
-    if (SupportsArenas(descriptor_->message_type())) {
-      printer->Print(variables,
-      "  if ($name$ != NULL && static_cast< $dependent_typename$* >($name$)"
-      "->GetArena() != NULL) {\n"
-      "    $dependent_typename$* new_$name$ = new $dependent_typename$;\n"
-      "    new_$name$->CopyFrom(*$name$);\n"
-      "    $name$ = new_$name$;\n"
-      "  }\n");
-    }
-
-    printer->Print(variables,
-      "  $name$_ = $name$;\n"
-      "  if ($name$) {\n"
-      "    $set_hasbit$\n"
-      "  } else {\n"
-      "    $clear_hasbit$\n"
-      "  }\n"
-      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+  if (!implicit_weak_field_) {
+    printer->Print(variables_,
+      "inline const $type$& $classname$::_internal_$name$() const {\n"
+      "  return *$field_member$;\n"
       "}\n");
   }
-}
+  printer->Print(variables_,
+    "inline const $type$& $classname$::$name$() const {\n"
+    "  const $type$* p = $casted_member$;\n"
+    "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+    "  return p != NULL ? *p : *reinterpret_cast<const $type$*>(\n"
+    "      &$type_default_instance$);\n"
+    "}\n");
 
-void MessageFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                  bool is_inline) const {
-  map<string, string> variables(variables_);
-  variables["inline"] = is_inline ? "inline " : "";
-  printer->Print(variables,
-    "$inline$const $type$& $classname$::$name$() const {\n"
-    "  // @@protoc_insertion_point(field_get:$full_name$)\n");
-
-  PrintHandlingOptionalStaticInitializers(
-    variables, descriptor_->file(), printer,
-    // With static initializers.
-    "  return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
-    // Without.
-    "  return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
-  printer->Print(variables, "}\n");
-
-  if (dependent_field_) {
-    return;
-  }
-
+  printer->Print(variables_,
+    "inline $type$* $classname$::$release_name$() {\n"
+    "  // @@protoc_insertion_point(field_release:$full_name$)\n"
+    "$type_reference_function$"
+    "  $clear_hasbit$\n"
+    "  $type$* temp = $casted_member$;\n");
   if (SupportsArenas(descriptor_)) {
-    printer->Print(variables,
-      "$inline$"
-      "$type$* $classname$::mutable_$name$() {\n"
-      "  $set_hasbit$\n"
-      "  if ($name$_ == NULL) {\n"
-      "    _slow_mutable_$name$();\n"
-      "  }\n"
-      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
-      "  return $name$_;\n"
-      "}\n"
-      "$inline$"
-      "$type$* $classname$::$release_name$() {\n"
-      "  $clear_hasbit$\n"
+    printer->Print(variables_,
       "  if (GetArenaNoVirtual() != NULL) {\n"
-      "    return _slow_$release_name$();\n"
-      "  } else {\n"
-      "    $type$* temp = $name$_;\n"
-      "    $name$_ = NULL;\n"
-      "    return temp;\n"
-      "  }\n"
-      "}\n"
-      "$inline$ "
-      "void $classname$::set_allocated_$name$($type$* $name$) {\n"
-      "  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n"
-      "  if (message_arena == NULL) {\n"
-      "    delete $name$_;\n"
-      "  }\n"
-      "  if ($name$ != NULL) {\n");
-    if (SupportsArenas(descriptor_->message_type())) {
-      // If we're on an arena and the incoming message is not, simply Own() it
-      // rather than copy to the arena -- either way we need a heap dealloc,
-      // so we might as well defer it. Otherwise, if incoming message is on a
-      // different ownership domain (specific arena, or the heap) than we are,
-      // copy to our arena (or heap, as the case may be).
-      printer->Print(variables,
-        "    _slow_set_allocated_$name$(message_arena, &$name$);\n");
-    } else {
-      printer->Print(variables,
-        "    if (message_arena != NULL) {\n"
-        "      message_arena->Own($name$);\n"
-        "    }\n");
-    }
-    printer->Print(variables,
-      "  }\n"
-      "  $name$_ = $name$;\n"
-      "  if ($name$) {\n"
-      "    $set_hasbit$\n"
-      "  } else {\n"
-      "    $clear_hasbit$\n"
-      "  }\n"
-      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
-      "}\n");
-  } else {
-    printer->Print(variables,
-      "$inline$"
-      "$type$* $classname$::mutable_$name$() {\n"
-      "  $set_hasbit$\n"
-      "  if ($name$_ == NULL) {\n"
-      "    $name$_ = new $type$;\n"
-      "  }\n"
-      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
-      "  return $name$_;\n"
-      "}\n"
-      "$inline$"
-      "$type$* $classname$::$release_name$() {\n"
+      "    temp = ::google::protobuf::internal::DuplicateIfNonNull(temp);\n"
+      "  }\n");
+  }
+  printer->Print(variables_,
+    "  $name$_ = NULL;\n"
+    "  return temp;\n"
+    "}\n");
+
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+      "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
+      "  // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
+      "$type_reference_function$"
       "  $clear_hasbit$\n"
-      "  $type$* temp = $name$_;\n"
+      "  $type$* temp = $casted_member$;\n"
       "  $name$_ = NULL;\n"
       "  return temp;\n"
-      "}\n"
-      "$inline$"
-      "void $classname$::set_allocated_$name$($type$* $name$) {\n"
-      "  delete $name$_;\n");
-
-    if (SupportsArenas(descriptor_->message_type())) {
-      printer->Print(variables,
-      "  if ($name$ != NULL && $name$->GetArena() != NULL) {\n"
-      "    $type$* new_$name$ = new $type$;\n"
-      "    new_$name$->CopyFrom(*$name$);\n"
-      "    $name$ = new_$name$;\n"
-      "  }\n");
-    }
-
-    printer->Print(variables,
-      "  $name$_ = $name$;\n"
-      "  if ($name$) {\n"
-      "    $set_hasbit$\n"
-      "  } else {\n"
-      "    $clear_hasbit$\n"
-      "  }\n"
-      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
       "}\n");
   }
+
+  printer->Print(variables_,
+    "inline $type$* $classname$::mutable_$name$() {\n"
+    "  $set_hasbit$\n"
+    "  if ($name$_ == NULL) {\n"
+    "    auto* p = CreateMaybeMessage<$type$>(GetArenaNoVirtual());\n");
+  if (implicit_weak_field_) {
+    printer->Print(variables_,
+      "    $name$_ = reinterpret_cast<::google::protobuf::MessageLite*>(p);\n");
+  } else {
+    printer->Print(variables_,
+      "    $name$_ = p;\n");
+  }
+  printer->Print(variables_,
+    "  }\n"
+    "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+    "  return $casted_member$;\n"
+    "}\n");
+
+  // We handle the most common case inline, and delegate less common cases to
+  // the slow fallback function.
+  printer->Print(variables_,
+    "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+    "  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n");
+  printer->Print(variables_,
+    "  if (message_arena == NULL) {\n");
+  if (IsCrossFileMessage(descriptor_)) {
+    printer->Print(variables_,
+      "    delete reinterpret_cast< ::google::protobuf::MessageLite*>($name$_);\n");
+  } else {
+    printer->Print(variables_,
+      "    delete $name$_;\n");
+  }
+  printer->Print(variables_,
+    "  }\n"
+    "  if ($name$) {\n");
+  if (SupportsArenas(descriptor_->message_type()) &&
+      IsCrossFileMessage(descriptor_)) {
+    // We have to read the arena through the virtual method, because the type
+    // isn't defined in this file.
+    printer->Print(variables_,
+      "    ::google::protobuf::Arena* submessage_arena =\n"
+      "      reinterpret_cast<::google::protobuf::MessageLite*>($name$)->GetArena();\n");
+  } else if (!SupportsArenas(descriptor_->message_type())) {
+    printer->Print(variables_,
+      "    ::google::protobuf::Arena* submessage_arena = NULL;\n");
+  } else {
+    printer->Print(variables_,
+      "    ::google::protobuf::Arena* submessage_arena =\n"
+      "      ::google::protobuf::Arena::GetArena($name$);\n");
+  }
+  printer->Print(variables_,
+    "    if (message_arena != submessage_arena) {\n"
+    "      $name$ = ::google::protobuf::internal::GetOwnedMessage(\n"
+    "          message_arena, $name$, submessage_arena);\n"
+    "    }\n"
+    "    $set_hasbit$\n"
+    "  } else {\n"
+    "    $clear_hasbit$\n"
+    "  }\n");
+  if (implicit_weak_field_) {
+    printer->Print(variables_,
+      "  $name$_ = reinterpret_cast<MessageLite*>($name$);\n");
+  } else {
+    printer->Print(variables_,
+      "  $name$_ = $name$;\n");
+  }
+  printer->Print(variables_,
+    "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+    "}\n");
 }
 
 void MessageFieldGenerator::
 GenerateClearingCode(io::Printer* printer) const {
-  map<string, string> variables(variables_);
-  variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
   if (!HasFieldPresence(descriptor_->file())) {
     // If we don't have has-bits, message presence is indicated only by ptr !=
     // NULL. Thus on clear, we need to delete the object.
-    printer->Print(variables,
-      "if ($this_message$GetArenaNoVirtual() == NULL && "
-      "$this_message$$name$_ != NULL) delete $this_message$$name$_;\n"
-      "$this_message$$name$_ = NULL;\n");
+    printer->Print(variables_,
+      "if (GetArenaNoVirtual() == NULL && $name$_ != NULL) {\n"
+      "  delete $name$_;\n"
+      "}\n"
+      "$name$_ = NULL;\n");
   } else {
-    printer->Print(variables,
-      "if ($this_message$$name$_ != NULL) $this_message$$name$_->"
-      "$dependent_type$::Clear();\n");
+    printer->Print(variables_,
+      "if ($name$_ != NULL) $name$_->Clear();\n");
+  }
+}
+
+void MessageFieldGenerator::
+GenerateMessageClearingCode(io::Printer* printer) const {
+  if (!HasFieldPresence(descriptor_->file())) {
+    // If we don't have has-bits, message presence is indicated only by ptr !=
+    // NULL. Thus on clear, we need to delete the object.
+    printer->Print(variables_,
+      "if (GetArenaNoVirtual() == NULL && $name$_ != NULL) {\n"
+      "  delete $name$_;\n"
+      "}\n"
+      "$name$_ = NULL;\n");
+  } else {
+    printer->Print(variables_,
+      "GOOGLE_DCHECK($name$_ != NULL);\n"
+      "$name$_->Clear();\n");
   }
 }
 
 void MessageFieldGenerator::
 GenerateMergingCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
+  if (implicit_weak_field_) {
+    printer->Print(variables_,
+      "_internal_mutable_$name$()->CheckTypeAndMergeFrom(\n"
+      "    from._internal_$name$());\n");
+  } else {
+    printer->Print(variables_,
+      "mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
+  }
 }
 
 void MessageFieldGenerator::
 GenerateSwappingCode(io::Printer* printer) const {
-  printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
+  printer->Print(variables_, "swap($name$_, other->$name$_);\n");
+}
+
+void MessageFieldGenerator::
+GenerateDestructorCode(io::Printer* printer) const {
+  // TODO(gerbens) Remove this when we don't need to destruct default instances.
+  // In google3 a default instance will never get deleted so we don't need to
+  // worry about that but in opensource protobuf default instances are deleted
+  // in shutdown process and we need to take special care when handling them.
+  printer->Print(variables_,
+    "if (this != internal_default_instance()) ");
+  printer->Print(variables_, "delete $name$_;\n");
 }
 
 void MessageFieldGenerator::
@@ -491,14 +417,28 @@
 }
 
 void MessageFieldGenerator::
+GenerateCopyConstructorCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (from.has_$name$()) {\n"
+    "  $name$_ = new $type$(*from.$name$_);\n"
+    "} else {\n"
+    "  $name$_ = NULL;\n"
+    "}\n");
+}
+
+void MessageFieldGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) const {
-  if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
+  if (implicit_weak_field_) {
     printer->Print(variables_,
-      "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
+      "DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(\n"
+      "     input, _internal_mutable_$name$()));\n");
+  } else if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
+    printer->Print(variables_,
+      "DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(\n"
       "     input, mutable_$name$()));\n");
   } else {
     printer->Print(variables_,
-      "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
+      "DO_(::google::protobuf::internal::WireFormatLite::ReadGroup(\n"
       "      $number$, input, mutable_$name$()));\n");
   }
 }
@@ -507,215 +447,121 @@
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
   printer->Print(variables_,
     "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
-    "  $number$, *$non_null_ptr_to_name$, output);\n");
+    "  $number$, this->_internal_$name$(), output);\n");
 }
 
 void MessageFieldGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
   printer->Print(variables_,
     "target = ::google::protobuf::internal::WireFormatLite::\n"
-    "  Write$declared_type$NoVirtualToArray(\n"
-    "    $number$, *$non_null_ptr_to_name$, target);\n");
+    "  InternalWrite$declared_type$ToArray(\n"
+    "    $number$, this->_internal_$name$(), deterministic, target);\n");
 }
 
 void MessageFieldGenerator::
 GenerateByteSize(io::Printer* printer) const {
   printer->Print(variables_,
     "total_size += $tag_size$ +\n"
-    "  ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
-    "    *$non_null_ptr_to_name$);\n");
+    "  ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
+    "    *$field_member$);\n");
 }
 
 // ===================================================================
 
-MessageOneofFieldGenerator::
-MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
-                           const Options& options)
-  : MessageFieldGenerator(descriptor, options),
-    dependent_base_(options.proto_h) {
+MessageOneofFieldGenerator::MessageOneofFieldGenerator(
+    const FieldDescriptor* descriptor, const Options& options,
+    SCCAnalyzer* scc_analyzer)
+    : MessageFieldGenerator(descriptor, options, scc_analyzer) {
   SetCommonOneofFieldVariables(descriptor, &variables_);
 }
 
 MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
 
-
-void MessageOneofFieldGenerator::
-GenerateDependentAccessorDeclarations(io::Printer* printer) const {
-  // Oneof field getters must be dependent as they call default_instance().
-  // Otherwise, the logic is the same as MessageFields.
-  if (!dependent_field_) {
-    return;
+void MessageOneofFieldGenerator::GenerateNonInlineAccessorDefinitions(
+    io::Printer* printer) const {
+  printer->Print(variables_,
+    "void $classname$::set_allocated_$name$($type$* $name$) {\n"
+    "  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n"
+    "  clear_$oneof_name$();\n"
+    "  if ($name$) {\n");
+  if (SupportsArenas(descriptor_->message_type()) &&
+      descriptor_->file() != descriptor_->message_type()->file()) {
+    // We have to read the arena through the virtual method, because the type
+    // isn't defined in this file.
+    printer->Print(variables_,
+      "    ::google::protobuf::Arena* submessage_arena =\n"
+      "      reinterpret_cast<::google::protobuf::MessageLite*>($name$)->GetArena();\n");
+  } else if (!SupportsArenas(descriptor_->message_type())) {
+    printer->Print(variables_,
+      "    ::google::protobuf::Arena* submessage_arena = NULL;\n");
+  } else {
+    printer->Print(variables_,
+      "    ::google::protobuf::Arena* submessage_arena =\n"
+      "      ::google::protobuf::Arena::GetArena($name$);\n");
   }
   printer->Print(variables_,
-      "const $type$& $name$() const$deprecation$;\n");
-  MessageFieldGenerator::GenerateDependentAccessorDeclarations(printer);
+    "    if (message_arena != submessage_arena) {\n"
+    "      $name$ = ::google::protobuf::internal::GetOwnedMessage(\n"
+    "          message_arena, $name$, submessage_arena);\n"
+    "    }\n"
+    "    set_has_$name$();\n"
+    "    $field_member$ = $name$;\n"
+    "  }\n"
+    "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+    "}\n");
 }
 
 void MessageOneofFieldGenerator::
-GenerateGetterDeclaration(io::Printer* printer) const {
-  // Oneof field getters must be dependent as they call default_instance().
-  // Unlike MessageField, this means there is no (non-dependent) getter to
-  // generate.
-  if (dependent_field_) {
-    return;
+GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+  if (!implicit_weak_field_) {
+    printer->Print(variables_,
+      "inline const $type$& $classname$::_internal_$name$() const {\n"
+      "  return *$field_member$;\n"
+      "}\n");
   }
   printer->Print(variables_,
-      "const $type$& $name$() const$deprecation$;\n");
-}
-
-void MessageOneofFieldGenerator::
-GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
-  // For the CRTP base class, all mutation methods are dependent, and so
-  // they must be in the header.
-  if (!dependent_base_) {
-    return;
+    "inline $type$* $classname$::$release_name$() {\n"
+    "  // @@protoc_insertion_point(field_release:$full_name$)\n"
+    "  if (has_$name$()) {\n"
+    "    clear_has_$oneof_name$();\n"
+    "      $type$* temp = $field_member$;\n");
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+      "    if (GetArenaNoVirtual() != NULL) {\n"
+      "      temp = ::google::protobuf::internal::DuplicateIfNonNull(temp);\n"
+      "    }\n");
   }
-  map<string, string> variables(variables_);
-  variables["inline"] = "inline ";
-  variables["dependent_classname"] =
-      DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
-  variables["this_message"] = "reinterpret_cast<T*>(this)->";
-  // Const message access is needed for the dependent getter.
-  variables["this_const_message"] = "reinterpret_cast<const T*>(this)->";
-  variables["tmpl"] = "template <class T>\n";
-  variables["field_member"] = variables["this_message"] +
-                              variables["oneof_prefix"] + variables["name"] +
-                              "_";
-  InternalGenerateInlineAccessorDefinitions(variables, printer);
-}
+  printer->Print(variables_,
+    "    $field_member$ = NULL;\n"
+    "    return temp;\n"
+    "  } else {\n"
+    "    return NULL;\n"
+    "  }\n"
+    "}\n");
 
-void MessageOneofFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                  bool is_inline) const {
-  if (dependent_base_) {
-    return;
-  }
-  map<string, string> variables(variables_);
-  variables["inline"] = is_inline ? "inline " : "";
-  variables["dependent_classname"] = variables["classname"];
-  variables["this_message"] = "";
-  variables["this_const_message"] = "";
-  variables["tmpl"] = "";
-  variables["field_member"] =
-      variables["oneof_prefix"] + variables["name"] + "_";
-  variables["dependent_type"] = variables["type"];
-  InternalGenerateInlineAccessorDefinitions(variables, printer);
-}
-
-void MessageOneofFieldGenerator::
-GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
-  map<string, string> variables(variables_);
-  variables["field_member"] =
-      variables["oneof_prefix"] + variables["name"] + "_";
-
-  //printer->Print(variables,
-}
-
-void MessageOneofFieldGenerator::
-InternalGenerateInlineAccessorDefinitions(const map<string, string>& variables,
-                                          io::Printer* printer) const {
-  printer->Print(variables,
-    "$tmpl$"
-    "$inline$ "
-    "const $type$& $dependent_classname$::$name$() const {\n"
+  printer->Print(variables_,
+    "inline const $type$& $classname$::$name$() const {\n"
     "  // @@protoc_insertion_point(field_get:$full_name$)\n"
-    "  return $this_const_message$has_$name$()\n"
-    "      ? *$this_const_message$$oneof_prefix$$name$_\n"
-    "      : $dependent_type$::default_instance();\n"
+    "  return has_$name$()\n"
+    "      ? *$field_member$\n"
+    "      : *reinterpret_cast< $type$*>(&$type_default_instance$);\n"
     "}\n");
 
   if (SupportsArenas(descriptor_)) {
-    printer->Print(variables,
-      "$tmpl$"
-      "$inline$"
-      "$type$* $dependent_classname$::mutable_$name$() {\n"
-      "  if (!$this_message$has_$name$()) {\n"
-      "    $this_message$clear_$oneof_name$();\n"
-      "    $this_message$set_has_$name$();\n");
-    if (SupportsArenas(descriptor_->message_type())) {
-      printer->Print(variables,
-         "    $field_member$ = \n"
-         "      ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n"
-         "      $this_message$GetArenaNoVirtual());\n");
-    } else {
-      printer->Print(variables,
-         "    $this_message$$oneof_prefix$$name$_ = \n"
-         "      ::google::protobuf::Arena::Create< $dependent_typename$ >(\n"
-         "      $this_message$GetArenaNoVirtual());\n");
-    }
-    printer->Print(variables,
-      "  }\n"
-      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
-      "  return $field_member$;\n"
-      "}\n"
-      "$tmpl$"
-      "$inline$"
-      "$type$* $dependent_classname$::$release_name$() {\n"
-      "  if ($this_message$has_$name$()) {\n"
-      "    $this_message$clear_has_$oneof_name$();\n"
-      "    if ($this_message$GetArenaNoVirtual() != NULL) {\n"
-      // N.B.: safe to use the underlying field pointer here because we are sure
-      // that it is non-NULL (because has_$name$() returned true).
-      "      $dependent_typename$* temp = new $dependent_typename$;\n"
-      "      temp->MergeFrom(*$field_member$);\n"
-      "      $field_member$ = NULL;\n"
-      "      return temp;\n"
-      "    } else {\n"
-      "      $dependent_typename$* temp = $field_member$;\n"
-      "      $field_member$ = NULL;\n"
-      "      return temp;\n"
-      "    }\n"
-      "  } else {\n"
-      "    return NULL;\n"
-      "  }\n"
-      "}\n"
-      "$tmpl$"
-      "$inline$"
-      "void $dependent_classname$::"
-      "set_allocated_$name$($type$* $name$) {\n"
-      "  $this_message$clear_$oneof_name$();\n"
-      "  if ($name$) {\n");
-
-    if (SupportsArenas(descriptor_->message_type())) {
-      printer->Print(variables,
-        // If incoming message is on the heap and we are on an arena, just Own()
-        // it (see above). If it's on a different arena than we are or one of us
-        // is on the heap, we make a copy to our arena/heap.
-        "    if ($this_message$GetArenaNoVirtual() != NULL &&\n"
-        "        ::google::protobuf::Arena::GetArena($name$) == NULL) {\n"
-        "      $this_message$GetArenaNoVirtual()->Own($name$);\n"
-        "    } else if ($this_message$GetArenaNoVirtual() !=\n"
-        "               ::google::protobuf::Arena::GetArena($name$)) {\n"
-        "      $dependent_typename$* new_$name$ = \n"
-        "          ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n"
-        "          $this_message$GetArenaNoVirtual());\n"
-        "      new_$name$->CopyFrom(*$name$);\n"
-        "      $name$ = new_$name$;\n"
-        "    }\n");
-    } else {
-      printer->Print(variables,
-        "    if ($this_message$GetArenaNoVirtual() != NULL) {\n"
-        "      $this_message$GetArenaNoVirtual()->Own($name$);\n"
-        "    }\n");
-    }
-
-    printer->Print(variables,
-      "    $this_message$set_has_$name$();\n"
-      "    $field_member$ = $name$;\n"
-      "  }\n"
-      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
-      "}\n"
-      "$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n"
+    printer->Print(variables_,
+      "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
+      "  // @@protoc_insertion_point(field_unsafe_arena_release"
+      ":$full_name$)\n"
       "  if (has_$name$()) {\n"
       "    clear_has_$oneof_name$();\n"
-      "    $type$* temp = $oneof_prefix$$name$_;\n"
-      "    $oneof_prefix$$name$_ = NULL;\n"
+      "    $type$* temp = $field_member$;\n"
+      "    $field_member$ = NULL;\n"
       "    return temp;\n"
       "  } else {\n"
       "    return NULL;\n"
       "  }\n"
       "}\n"
-      "$inline$ void $classname$::unsafe_arena_set_allocated_$name$"
+      "inline void $classname$::unsafe_arena_set_allocated_$name$"
       "($type$* $name$) {\n"
       // We rely on the oneof clear method to free the earlier contents of this
       // oneof. We can directly use the pointer we're given to set the new
@@ -723,81 +569,56 @@
       "  clear_$oneof_name$();\n"
       "  if ($name$) {\n"
       "    set_has_$name$();\n"
-      "    $oneof_prefix$$name$_ = $name$;\n"
+      "    $field_member$ = $name$;\n"
       "  }\n"
       "  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
       "$full_name$)\n"
       "}\n");
-  } else {
-    printer->Print(variables,
-      "$tmpl$"
-      "$inline$"
-      "$type$* $dependent_classname$::mutable_$name$() {\n"
-      "  if (!$this_message$has_$name$()) {\n"
-      "    $this_message$clear_$oneof_name$();\n"
-      "    $this_message$set_has_$name$();\n"
-      "    $field_member$ = new $dependent_typename$;\n"
-      "  }\n"
-      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
-      "  return $field_member$;\n"
-      "}\n"
-      "$tmpl$"
-      "$inline$"
-      "$type$* $dependent_classname$::$release_name$() {\n"
-      "  if ($this_message$has_$name$()) {\n"
-      "    $this_message$clear_has_$oneof_name$();\n"
-      "    $dependent_typename$* temp = $field_member$;\n"
-      "    $field_member$ = NULL;\n"
-      "    return temp;\n"
-      "  } else {\n"
-      "    return NULL;\n"
-      "  }\n"
-      "}\n"
-      "$tmpl$"
-      "$inline$"
-      "void $dependent_classname$::"
-      "set_allocated_$name$($type$* $name$) {\n"
-      "  $this_message$clear_$oneof_name$();\n"
-      "  if ($name$) {\n");
-    if (SupportsArenas(descriptor_->message_type())) {
-      printer->Print(variables,
-        "    if (static_cast< $dependent_typename$*>($name$)->"
-        "GetArena() != NULL) {\n"
-        "      $dependent_typename$* new_$name$ = new $dependent_typename$;\n"
-        "      new_$name$->CopyFrom(*$name$);\n"
-        "      $name$ = new_$name$;\n"
-        "    }\n");
-    }
-    printer->Print(variables,
-      "    $this_message$set_has_$name$();\n"
-      "    $field_member$ = $name$;\n"
-      "  }\n"
-      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
-      "}\n");
   }
+
+  printer->Print(variables_,
+    "inline $type$* $classname$::mutable_$name$() {\n"
+    "  if (!has_$name$()) {\n"
+    "    clear_$oneof_name$();\n"
+    "    set_has_$name$();\n"
+    "    $field_member$ = CreateMaybeMessage< $type$ >(\n"
+    "        GetArenaNoVirtual());\n"
+    "  }\n"
+    "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+    "  return $field_member$;\n"
+    "}\n");
 }
 
 void MessageOneofFieldGenerator::
 GenerateClearingCode(io::Printer* printer) const {
-  map<string, string> variables(variables_);
-  variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
   if (SupportsArenas(descriptor_)) {
-    printer->Print(variables,
-      "if ($this_message$GetArenaNoVirtual() == NULL) {\n"
-      "  delete $this_message$$oneof_prefix$$name$_;\n"
+    printer->Print(variables_,
+      "if (GetArenaNoVirtual() == NULL) {\n"
+      "  delete $field_member$;\n"
       "}\n");
   } else {
-    printer->Print(variables,
-      "delete $this_message$$oneof_prefix$$name$_;\n");
+    printer->Print(variables_,
+      "delete $field_member$;\n");
   }
 }
 
 void MessageOneofFieldGenerator::
+GenerateMessageClearingCode(io::Printer* printer) const {
+  GenerateClearingCode(printer);
+}
+
+void MessageOneofFieldGenerator::
 GenerateSwappingCode(io::Printer* printer) const {
   // Don't print any swapping code. Swapping the union will swap this field.
 }
 
 void MessageOneofFieldGenerator::
+GenerateDestructorCode(io::Printer* printer) const {
+  // We inherit from MessageFieldGenerator, so we need to override the default
+  // behavior.
+}
+
+void MessageOneofFieldGenerator::
 GenerateConstructorCode(io::Printer* printer) const {
   // Don't print any constructor code. The field is in a union. We allocate
   // space only when this field is used.
@@ -805,13 +626,14 @@
 
 // ===================================================================
 
-RepeatedMessageFieldGenerator::
-RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
-                              const Options& options)
-  : descriptor_(descriptor),
-    dependent_field_(options.proto_h && IsFieldDependent(descriptor)),
-    dependent_getter_(dependent_field_ && options.safe_boundary_check) {
-  SetMessageVariables(descriptor, &variables_, options);
+RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
+    const FieldDescriptor* descriptor, const Options& options,
+    SCCAnalyzer* scc_analyzer)
+    : FieldGenerator(options),
+      descriptor_(descriptor),
+      implicit_weak_field_(
+          IsImplicitWeakField(descriptor, options, scc_analyzer)) {
+  SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_);
 }
 
 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
@@ -823,170 +645,103 @@
 }
 
 void RepeatedMessageFieldGenerator::
-InternalGenerateTypeDependentAccessorDeclarations(io::Printer* printer) const {
-  printer->Print(variables_,
-    "$type$* mutable_$name$(int index)$deprecation$;\n"
-    "$type$* add_$name$()$deprecation$;\n");
-  if (dependent_getter_) {
-    printer->Print(variables_,
-      "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
-      "    $name$() const$deprecation$;\n");
-  }
-  printer->Print(variables_,
-    "::google::protobuf::RepeatedPtrField< $type$ >*\n"
-    "    mutable_$name$()$deprecation$;\n");
-}
-
-void RepeatedMessageFieldGenerator::
-GenerateDependentAccessorDeclarations(io::Printer* printer) const {
-  if (dependent_getter_) {
-    printer->Print(variables_,
-      "const $type$& $name$(int index) const$deprecation$;\n");
-  }
-  if (dependent_field_) {
-    InternalGenerateTypeDependentAccessorDeclarations(printer);
-  }
-}
-
-void RepeatedMessageFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
-  if (!dependent_getter_) {
-    printer->Print(variables_,
-      "const $type$& $name$(int index) const$deprecation$;\n");
-  }
-  if (!dependent_field_) {
-    InternalGenerateTypeDependentAccessorDeclarations(printer);
-  }
-  if (!dependent_getter_) {
-    printer->Print(variables_,
-      "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
-      "    $name$() const$deprecation$;\n");
-  }
+  printer->Print(variables_,
+                 "$deprecated_attr$$type$* ${$mutable_$name$$}$(int index);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$::google::protobuf::RepeatedPtrField< $type$ >*\n"
+                 "    ${$mutable_$name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
+
+  printer->Print(variables_,
+    "$deprecated_attr$const $type$& $name$(int index) const;\n");
+  printer->Annotate("name", descriptor_);
+  printer->Print(variables_, "$deprecated_attr$$type$* ${$add_$name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+    "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+    "    $name$() const;\n");
+  printer->Annotate("name", descriptor_);
 }
 
 void RepeatedMessageFieldGenerator::
-GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
-  if (!dependent_field_) {
-    return;
-  }
-  map<string, string> variables(variables_);
-  // For the CRTP base class, all mutation methods are dependent, and so
-  // they must be in the header.
-  variables["dependent_classname"] =
-      DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
-  variables["this_message"] = DependentBaseDownCast();
-  variables["this_const_message"] = DependentBaseConstDownCast();
-
-  if (dependent_getter_) {
-    printer->Print(variables,
-      "template <class T>\n"
-      "inline const $type$& $dependent_classname$::$name$(int index) const {\n"
-      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
-      "  return $this_const_message$$name$_.$cppget$(index);\n"
-      "}\n");
-  }
-
-  // Generate per-element accessors:
-  printer->Print(variables,
-    "template <class T>\n"
-    "inline $type$* $dependent_classname$::mutable_$name$(int index) {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+  printer->Print(variables_,
+    "inline $type$* $classname$::mutable_$name$(int index) {\n"
     // TODO(dlj): move insertion points
     "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
-    "  return $this_message$$name$_.Mutable(index);\n"
+    "$type_reference_function$"
+    "  return $name$_.Mutable(index);\n"
     "}\n"
-    "template <class T>\n"
-    "inline $type$* $dependent_classname$::add_$name$() {\n"
-    "  // @@protoc_insertion_point(field_add:$full_name$)\n"
-    "  return $this_message$$name$_.Add();\n"
-    "}\n");
-
-
-  if (dependent_getter_) {
-    printer->Print(variables,
-      "template <class T>\n"
-      "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
-      "$dependent_classname$::$name$() const {\n"
-      "  // @@protoc_insertion_point(field_list:$full_name$)\n"
-      "  return $this_const_message$$name$_;\n"
-      "}\n");
-  }
-
-  // Generate mutable access to the entire list:
-  printer->Print(variables,
-    "template <class T>\n"
     "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
-    "$dependent_classname$::mutable_$name$() {\n"
+    "$classname$::mutable_$name$() {\n"
     "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
-    "  return &$this_message$$name$_;\n"
+    "$type_reference_function$"
+    "  return &$name$_;\n"
     "}\n");
-}
 
-void RepeatedMessageFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                  bool is_inline) const {
-  map<string, string> variables(variables_);
-  variables["inline"] = is_inline ? "inline " : "";
-
-  if (!dependent_getter_) {
-    printer->Print(variables,
-      "$inline$"
-      "const $type$& $classname$::$name$(int index) const {\n"
+  if (options_.safe_boundary_check) {
+    printer->Print(variables_,
+      "inline const $type$& $classname$::$name$(int index) const {\n"
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
-      "  return $name$_.$cppget$(index);\n"
+      "  return $name$_.InternalCheckedGet(index,\n"
+      "      *reinterpret_cast<const $type$*>(&$type_default_instance$));\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "inline const $type$& $classname$::$name$(int index) const {\n"
+      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+      "$type_reference_function$"
+      "  return $name$_.Get(index);\n"
       "}\n");
   }
 
-  if (!dependent_field_) {
-    printer->Print(variables,
-      "$inline$"
-      "$type$* $classname$::mutable_$name$(int index) {\n"
-      // TODO(dlj): move insertion points
-      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
-      "  return $name$_.Mutable(index);\n"
-      "}\n"
-      "$inline$"
-      "$type$* $classname$::add_$name$() {\n"
-      "  // @@protoc_insertion_point(field_add:$full_name$)\n"
-      "  return $name$_.Add();\n"
-      "}\n");
-  }
+  printer->Print(variables_,
+    "inline $type$* $classname$::add_$name$() {\n"
+    "  // @@protoc_insertion_point(field_add:$full_name$)\n"
+    "  return $name$_.Add();\n"
+    "}\n");
 
-
-  if (!dependent_field_) {
-    printer->Print(variables,
-      "$inline$"
-      "::google::protobuf::RepeatedPtrField< $type$ >*\n"
-      "$classname$::mutable_$name$() {\n"
-      "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
-      "  return &$name$_;\n"
-      "}\n");
-  }
-  if (!dependent_getter_) {
-    printer->Print(variables,
-      "$inline$"
-      "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
-      "$classname$::$name$() const {\n"
-      "  // @@protoc_insertion_point(field_list:$full_name$)\n"
-      "  return $name$_;\n"
-      "}\n");
-  }
+  printer->Print(variables_,
+    "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+    "$classname$::$name$() const {\n"
+    "  // @@protoc_insertion_point(field_list:$full_name$)\n"
+    "$type_reference_function$"
+    "  return $name$_;\n"
+    "}\n");
 }
 
 void RepeatedMessageFieldGenerator::
 GenerateClearingCode(io::Printer* printer) const {
-  map<string, string> variables(variables_);
-  variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
-  printer->Print(variables, "$this_message$$name$_.Clear();\n");
+  if (implicit_weak_field_) {
+    printer->Print(
+        variables_,
+        "CastToBase(&$name$_)->Clear<"
+        "::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>();\n");
+  } else {
+    printer->Print(variables_, "$name$_.Clear();\n");
+  }
 }
 
 void RepeatedMessageFieldGenerator::
 GenerateMergingCode(io::Printer* printer) const {
-  printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
+  if (implicit_weak_field_) {
+    printer->Print(
+        variables_,
+        "CastToBase(&$name$_)->MergeFrom<"
+        "::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>(CastToBase("
+        "from.$name$_));\n");
+  } else {
+    printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
+  }
 }
 
 void RepeatedMessageFieldGenerator::
 GenerateSwappingCode(io::Printer* printer) const {
-  printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
+  printer->Print(
+      variables_,
+      "CastToBase(&$name$_)->InternalSwap(CastToBase(&other->$name$_));\n");
 }
 
 void RepeatedMessageFieldGenerator::
@@ -997,46 +752,82 @@
 void RepeatedMessageFieldGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) const {
   if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
-    printer->Print(variables_,
-      "DO_(::google::protobuf::internal::WireFormatLite::"
-      "ReadMessageNoVirtualNoRecursionDepth(\n"
-      "      input, add_$name$()));\n");
+    if (implicit_weak_field_) {
+      printer->Print(variables_,
+        "DO_(::google::protobuf::internal::WireFormatLite::"
+        "ReadMessage(input, CastToBase(&$name$_)->AddWeak(\n"
+        "    reinterpret_cast<const ::google::protobuf::MessageLite*>(\n"
+        "        &$type_default_instance$))));\n");
+    } else {
+      printer->Print(variables_,
+        "DO_(::google::protobuf::internal::WireFormatLite::"
+        "ReadMessage(\n"
+        "      input, add_$name$()));\n");
+    }
   } else {
     printer->Print(variables_,
       "DO_(::google::protobuf::internal::WireFormatLite::"
-      "ReadGroupNoVirtualNoRecursionDepth(\n"
-      "      $number$, input, add_$name$()));\n");
+      "ReadGroup($number$, input, add_$name$()));\n");
   }
 }
 
 void RepeatedMessageFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
   printer->Print(variables_,
-    "for (unsigned int i = 0, n = this->$name$_size(); i < n; i++) {\n"
+    "for (unsigned int i = 0,\n"
+    "    n = static_cast<unsigned int>(this->$name$_size()); i < n; i++) {\n"
     "  ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
-    "    $number$, this->$name$(i), output);\n"
+    "    $number$,\n");
+  if (implicit_weak_field_) {
+    printer->Print(
+        variables_,
+        "    CastToBase($name$_).Get<"
+        "::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>("
+        "static_cast<int>(i)),\n");
+  } else {
+    printer->Print(variables_,
+      "    this->$name$(static_cast<int>(i)),\n");
+  }
+  printer->Print(variables_,
+    "    output);\n"
     "}\n");
 }
 
 void RepeatedMessageFieldGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
   printer->Print(variables_,
-    "for (unsigned int i = 0, n = this->$name$_size(); i < n; i++) {\n"
+    "for (unsigned int i = 0,\n"
+    "    n = static_cast<unsigned int>(this->$name$_size()); i < n; i++) {\n"
     "  target = ::google::protobuf::internal::WireFormatLite::\n"
-    "    Write$declared_type$NoVirtualToArray(\n"
-    "      $number$, this->$name$(i), target);\n"
+    "    InternalWrite$declared_type$ToArray(\n"
+    "      $number$, this->$name$(static_cast<int>(i)), deterministic, target);\n"
     "}\n");
 }
 
 void RepeatedMessageFieldGenerator::
 GenerateByteSize(io::Printer* printer) const {
   printer->Print(variables_,
-    "total_size += $tag_size$ * this->$name$_size();\n"
-    "for (int i = 0; i < this->$name$_size(); i++) {\n"
+    "{\n"
+    "  unsigned int count = static_cast<unsigned int>(this->$name$_size());\n");
+  printer->Indent();
+  printer->Print(variables_,
+    "total_size += $tag_size$UL * count;\n"
+    "for (unsigned int i = 0; i < count; i++) {\n"
     "  total_size +=\n"
-    "    ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
-    "      this->$name$(i));\n"
-    "}\n");
+    "    ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n");
+  if (implicit_weak_field_) {
+    printer->Print(
+        variables_,
+        "      CastToBase($name$_).Get<"
+        "::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>("
+        "static_cast<int>(i)));\n");
+  } else {
+    printer->Print(variables_,
+        "      this->$name$(static_cast<int>(i)));\n");
+  }
+  printer->Print(variables_, "}\n");
+  printer->Outdent();
+  printer->Print("}\n");
 }
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h
index 35efd0f..6879539 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h
@@ -38,6 +38,7 @@
 #include <map>
 #include <string>
 #include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
 
 namespace google {
 namespace protobuf {
@@ -46,36 +47,31 @@
 
 class MessageFieldGenerator : public FieldGenerator {
  public:
-  explicit MessageFieldGenerator(const FieldDescriptor* descriptor,
-                                 const Options& options);
+  MessageFieldGenerator(const FieldDescriptor* descriptor,
+                        const Options& options, SCCAnalyzer* scc_analyzer);
   ~MessageFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
   void GeneratePrivateMembers(io::Printer* printer) const;
-  void GenerateDependentAccessorDeclarations(io::Printer* printer) const;
   void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                         bool is_inline) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
   void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
   void GenerateClearingCode(io::Printer* printer) const;
+  void GenerateMessageClearingCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
+  void GenerateDestructorCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
 
  protected:
-  void GenerateArenaManipulationCode(const map<string, string>& variables,
-                                     io::Printer* printer) const;
-
-  virtual void GenerateGetterDeclaration(io::Printer* printer) const;
-
   const FieldDescriptor* descriptor_;
-  const bool dependent_field_;
-  map<string, string> variables_;
+  const bool implicit_weak_field_;
+  std::map<string, string> variables_;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
@@ -83,61 +79,51 @@
 
 class MessageOneofFieldGenerator : public MessageFieldGenerator {
  public:
-  explicit MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
-                                      const Options& options);
+  MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
+                             const Options& options, SCCAnalyzer* scc_analyzer);
   ~MessageOneofFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GenerateDependentAccessorDeclarations(io::Printer* printer) const;
-  void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                         bool is_inline) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
   void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
   void GenerateClearingCode(io::Printer* printer) const;
+
+  // MessageFieldGenerator, from which we inherit, overrides this so we need to
+  // override it as well.
+  void GenerateMessageClearingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
+  void GenerateDestructorCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
 
- protected:
-  void GenerateGetterDeclaration(io::Printer* printer) const;
-
  private:
-  void InternalGenerateInlineAccessorDefinitions(
-      const map<string, string>& variables, io::Printer* printer) const;
-
-  const bool dependent_base_;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
 };
 
 class RepeatedMessageFieldGenerator : public FieldGenerator {
  public:
-  explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
-                                         const Options& options);
+  RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+                                const Options& options,
+                                SCCAnalyzer* scc_analyzer);
   ~RepeatedMessageFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
   void GeneratePrivateMembers(io::Printer* printer) const;
-  void GenerateDependentAccessorDeclarations(io::Printer* printer) const;
   void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                         bool is_inline) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateCopyConstructorCode(io::Printer* printer) const {}
   void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
 
  private:
-  void InternalGenerateTypeDependentAccessorDeclarations(
-      io::Printer* printer) const;
-
   const FieldDescriptor* descriptor_;
-  const bool dependent_field_;
-  const bool dependent_getter_;
-  map<string, string> variables_;
+  const bool implicit_weak_field_;
+  std::map<string, string> variables_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
 };
diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.h b/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h
similarity index 67%
copy from src/google/protobuf/compiler/javanano/javanano_extension.h
copy to src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h
index 4843e29..d502a6f 100644
--- a/src/google/protobuf/compiler/javanano/javanano_extension.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h
@@ -1,6 +1,6 @@
 // Protocol Buffers - Google's data interchange format
 // Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
+// https://developers.google.com/protocol-buffers/
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -28,47 +28,34 @@
 // (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: bduff@google.com (Brian Duff)
+// Author: seongkim@google.com (Seong Beom Kim)
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
-#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/javanano/javanano_params.h>
-#include <google/protobuf/descriptor.pb.h>
-
+#include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/descriptor.h>
 
 namespace google {
 namespace protobuf {
-  namespace io {
-    class Printer;             // printer.h
-  }
-}
-
-namespace protobuf {
 namespace compiler {
-namespace javanano {
+namespace cpp {
 
-class ExtensionGenerator {
+// Provides an abstract interface to optimize message layout
+// by rearranging the fields of a message.
+class MessageLayoutHelper {
  public:
-  explicit ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params);
-  ~ExtensionGenerator();
+  virtual ~MessageLayoutHelper() {}
 
-  void Generate(io::Printer* printer) const;
-
- private:
-  const Params& params_;
-  const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
+  virtual void OptimizeLayout(std::vector<const FieldDescriptor*>* fields,
+                              const Options& options) = 0;
 };
 
-}  // namespace javanano
+}  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
-}  // namespace google
 
-#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__
diff --git a/src/google/protobuf/compiler/cpp/cpp_move_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_move_unittest.cc
new file mode 100644
index 0000000..eb7cd1c
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_move_unittest.cc
@@ -0,0 +1,169 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <gtest/gtest.h>
+
+#if LANG_CXX11
+#include <type_traits>
+#endif
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
+namespace cpp_unittest {
+
+// Moves are enabled only when compiling with a C++11 compiler or newer.
+#if LANG_CXX11
+
+TEST(MovableMessageTest, MoveConstructor) {
+  protobuf_unittest::TestAllTypes message1;
+  TestUtil::SetAllFields(&message1);
+  const auto* nested = &message1.optional_nested_message();
+
+  protobuf_unittest::TestAllTypes message2(std::move(message1));
+  TestUtil::ExpectAllFieldsSet(message2);
+
+  // Check if the optional_nested_message was actually moved (and not just
+  // copied).
+  EXPECT_EQ(nested, &message2.optional_nested_message());
+  EXPECT_NE(nested, &message1.optional_nested_message());
+}
+
+TEST(MovableMessageTest, MoveAssignmentOperator) {
+  protobuf_unittest::TestAllTypes message1;
+  TestUtil::SetAllFields(&message1);
+  const auto* nested = &message1.optional_nested_message();
+
+  protobuf_unittest::TestAllTypes message2;
+  message2 = std::move(message1);
+  TestUtil::ExpectAllFieldsSet(message2);
+
+  // Check if the optional_nested_message was actually moved (and not just
+  // copied).
+  EXPECT_EQ(nested, &message2.optional_nested_message());
+  EXPECT_NE(nested, &message1.optional_nested_message());
+}
+
+TEST(MovableMessageTest, SelfMoveAssignment) {
+  // The `self` reference is necessary to defeat -Wself-move.
+  protobuf_unittest::TestAllTypes message, &self = message;
+  TestUtil::SetAllFields(&message);
+  message = std::move(self);
+  TestUtil::ExpectAllFieldsSet(message);
+}
+
+TEST(MovableMessageTest, MoveSameArena) {
+  Arena arena;
+
+  auto* message1_on_arena =
+      Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
+  TestUtil::SetAllFields(message1_on_arena);
+  const auto* nested = &message1_on_arena->optional_nested_message();
+
+  auto* message2_on_arena =
+      Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
+
+  // Moving messages on the same arena should lead to swapped pointers.
+  *message2_on_arena = std::move(*message1_on_arena);
+  EXPECT_EQ(nested, &message2_on_arena->optional_nested_message());
+}
+
+TEST(MovableMessageTest, MoveDifferentArenas) {
+  Arena arena1, arena2;
+
+  auto* message1_on_arena =
+      Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena1);
+  TestUtil::SetAllFields(message1_on_arena);
+  const auto* nested = &message1_on_arena->optional_nested_message();
+
+  auto* message2_on_arena =
+      Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena2);
+
+  // Moving messages on two different arenas should lead to a copy.
+  *message2_on_arena = std::move(*message1_on_arena);
+  EXPECT_NE(nested, &message2_on_arena->optional_nested_message());
+  TestUtil::ExpectAllFieldsSet(*message1_on_arena);
+  TestUtil::ExpectAllFieldsSet(*message2_on_arena);
+}
+
+TEST(MovableMessageTest, MoveFromArena) {
+  Arena arena;
+
+  auto* message1_on_arena =
+      Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
+  TestUtil::SetAllFields(message1_on_arena);
+  const auto* nested = &message1_on_arena->optional_nested_message();
+
+  protobuf_unittest::TestAllTypes message2;
+
+  // Moving from a message on the arena should lead to a copy.
+  message2 = std::move(*message1_on_arena);
+  EXPECT_NE(nested, &message2.optional_nested_message());
+  TestUtil::ExpectAllFieldsSet(*message1_on_arena);
+  TestUtil::ExpectAllFieldsSet(message2);
+}
+
+TEST(MovableMessageTest, MoveToArena) {
+  Arena arena;
+
+  protobuf_unittest::TestAllTypes message1;
+  TestUtil::SetAllFields(&message1);
+  const auto* nested = &message1.optional_nested_message();
+
+  auto* message2_on_arena =
+      Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
+
+  // Moving to a message on the arena should lead to a copy.
+  *message2_on_arena = std::move(message1);
+  EXPECT_NE(nested, &message2_on_arena->optional_nested_message());
+  TestUtil::ExpectAllFieldsSet(message1);
+  TestUtil::ExpectAllFieldsSet(*message2_on_arena);
+}
+
+TEST(MovableMessageTest, Noexcept) {
+  EXPECT_TRUE(
+      std::is_nothrow_move_constructible<protobuf_unittest::TestAllTypes>());
+  EXPECT_TRUE(std::is_nothrow_move_assignable<protobuf_unittest::TestAllTypes>());
+}
+
+#endif  // LANG_CXX11
+
+}  // namespace cpp_unittest
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h
index 4463f20..f09885b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_options.h
+++ b/src/google/protobuf/compiler/cpp/cpp_options.h
@@ -39,15 +39,39 @@
 namespace google {
 namespace protobuf {
 namespace compiler {
+class AccessInfoMap;
+
 namespace cpp {
 
 // Generator options (see generator.cc for a description of each):
 struct Options {
-  Options() : safe_boundary_check(false), proto_h(false) {
-  }
+  Options()
+      : safe_boundary_check(false),
+        proto_h(false),
+        transitive_pb_h(true),
+        annotate_headers(false),
+        enforce_lite(false),
+        table_driven_parsing(false),
+        table_driven_serialization(false),
+        lite_implicit_weak_fields(false),
+        bootstrap(false),
+        num_cc_files(0),
+        access_info_map(NULL) {}
+
   string dllexport_decl;
   bool safe_boundary_check;
   bool proto_h;
+  bool transitive_pb_h;
+  bool annotate_headers;
+  bool enforce_lite;
+  bool table_driven_parsing;
+  bool table_driven_serialization;
+  bool lite_implicit_weak_fields;
+  bool bootstrap;
+  int num_cc_files;
+  string annotation_pragma_name;
+  string annotation_guard_name;
+  const AccessInfoMap* access_info_map;
 };
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc
new file mode 100644
index 0000000..e930386
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc
@@ -0,0 +1,220 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/compiler/cpp/cpp_padding_optimizer.h>
+
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+namespace {
+
+// FieldGroup is just a helper for PaddingOptimizer 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 std::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_;
+  std::vector<const FieldDescriptor*> fields_;
+  // We rely on the default copy constructor and operator= so this type can be
+  // used in a vector.
+};
+
+}  // namespace
+
+// Reorder 'fields' so that if the fields are output into a c++ class in the new
+// order, fields of similar family (see below) are together and within each
+// family, alignment padding is minimized.
+//
+// We try to do this while keeping each field as close as possible to its field
+// number order so that we don't reduce cache locality much for function that
+// access each field in order.  Originally, OptimizePadding used declaration
+// order for its decisions, but generated code minus the serializer/parsers uses
+// the output of OptimizePadding as well (stored in
+// MessageGenerator::optimized_order_).  Since the serializers use field number
+// order, we use that as a tie-breaker.
+//
+// We classify each field into a particular "family" of fields, that we perform
+// the same operation on in our generated functions.
+//
+// REPEATED is placed first, as the C++ compiler automatically initializes
+// these fields in layout order.
+//
+// STRING is grouped next, as our Clear/SharedCtor/SharedDtor walks it and
+// calls ArenaStringPtr::Destroy on each.
+//
+//
+// MESSAGE is grouped next, as our Clear/SharedDtor code walks it and calls
+// delete on each.  We initialize these fields with a NULL pointer (see
+// MessageFieldGenerator::GenerateConstructorCode), which allows them to be
+// memset.
+//
+// ZERO_INITIALIZABLE is memset in Clear/SharedCtor
+//
+// OTHER these fields are initialized one-by-one.
+void PaddingOptimizer::OptimizeLayout(
+    std::vector<const FieldDescriptor*>* fields, const Options& options) {
+  // The sorted numeric order of Family determines the declaration order in the
+  // memory layout.
+  enum Family {
+    REPEATED = 0,
+    STRING = 1,
+    MESSAGE = 3,
+    ZERO_INITIALIZABLE = 4,
+    OTHER = 5,
+    kMaxFamily
+  };
+
+  // First divide fields into those that align to 1 byte, 4 bytes or 8 bytes.
+  std::vector<FieldGroup> aligned_to_1[kMaxFamily];
+  std::vector<FieldGroup> aligned_to_4[kMaxFamily];
+  std::vector<FieldGroup> aligned_to_8[kMaxFamily];
+  for (int i = 0; i < fields->size(); ++i) {
+    const FieldDescriptor* field = (*fields)[i];
+
+    Family f = OTHER;
+    if (field->is_repeated()) {
+      f = REPEATED;
+    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+      f = STRING;
+    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      f = MESSAGE;
+
+    } else if (CanInitializeByZeroing(field)) {
+      f = ZERO_INITIALIZABLE;
+    }
+
+    const int j = field->number();
+    switch (EstimateAlignmentSize(field)) {
+      case 1:
+        aligned_to_1[f].push_back(FieldGroup(j, field));
+        break;
+      case 4:
+        aligned_to_4[f].push_back(FieldGroup(j, field));
+        break;
+      case 8:
+        aligned_to_8[f].push_back(FieldGroup(j, field));
+        break;
+      default:
+        GOOGLE_LOG(FATAL) << "Unknown alignment size " << EstimateAlignmentSize(field)
+                   << "for a field " << field->full_name() << ".";
+    }
+  }
+
+  // For each family, group fields to optimize padding.
+  for (int f = 0; f < kMaxFamily; f++) {
+    // 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[f].size(); i += 4) {
+      FieldGroup field_group;
+      for (int j = i; j < aligned_to_1[f].size() && j < i + 4; ++j) {
+        field_group.Append(aligned_to_1[f][j]);
+      }
+      aligned_to_4[f].push_back(field_group);
+    }
+    // Sort by preferred location to keep fields as close to their field number
+    // order as possible.  Using stable_sort ensures that the output is
+    // consistent across runs.
+    std::stable_sort(aligned_to_4[f].begin(), aligned_to_4[f].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[f].size(); i += 2) {
+      FieldGroup field_group;
+      for (int j = i; j < aligned_to_4[f].size() && j < i + 2; ++j) {
+        field_group.Append(aligned_to_4[f][j]);
+      }
+      if (i == aligned_to_4[f].size() - 1) {
+        if (f == OTHER) {
+          // Move incomplete 4-byte block to the beginning.  This is done to
+          // pair with the (possible) leftover blocks from the
+          // ZERO_INITIALIZABLE family.
+          field_group.SetPreferredLocation(-1);
+        } else {
+          // Move incomplete 4-byte block to the end.
+          field_group.SetPreferredLocation(fields->size() + 1);
+        }
+      }
+      aligned_to_8[f].push_back(field_group);
+    }
+    // Sort by preferred location.
+    std::stable_sort(aligned_to_8[f].begin(), aligned_to_8[f].end());
+  }
+
+  // Now pull out all the FieldDescriptors in order.
+  fields->clear();
+  for (int f = 0; f < kMaxFamily; ++f) {
+    for (int i = 0; i < aligned_to_8[f].size(); ++i) {
+      fields->insert(fields->end(), aligned_to_8[f][i].fields().begin(),
+                     aligned_to_8[f][i].fields().end());
+    }
+  }
+}
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.h b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h
similarity index 67%
rename from src/google/protobuf/compiler/javanano/javanano_extension.h
rename to src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h
index 4843e29..42a3b5c 100644
--- a/src/google/protobuf/compiler/javanano/javanano_extension.h
+++ b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h
@@ -1,6 +1,6 @@
 // Protocol Buffers - Google's data interchange format
 // Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
+// https://developers.google.com/protocol-buffers/
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -28,47 +28,37 @@
 // (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: bduff@google.com (Brian Duff)
+// Author: seongkim@google.com (Seong Beom Kim)
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
-#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/javanano/javanano_params.h>
-#include <google/protobuf/descriptor.pb.h>
-
+#include <google/protobuf/compiler/cpp/cpp_message_layout_helper.h>
 
 namespace google {
 namespace protobuf {
-  namespace io {
-    class Printer;             // printer.h
-  }
-}
-
-namespace protobuf {
 namespace compiler {
-namespace javanano {
+namespace cpp {
 
-class ExtensionGenerator {
+// Rearranges the fields of a message to minimize padding.
+// Fields are grouped by the type and the size.
+// For example, grouping four boolean fields and one int32
+// field results in zero padding overhead. See OptimizeLayout's
+// comment for details.
+class PaddingOptimizer : public MessageLayoutHelper {
  public:
-  explicit ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params);
-  ~ExtensionGenerator();
+  PaddingOptimizer() {}
+  ~PaddingOptimizer() override {}
 
-  void Generate(io::Printer* printer) const;
-
- private:
-  const Params& params_;
-  const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
+  void OptimizeLayout(std::vector<const FieldDescriptor*>* fields,
+                      const Options& options) override;
 };
 
-}  // namespace javanano
+}  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
-}  // namespace google
 
-#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__
diff --git a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
index d1efbfe..ff6ba0f 100644
--- a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
@@ -35,18 +35,16 @@
 //   worth.
 
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 
 #include <google/protobuf/compiler/cpp/cpp_generator.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/io/printer.h>
 
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
-#include <google/protobuf/testing/file.h>
 
 namespace google {
 namespace protobuf {
@@ -131,7 +129,7 @@
     // Check field accessors for a message inside oneof{}:
     TryInsert("test.pb.h", "field_get:foo.Bar.oneOfMessage", context);
     TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfMessage", context);
-    TryInsert("test.pb.h", "field_set_allocated:foo.Bar.oneOfMessage", context);
+    TryInsert("test.pb.cc", "field_set_allocated:foo.Bar.oneOfMessage", context);
 
     // Check field accessors for an optional enum:
     TryInsert("test.pb.h", "field_get:foo.Bar.optEnum", context);
@@ -171,7 +169,7 @@
 
   void TryInsert(const string& filename, const string& insertion_point,
                  GeneratorContext* context) const {
-    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+    std::unique_ptr<io::ZeroCopyOutputStream> output(
         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 9f929d3..701f9d2 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -80,7 +80,7 @@
 }
 
 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
-                           map<string, string>* variables,
+                           std::map<string, string>* variables,
                            const Options& options) {
   SetCommonFieldVariables(descriptor, variables, options);
   (*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
@@ -100,10 +100,9 @@
 
 // ===================================================================
 
-PrimitiveFieldGenerator::
-PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
-                        const Options& options)
-  : descriptor_(descriptor) {
+PrimitiveFieldGenerator::PrimitiveFieldGenerator(
+    const FieldDescriptor* descriptor, const Options& options)
+    : FieldGenerator(options), descriptor_(descriptor) {
   SetPrimitiveVariables(descriptor, &variables_, options);
 }
 
@@ -116,21 +115,21 @@
 
 void PrimitiveFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
+  printer->Print(variables_, "$deprecated_attr$$type$ $name$() const;\n");
+  printer->Annotate("name", descriptor_);
   printer->Print(variables_,
-    "$type$ $name$() const$deprecation$;\n"
-    "void set_$name$($type$ value)$deprecation$;\n");
+                 "$deprecated_attr$void ${$set_$name$$}$($type$ value);\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void PrimitiveFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
-  map<string, string> variables(variables_);
-  variables["inline"] = is_inline ? "inline" : "";
-  printer->Print(variables,
-    "$inline$ $type$ $classname$::$name$() const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+  printer->Print(variables_,
+    "inline $type$ $classname$::$name$() const {\n"
     "  // @@protoc_insertion_point(field_get:$full_name$)\n"
     "  return $name$_;\n"
     "}\n"
-    "$inline$ void $classname$::set_$name$($type$ value) {\n"
+    "inline void $classname$::set_$name$($type$ value) {\n"
     "  $set_hasbit$\n"
     "  $name$_ = value;\n"
     "  // @@protoc_insertion_point(field_set:$full_name$)\n"
@@ -149,7 +148,7 @@
 
 void PrimitiveFieldGenerator::
 GenerateSwappingCode(io::Printer* printer) const {
-  printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
+  printer->Print(variables_, "swap($name$_, other->$name$_);\n");
 }
 
 void PrimitiveFieldGenerator::
@@ -158,12 +157,17 @@
 }
 
 void PrimitiveFieldGenerator::
+GenerateCopyConstructorCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_ = from.$name$_;\n");
+}
+
+void PrimitiveFieldGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) const {
   printer->Print(variables_,
+    "$set_hasbit$\n"
     "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
     "         $type$, $wire_format_field_type$>(\n"
-    "       input, &$name$_)));\n"
-    "$set_hasbit$\n");
+    "       input, &$name$_)));\n");
 }
 
 void PrimitiveFieldGenerator::
@@ -206,30 +210,28 @@
 PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
 
 void PrimitiveOneofFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
-  map<string, string> variables(variables_);
-  variables["inline"] = is_inline ? "inline" : "";
-  printer->Print(variables,
-    "$inline$ $type$ $classname$::$name$() const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+  printer->Print(variables_,
+    "inline $type$ $classname$::$name$() const {\n"
     "  // @@protoc_insertion_point(field_get:$full_name$)\n"
     "  if (has_$name$()) {\n"
-    "    return $oneof_prefix$$name$_;\n"
+    "    return $field_member$;\n"
     "  }\n"
     "  return $default$;\n"
     "}\n"
-    "$inline$ void $classname$::set_$name$($type$ value) {\n"
+    "inline void $classname$::set_$name$($type$ value) {\n"
     "  if (!has_$name$()) {\n"
     "    clear_$oneof_name$();\n"
     "    set_has_$name$();\n"
     "  }\n"
-    "  $oneof_prefix$$name$_ = value;\n"
+    "  $field_member$ = value;\n"
     "  // @@protoc_insertion_point(field_set:$full_name$)\n"
     "}\n");
 }
 
 void PrimitiveOneofFieldGenerator::
 GenerateClearingCode(io::Printer* printer) const {
-  printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n");
+  printer->Print(variables_, "$field_member$ = $default$;\n");
 }
 
 void PrimitiveOneofFieldGenerator::
@@ -239,9 +241,8 @@
 
 void PrimitiveOneofFieldGenerator::
 GenerateConstructorCode(io::Printer* printer) const {
-  printer->Print(
-      variables_,
-      "  $classname$_default_oneof_instance_->$name$_ = $default$;\n");
+  printer->Print(variables_,
+                 "$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
 }
 
 void PrimitiveOneofFieldGenerator::
@@ -250,16 +251,15 @@
     "clear_$oneof_name$();\n"
     "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
     "         $type$, $wire_format_field_type$>(\n"
-    "       input, &$oneof_prefix$$name$_)));\n"
+    "       input, &$field_member$)));\n"
     "set_has_$name$();\n");
 }
 
 // ===================================================================
 
-RepeatedPrimitiveFieldGenerator::
-RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
-                                const Options& options)
-  : descriptor_(descriptor) {
+RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
+    const FieldDescriptor* descriptor, const Options& options)
+    : FieldGenerator(options), descriptor_(descriptor) {
   SetPrimitiveVariables(descriptor, &variables_, options);
 
   if (descriptor->is_packed()) {
@@ -277,7 +277,8 @@
 GeneratePrivateMembers(io::Printer* printer) const {
   printer->Print(variables_,
     "::google::protobuf::RepeatedField< $type$ > $name$_;\n");
-  if (descriptor_->is_packed() && HasGeneratedMethods(descriptor_->file())) {
+  if (descriptor_->is_packed() &&
+      HasGeneratedMethods(descriptor_->file(), options_)) {
     printer->Print(variables_,
       "mutable int _$name$_cached_byte_size_;\n");
   }
@@ -286,40 +287,46 @@
 void RepeatedPrimitiveFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
-    "$type$ $name$(int index) const$deprecation$;\n"
-    "void set_$name$(int index, $type$ value)$deprecation$;\n"
-    "void add_$name$($type$ value)$deprecation$;\n");
+                 "$deprecated_attr$$type$ $name$(int index) const;\n");
+  printer->Annotate("name", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecated_attr$void ${$set_$name$$}$(int index, $type$ value);\n");
+  printer->Annotate("{", "}", descriptor_);
   printer->Print(variables_,
-    "const ::google::protobuf::RepeatedField< $type$ >&\n"
-    "    $name$() const$deprecation$;\n"
-    "::google::protobuf::RepeatedField< $type$ >*\n"
-    "    mutable_$name$()$deprecation$;\n");
+                 "$deprecated_attr$void ${$add_$name$$}$($type$ value);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$const ::google::protobuf::RepeatedField< $type$ >&\n"
+                 "    $name$() const;\n");
+  printer->Annotate("name", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$::google::protobuf::RepeatedField< $type$ >*\n"
+                 "    ${$mutable_$name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedPrimitiveFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
-  map<string, string> variables(variables_);
-  variables["inline"] = is_inline ? "inline" : "";
-  printer->Print(variables,
-    "$inline$ $type$ $classname$::$name$(int index) const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+  printer->Print(variables_,
+    "inline $type$ $classname$::$name$(int index) const {\n"
     "  // @@protoc_insertion_point(field_get:$full_name$)\n"
     "  return $name$_.Get(index);\n"
     "}\n"
-    "$inline$ void $classname$::set_$name$(int index, $type$ value) {\n"
+    "inline void $classname$::set_$name$(int index, $type$ value) {\n"
     "  $name$_.Set(index, value);\n"
     "  // @@protoc_insertion_point(field_set:$full_name$)\n"
     "}\n"
-    "$inline$ void $classname$::add_$name$($type$ value) {\n"
+    "inline void $classname$::add_$name$($type$ value) {\n"
     "  $name$_.Add(value);\n"
     "  // @@protoc_insertion_point(field_add:$full_name$)\n"
-    "}\n");
-  printer->Print(variables,
-    "$inline$ const ::google::protobuf::RepeatedField< $type$ >&\n"
+    "}\n"
+    "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
     "$classname$::$name$() const {\n"
     "  // @@protoc_insertion_point(field_list:$full_name$)\n"
     "  return $name$_;\n"
     "}\n"
-    "$inline$ ::google::protobuf::RepeatedField< $type$ >*\n"
+    "inline ::google::protobuf::RepeatedField< $type$ >*\n"
     "$classname$::mutable_$name$() {\n"
     "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
     "  return &$name$_;\n"
@@ -338,7 +345,7 @@
 
 void RepeatedPrimitiveFieldGenerator::
 GenerateSwappingCode(io::Printer* printer) const {
-  printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
+  printer->Print(variables_, "$name$_.InternalSwap(&other->$name$_);\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::
@@ -347,11 +354,16 @@
 }
 
 void RepeatedPrimitiveFieldGenerator::
+GenerateCopyConstructorCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.CopyFrom(from.$name$_);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) const {
   printer->Print(variables_,
     "DO_((::google::protobuf::internal::WireFormatLite::$repeated_reader$<\n"
     "         $type$, $wire_format_field_type$>(\n"
-    "       $tag_size$, $tag$, input, this->mutable_$name$())));\n");
+    "       $tag_size$, $tag$u, input, this->mutable_$name$())));\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::
@@ -364,6 +376,7 @@
 
 void RepeatedPrimitiveFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
+  bool array_written = false;
   if (descriptor_->is_packed()) {
     // Write the tag and the size.
     printer->Print(variables_,
@@ -372,21 +385,34 @@
           "$number$, "
           "::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, "
           "output);\n"
-      "  output->WriteVarint32(_$name$_cached_byte_size_);\n"
-      "}\n");
+      "  output->WriteVarint32(static_cast< ::google::protobuf::uint32>(\n"
+      "      _$name$_cached_byte_size_));\n");
+
+    if (FixedSize(descriptor_->type()) > 0) {
+      // TODO(ckennelly): Use RepeatedField<T>::unsafe_data() via
+      // WireFormatLite to access the contents of this->$name$_ to save a branch
+      // here.
+      printer->Print(variables_,
+        "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$Array(\n"
+        "    this->$name$().data(), this->$name$_size(), output);\n");
+      array_written = true;  // Wrote array all at once
+    }
+    printer->Print(variables_, "}\n");
   }
-  printer->Print(variables_,
-      "for (int i = 0; i < this->$name$_size(); i++) {\n");
-  if (descriptor_->is_packed()) {
+  if (!array_written) {
     printer->Print(variables_,
-      "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n"
-      "    this->$name$(i), output);\n");
-  } else {
-    printer->Print(variables_,
-      "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
-      "    $number$, this->$name$(i), output);\n");
+        "for (int i = 0, n = this->$name$_size(); i < n; i++) {\n");
+    if (descriptor_->is_packed()) {
+      printer->Print(variables_,
+        "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n"
+        "    this->$name$(i), output);\n");
+    } else {
+      printer->Print(variables_,
+        "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
+        "    $number$, this->$name$(i), output);\n");
+    }
+    printer->Print("}\n");
   }
-  printer->Print("}\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::
@@ -400,54 +426,50 @@
       "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
       "    target);\n"
       "  target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n"
-      "    _$name$_cached_byte_size_, target);\n"
-      "}\n");
-  }
-  printer->Print(variables_,
-      "for (int i = 0; i < this->$name$_size(); i++) {\n");
-  if (descriptor_->is_packed()) {
-    printer->Print(variables_,
+      "      static_cast< ::google::protobuf::int32>(\n"
+      "          _$name$_cached_byte_size_), target);\n"
       "  target = ::google::protobuf::internal::WireFormatLite::\n"
-      "    Write$declared_type$NoTagToArray(this->$name$(i), target);\n");
+      "    Write$declared_type$NoTagToArray(this->$name$_, target);\n"
+      "}\n");
   } else {
     printer->Print(variables_,
-      "  target = ::google::protobuf::internal::WireFormatLite::\n"
-      "    Write$declared_type$ToArray($number$, this->$name$(i), target);\n");
+      "target = ::google::protobuf::internal::WireFormatLite::\n"
+      "  Write$declared_type$ToArray($number$, this->$name$_, target);\n");
   }
-  printer->Print("}\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::
 GenerateByteSize(io::Printer* printer) const {
-  printer->Print(variables_,
-    "{\n"
-    "  int data_size = 0;\n");
+  printer->Print(variables_, "{\n");
   printer->Indent();
   int fixed_size = FixedSize(descriptor_->type());
   if (fixed_size == -1) {
     printer->Print(variables_,
-      "for (int i = 0; i < this->$name$_size(); i++) {\n"
-      "  data_size += ::google::protobuf::internal::WireFormatLite::\n"
-      "    $declared_type$Size(this->$name$(i));\n"
-      "}\n");
+      "size_t data_size = ::google::protobuf::internal::WireFormatLite::\n"
+      "  $declared_type$Size(this->$name$_);\n");
   } else {
     printer->Print(variables_,
-      "data_size = $fixed_size$ * this->$name$_size();\n");
+      "unsigned int count = static_cast<unsigned int>(this->$name$_size());\n"
+      "size_t data_size = $fixed_size$UL * count;\n");
   }
 
   if (descriptor_->is_packed()) {
     printer->Print(variables_,
       "if (data_size > 0) {\n"
       "  total_size += $tag_size$ +\n"
-      "    ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
+      "    ::google::protobuf::internal::WireFormatLite::Int32Size(\n"
+      "        static_cast< ::google::protobuf::int32>(data_size));\n"
       "}\n"
+      "int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);\n"
       "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
-      "_$name$_cached_byte_size_ = data_size;\n"
+      "_$name$_cached_byte_size_ = cached_size;\n"
       "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
       "total_size += data_size;\n");
   } else {
     printer->Print(variables_,
-      "total_size += $tag_size$ * this->$name$_size() + data_size;\n");
+      "total_size += $tag_size$ *\n"
+      "              ::google::protobuf::internal::FromIntSize(this->$name$_size());\n"
+      "total_size += data_size;\n");
   }
   printer->Outdent();
   printer->Print("}\n");
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
index fcd7d68..d52228e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
@@ -46,19 +46,19 @@
 
 class PrimitiveFieldGenerator : public FieldGenerator {
  public:
-  explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
-                                   const Options& options);
+  PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                          const Options& options);
   ~PrimitiveFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
   void GeneratePrivateMembers(io::Printer* printer) const;
   void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                         bool is_inline) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
@@ -66,7 +66,7 @@
 
  protected:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
@@ -74,13 +74,12 @@
 
 class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
  public:
-  explicit PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
-                                        const Options& options);
+  PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
+                               const Options& options);
   ~PrimitiveOneofFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                         bool is_inline) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
@@ -92,19 +91,19 @@
 
 class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
  public:
-  explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
-                                           const Options& options);
+  RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                                  const Options& options);
   ~RepeatedPrimitiveFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
   void GeneratePrivateMembers(io::Printer* printer) const;
   void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                         bool is_inline) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
@@ -113,7 +112,7 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
 };
diff --git a/src/google/protobuf/compiler/cpp/cpp_service.cc b/src/google/protobuf/compiler/cpp/cpp_service.cc
index 226c2aa..95357d9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_service.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_service.cc
@@ -46,6 +46,7 @@
                                    const Options& options)
   : descriptor_(descriptor) {
   vars_["classname"] = descriptor_->name();
+  vars_["file_namespace"] = FileLevelNamespace(descriptor_->file()->name());
   vars_["full_name"] = descriptor_->full_name();
   if (options.dllexport_decl.empty()) {
     vars_["dllexport"] = "";
@@ -143,7 +144,7 @@
     VirtualOrNon virtual_or_non, io::Printer* printer) {
   for (int i = 0; i < descriptor_->method_count(); i++) {
     const MethodDescriptor* method = descriptor_->method(i);
-    map<string, string> sub_vars;
+    std::map<string, string> sub_vars;
     sub_vars["name"] = method->name();
     sub_vars["input_type"] = ClassName(method->input_type(), true);
     sub_vars["output_type"] = ClassName(method->output_type(), true);
@@ -161,7 +162,7 @@
 
 void ServiceGenerator::GenerateDescriptorInitializer(
     io::Printer* printer, int index) {
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["classname"] = descriptor_->name();
   vars["index"] = SimpleItoa(index);
 
@@ -172,19 +173,20 @@
 // ===================================================================
 
 void ServiceGenerator::GenerateImplementation(io::Printer* printer) {
-  printer->Print(vars_,
-    "$classname$::~$classname$() {}\n"
-    "\n"
-    "const ::google::protobuf::ServiceDescriptor* $classname$::descriptor() {\n"
-    "  protobuf_AssignDescriptorsOnce();\n"
-    "  return $classname$_descriptor_;\n"
-    "}\n"
-    "\n"
-    "const ::google::protobuf::ServiceDescriptor* $classname$::GetDescriptor() {\n"
-    "  protobuf_AssignDescriptorsOnce();\n"
-    "  return $classname$_descriptor_;\n"
-    "}\n"
-    "\n");
+  vars_["index"] = SimpleItoa(index_in_metadata_);
+  printer->Print(
+      vars_,
+      "$classname$::~$classname$() {}\n"
+      "\n"
+      "const ::google::protobuf::ServiceDescriptor* $classname$::descriptor() {\n"
+      "  $file_namespace$::protobuf_AssignDescriptorsOnce();\n"
+      "  return $file_namespace$::file_level_service_descriptors[$index$];\n"
+      "}\n"
+      "\n"
+      "const ::google::protobuf::ServiceDescriptor* $classname$::GetDescriptor() {\n"
+      "  return descriptor();\n"
+      "}\n"
+      "\n");
 
   // Generate methods of the interface.
   GenerateNotImplementedMethods(printer);
@@ -212,7 +214,7 @@
 void ServiceGenerator::GenerateNotImplementedMethods(io::Printer* printer) {
   for (int i = 0; i < descriptor_->method_count(); i++) {
     const MethodDescriptor* method = descriptor_->method(i);
-    map<string, string> sub_vars;
+    std::map<string, string> sub_vars;
     sub_vars["classname"] = descriptor_->name();
     sub_vars["name"] = method->name();
     sub_vars["index"] = SimpleItoa(i);
@@ -232,18 +234,20 @@
 }
 
 void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
-  printer->Print(vars_,
-    "void $classname$::CallMethod(const ::google::protobuf::MethodDescriptor* method,\n"
-    "                             ::google::protobuf::RpcController* controller,\n"
-    "                             const ::google::protobuf::Message* request,\n"
-    "                             ::google::protobuf::Message* response,\n"
-    "                             ::google::protobuf::Closure* done) {\n"
-    "  GOOGLE_DCHECK_EQ(method->service(), $classname$_descriptor_);\n"
-    "  switch(method->index()) {\n");
+  printer->Print(
+      vars_,
+      "void $classname$::CallMethod(const ::google::protobuf::MethodDescriptor* method,\n"
+      "                             ::google::protobuf::RpcController* controller,\n"
+      "                             const ::google::protobuf::Message* request,\n"
+      "                             ::google::protobuf::Message* response,\n"
+      "                             ::google::protobuf::Closure* done) {\n"
+      "  GOOGLE_DCHECK_EQ(method->service(), "
+      "$file_namespace$::file_level_service_descriptors[$index$]);\n"
+      "  switch(method->index()) {\n");
 
   for (int i = 0; i < descriptor_->method_count(); i++) {
     const MethodDescriptor* method = descriptor_->method(i);
-    map<string, string> sub_vars;
+    std::map<string, string> sub_vars;
     sub_vars["name"] = method->name();
     sub_vars["index"] = SimpleItoa(i);
     sub_vars["input_type"] = ClassName(method->input_type(), true);
@@ -289,7 +293,7 @@
     const Descriptor* type =
       (which == REQUEST) ? method->input_type() : method->output_type();
 
-    map<string, string> sub_vars;
+    std::map<string, string> sub_vars;
     sub_vars["index"] = SimpleItoa(i);
     sub_vars["type"] = ClassName(type, true);
 
@@ -298,19 +302,21 @@
       "      return $type$::default_instance();\n");
   }
 
-  printer->Print(vars_,
+  printer->Print(
     "    default:\n"
     "      GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n"
-    "      return *static_cast< ::google::protobuf::Message*>(NULL);\n"
+    "      return *::google::protobuf::MessageFactory::generated_factory()\n"
+    "          ->GetPrototype(method->$input_or_output$_type());\n"
     "  }\n"
     "}\n"
-    "\n");
+    "\n",
+    "input_or_output", which == REQUEST ? "input" : "output");
 }
 
 void ServiceGenerator::GenerateStubMethods(io::Printer* printer) {
   for (int i = 0; i < descriptor_->method_count(); i++) {
     const MethodDescriptor* method = descriptor_->method(i);
-    map<string, string> sub_vars;
+    std::map<string, string> sub_vars;
     sub_vars["classname"] = descriptor_->name();
     sub_vars["name"] = method->name();
     sub_vars["index"] = SimpleItoa(i);
diff --git a/src/google/protobuf/compiler/cpp/cpp_service.h b/src/google/protobuf/compiler/cpp/cpp_service.h
index ede2fd8..33c0254 100644
--- a/src/google/protobuf/compiler/cpp/cpp_service.h
+++ b/src/google/protobuf/compiler/cpp/cpp_service.h
@@ -105,8 +105,11 @@
   void GenerateStubMethods(io::Printer* printer);
 
   const ServiceDescriptor* descriptor_;
-  map<string, string> vars_;
+  std::map<string, string> vars_;
 
+  int index_in_metadata_;
+
+  friend class FileGenerator;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator);
 };
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 6b0821a..cf6c4b3 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -34,8 +34,9 @@
 
 #include <google/protobuf/compiler/cpp/cpp_string_field.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
-#include <google/protobuf/io/printer.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+
 #include <google/protobuf/stubs/strutil.h>
 
 namespace google {
@@ -46,22 +47,22 @@
 namespace {
 
 void SetStringVariables(const FieldDescriptor* descriptor,
-                        map<string, string>* variables,
+                        std::map<string, string>* variables,
                         const Options& options) {
   SetCommonFieldVariables(descriptor, variables, options);
   (*variables)["default"] = DefaultValue(descriptor);
   (*variables)["default_length"] =
       SimpleItoa(descriptor->default_value_string().length());
-  string default_variable_string =
+  string default_variable_string = MakeDefaultName(descriptor);
+  (*variables)["default_variable_name"] = default_variable_string;
+  (*variables)["default_variable"] =
       descriptor->default_value_string().empty()
           ? "&::google::protobuf::internal::GetEmptyStringAlreadyInited()"
-          : "_default_" + FieldName(descriptor) + "_";
-  (*variables)["default_variable"] = default_variable_string;
-  (*variables)["default_value_init"] =
-      descriptor->default_value_string().empty()
-      ? "" : "*" + default_variable_string;
+          : "&" + Namespace(descriptor) + "::" + (*variables)["classname"] +
+                "::" + default_variable_string + ".get()";
   (*variables)["pointer_type"] =
       descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
+  (*variables)["null_check"] = "GOOGLE_DCHECK(value != NULL);\n";
   // NOTE: Escaped here to unblock proto1->proto2 migration.
   // TODO(liujisi): Extend this to apply for other conflicting methods.
   (*variables)["release_name"] =
@@ -70,16 +71,35 @@
   (*variables)["full_name"] = descriptor->full_name();
 
   (*variables)["string_piece"] = "::std::string";
+
+  (*variables)["lite"] =
+      HasDescriptorMethods(descriptor->file(), options) ? "" : "Lite";
 }
 
 }  // namespace
 
 // ===================================================================
 
-StringFieldGenerator::
-StringFieldGenerator(const FieldDescriptor* descriptor,
-                     const Options& options)
-  : descriptor_(descriptor) {
+StringFieldGenerator::StringFieldGenerator(const FieldDescriptor* descriptor,
+                                           const Options& options)
+    : FieldGenerator(options),
+      descriptor_(descriptor),
+      lite_(!HasDescriptorMethods(descriptor->file(), options)),
+      inlined_(false) {
+
+  // TODO(ckennelly): Handle inlining for any.proto.
+  if (IsAnyMessage(descriptor_->containing_type())) {
+    inlined_ = false;
+  }
+  if (descriptor_->containing_type()->options().map_entry()) {
+    inlined_ = false;
+  }
+
+  // Limit to proto2, as we rely on has bits to distinguish field presence for
+  // release_$name$.  On proto3, we cannot use the address of the string
+  // instance when the field has been inlined.
+  inlined_ = inlined_ && HasFieldPresence(descriptor_->file());
+
   SetStringVariables(descriptor, &variables_, options);
 }
 
@@ -87,25 +107,36 @@
 
 void StringFieldGenerator::
 GeneratePrivateMembers(io::Printer* printer) const {
-  // N.B. that we continue to use |ArenaStringPtr| instead of |string*| for
-  // string fields, even when SupportArenas(descriptor_) == false. Why?
-  // The simple answer is to avoid unmaintainable complexity. The reflection
-  // code assumes ArenaStringPtrs. These are *almost* in-memory-compatible with
-  // string*, except for the pointer tags and related ownership semantics. We
-  // could modify the runtime code to use string* for the not-supporting-arenas
-  // case, but this would require a way to detect which type of class was
-  // generated (adding overhead and complexity to GeneratedMessageReflection)
-  // and littering the runtime code paths with conditionals. It's simpler to
-  // stick with this but use lightweight accessors that assume arena == NULL.
-  // There should be very little overhead anyway because it's just a tagged
-  // pointer in-memory.
-  printer->Print(variables_, "::google::protobuf::internal::ArenaStringPtr $name$_;\n");
+  if (inlined_) {
+    printer->Print(variables_,
+                   "::google::protobuf::internal::InlinedStringField $name$_;\n");
+  } else {
+    // N.B. that we continue to use |ArenaStringPtr| instead of |string*| for
+    // string fields, even when SupportArenas(descriptor_) == false. Why?  The
+    // simple answer is to avoid unmaintainable complexity. The reflection code
+    // assumes ArenaStringPtrs. These are *almost* in-memory-compatible with
+    // string*, except for the pointer tags and related ownership semantics. We
+    // could modify the runtime code to use string* for the
+    // not-supporting-arenas case, but this would require a way to detect which
+    // type of class was generated (adding overhead and complexity to
+    // GeneratedMessageReflection) and littering the runtime code paths with
+    // conditionals. It's simpler to stick with this but use lightweight
+    // accessors that assume arena == NULL.  There should be very little
+    // overhead anyway because it's just a tagged pointer in-memory.
+    printer->Print(variables_, "::google::protobuf::internal::ArenaStringPtr $name$_;\n");
+  }
 }
 
 void StringFieldGenerator::
 GenerateStaticMembers(io::Printer* printer) const {
   if (!descriptor_->default_value_string().empty()) {
-    printer->Print(variables_, "static ::std::string* $default_variable$;\n");
+    // We make the default instance public, so it can be initialized by
+    // non-friend code.
+    printer->Print(variables_,
+                   "public:\n"
+                   "static ::google::protobuf::internal::ExplicitlyConstructed< ::std::string>"
+                   " $default_variable_name$;\n"
+                   "private:\n");
   }
 }
 
@@ -140,21 +171,54 @@
   }
 
   printer->Print(variables_,
-    "const ::std::string& $name$() const$deprecation$;\n"
-    "void set_$name$(const ::std::string& value)$deprecation$;\n"
-    "void set_$name$(const char* value)$deprecation$;\n"
-    "void set_$name$(const $pointer_type$* value, size_t size)"
-                 "$deprecation$;\n"
-    "::std::string* mutable_$name$()$deprecation$;\n"
-    "::std::string* $release_name$()$deprecation$;\n"
-    "void set_allocated_$name$(::std::string* $name$)$deprecation$;\n");
-  if (SupportsArenas(descriptor_)) {
-    printer->Print(variables_,
-      "::std::string* unsafe_arena_release_$name$()$deprecation$;\n"
-      "void unsafe_arena_set_allocated_$name$(\n"
-      "    ::std::string* $name$)$deprecation$;\n");
-  }
+                 "$deprecated_attr$const ::std::string& $name$() const;\n");
+  printer->Annotate("name", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecated_attr$void ${$set_$name$$}$(const ::std::string& value);\n");
+  printer->Annotate("{", "}", descriptor_);
 
+  printer->Print(variables_,
+                 "#if LANG_CXX11\n"
+                 "$deprecated_attr$void ${$set_$name$$}$(::std::string&& value);\n"
+                 "#endif\n");
+  printer->Annotate("{", "}", descriptor_);
+
+  printer->Print(
+      variables_,
+      "$deprecated_attr$void ${$set_$name$$}$(const char* value);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$void ${$set_$name$$}$(const $pointer_type$* "
+                 "value, size_t size)"
+                 ";\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$::std::string* ${$mutable_$name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_, "$deprecated_attr$::std::string* $release_name$();\n");
+  printer->Annotate("release_name", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecated_attr$void ${$set_allocated_$name$$}$(::std::string* $name$);\n");
+  printer->Annotate("{", "}", descriptor_);
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(
+        variables_,
+        "PROTOBUF_RUNTIME_DEPRECATED(\"The unsafe_arena_ accessors for\"\n"
+        "\"    string fields are deprecated and will be removed in a\"\n"
+        "\"    future release.\")\n"
+        "::std::string* ${$unsafe_arena_release_$name$$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
+    printer->Print(
+        variables_,
+        "PROTOBUF_RUNTIME_DEPRECATED(\"The unsafe_arena_ accessors for\"\n"
+        "\"    string fields are deprecated and will be removed in a\"\n"
+        "\"    future release.\")\n"
+        "void ${$unsafe_arena_set_allocated_$name$$}$(\n"
+        "    ::std::string* $name$);\n");
+    printer->Annotate("{", "}", descriptor_);
+  }
 
   if (unknown_ctype) {
     printer->Outdent();
@@ -164,115 +228,165 @@
 }
 
 void StringFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                  bool is_inline) const {
-  map<string, string> variables(variables_);
-  variables["inline"] = is_inline ? "inline" : "";
+GenerateInlineAccessorDefinitions(io::Printer* printer) const {
   if (SupportsArenas(descriptor_)) {
-    printer->Print(variables,
-      "$inline$ const ::std::string& $classname$::$name$() const {\n"
-      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
-      "  return $name$_.Get($default_variable$);\n"
-      "}\n"
-      "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
-      "  $set_hasbit$\n"
-      "  $name$_.Set($default_variable$, value, GetArenaNoVirtual());\n"
-      "  // @@protoc_insertion_point(field_set:$full_name$)\n"
-      "}\n"
-      "$inline$ void $classname$::set_$name$(const char* value) {\n"
-      "  $set_hasbit$\n"
-      "  $name$_.Set($default_variable$, $string_piece$(value),\n"
-      "              GetArenaNoVirtual());\n"
-      "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
-      "}\n"
-      "$inline$ "
-      "void $classname$::set_$name$(const $pointer_type$* value,\n"
-      "    size_t size) {\n"
-      "  $set_hasbit$\n"
-      "  $name$_.Set($default_variable$, $string_piece$(\n"
-      "      reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());\n"
-      "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
-      "}\n"
-      "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
-      "  $set_hasbit$\n"
-      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
-      "  return $name$_.Mutable($default_variable$, GetArenaNoVirtual());\n"
-      "}\n"
-      "$inline$ ::std::string* $classname$::$release_name$() {\n"
-      "  $clear_hasbit$\n"
-      "  return $name$_.Release($default_variable$, GetArenaNoVirtual());\n"
-      "}\n"
-      "$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
-      "  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
-      "  $clear_hasbit$\n"
-      "  return $name$_.UnsafeArenaRelease($default_variable$,\n"
-      "      GetArenaNoVirtual());\n"
-      "}\n"
-      "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
-      "  if ($name$ != NULL) {\n"
-      "    $set_hasbit$\n"
-      "  } else {\n"
-      "    $clear_hasbit$\n"
-      "  }\n"
-      "  $name$_.SetAllocated($default_variable$, $name$,\n"
-      "      GetArenaNoVirtual());\n"
-      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
-      "}\n"
-      "$inline$ void $classname$::unsafe_arena_set_allocated_$name$(\n"
-      "    ::std::string* $name$) {\n"
-      "  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
-      "  if ($name$ != NULL) {\n"
-      "    $set_hasbit$\n"
-      "  } else {\n"
-      "    $clear_hasbit$\n"
-      "  }\n"
-      "  $name$_.UnsafeArenaSetAllocated($default_variable$,\n"
-      "      $name$, GetArenaNoVirtual());\n"
-      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
-      "}\n");
+    printer->Print(
+        variables_,
+        "inline const ::std::string& $classname$::$name$() const {\n"
+        "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+        "  return $name$_.Get();\n"
+        "}\n"
+        "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+        "  $set_hasbit$\n"
+        "  $name$_.Set$lite$($default_variable$, value, GetArenaNoVirtual());\n"
+        "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+        "}\n"
+        "#if LANG_CXX11\n"
+        "inline void $classname$::set_$name$(::std::string&& value) {\n"
+        "  $set_hasbit$\n"
+        "  $name$_.Set$lite$(\n"
+        "    $default_variable$, ::std::move(value), GetArenaNoVirtual());\n"
+        "  // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
+        "}\n"
+        "#endif\n"
+        "inline void $classname$::set_$name$(const char* value) {\n"
+        "  $null_check$"
+        "  $set_hasbit$\n"
+        "  $name$_.Set$lite$($default_variable$, $string_piece$(value),\n"
+        "              GetArenaNoVirtual());\n"
+        "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
+        "}\n"
+        "inline "
+        "void $classname$::set_$name$(const $pointer_type$* value,\n"
+        "    size_t size) {\n"
+        "  $set_hasbit$\n"
+        "  $name$_.Set$lite$($default_variable$, $string_piece$(\n"
+        "      reinterpret_cast<const char*>(value), size), "
+        "GetArenaNoVirtual());\n"
+        "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
+        "}\n"
+        "inline ::std::string* $classname$::mutable_$name$() {\n"
+        "  $set_hasbit$\n"
+        "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+        "  return $name$_.Mutable($default_variable$, GetArenaNoVirtual());\n"
+        "}\n"
+        "inline ::std::string* $classname$::$release_name$() {\n"
+        "  // @@protoc_insertion_point(field_release:$full_name$)\n");
+
+    if (HasFieldPresence(descriptor_->file())) {
+      printer->Print(variables_,
+        "  if (!has_$name$()) {\n"
+        "    return NULL;\n"
+        "  }\n"
+        "  $clear_hasbit$\n"
+        "  return $name$_.ReleaseNonDefault("
+        "$default_variable$, GetArenaNoVirtual());\n");
+    } else {
+      printer->Print(variables_,
+        "  $clear_hasbit$\n"
+        "  return $name$_.Release($default_variable$, GetArenaNoVirtual());\n");
+    }
+
+    printer->Print(variables_,
+        "}\n"
+        "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+        "  if ($name$ != NULL) {\n"
+        "    $set_hasbit$\n"
+        "  } else {\n"
+        "    $clear_hasbit$\n"
+        "  }\n"
+        "  $name$_.SetAllocated($default_variable$, $name$,\n"
+        "      GetArenaNoVirtual());\n"
+        "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+        "}\n"
+        "inline ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
+        "  // "
+        "@@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
+        "  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
+        "  $clear_hasbit$\n"
+        "  return $name$_.UnsafeArenaRelease($default_variable$,\n"
+        "      GetArenaNoVirtual());\n"
+        "}\n"
+        "inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
+        "    ::std::string* $name$) {\n"
+        "  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
+        "  if ($name$ != NULL) {\n"
+        "    $set_hasbit$\n"
+        "  } else {\n"
+        "    $clear_hasbit$\n"
+        "  }\n"
+        "  $name$_.UnsafeArenaSetAllocated($default_variable$,\n"
+        "      $name$, GetArenaNoVirtual());\n"
+        "  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
+        "$full_name$)\n"
+        "}\n");
   } else {
     // No-arena case.
-    printer->Print(variables,
-      "$inline$ const ::std::string& $classname$::$name$() const {\n"
-      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
-      "  return $name$_.GetNoArena($default_variable$);\n"
-      "}\n"
-      "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
-      "  $set_hasbit$\n"
-      "  $name$_.SetNoArena($default_variable$, value);\n"
-      "  // @@protoc_insertion_point(field_set:$full_name$)\n"
-      "}\n"
-      "$inline$ void $classname$::set_$name$(const char* value) {\n"
-      "  $set_hasbit$\n"
-      "  $name$_.SetNoArena($default_variable$, $string_piece$(value));\n"
-      "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
-      "}\n"
-      "$inline$ "
-      "void $classname$::set_$name$(const $pointer_type$* value, "
-      "size_t size) {\n"
-      "  $set_hasbit$\n"
-      "  $name$_.SetNoArena($default_variable$,\n"
-      "      $string_piece$(reinterpret_cast<const char*>(value), size));\n"
-      "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
-      "}\n"
-      "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
-      "  $set_hasbit$\n"
-      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
-      "  return $name$_.MutableNoArena($default_variable$);\n"
-      "}\n"
-      "$inline$ ::std::string* $classname$::$release_name$() {\n"
-      "  $clear_hasbit$\n"
-      "  return $name$_.ReleaseNoArena($default_variable$);\n"
-      "}\n"
-      "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
-      "  if ($name$ != NULL) {\n"
-      "    $set_hasbit$\n"
-      "  } else {\n"
-      "    $clear_hasbit$\n"
-      "  }\n"
-      "  $name$_.SetAllocatedNoArena($default_variable$, $name$);\n"
-      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
-      "}\n");
+    printer->Print(
+        variables_,
+        "inline const ::std::string& $classname$::$name$() const {\n"
+        "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+        "  return $name$_.GetNoArena();\n"
+        "}\n"
+        "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+        "  $set_hasbit$\n"
+        "  $name$_.SetNoArena($default_variable$, value);\n"
+        "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+        "}\n"
+        "#if LANG_CXX11\n"
+        "inline void $classname$::set_$name$(::std::string&& value) {\n"
+        "  $set_hasbit$\n"
+        "  $name$_.SetNoArena(\n"
+        "    $default_variable$, ::std::move(value));\n"
+        "  // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
+        "}\n"
+        "#endif\n"
+        "inline void $classname$::set_$name$(const char* value) {\n"
+        "  $null_check$"
+        "  $set_hasbit$\n"
+        "  $name$_.SetNoArena($default_variable$, $string_piece$(value));\n"
+        "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
+        "}\n"
+        "inline "
+        "void $classname$::set_$name$(const $pointer_type$* value, "
+        "size_t size) {\n"
+        "  $set_hasbit$\n"
+        "  $name$_.SetNoArena($default_variable$,\n"
+        "      $string_piece$(reinterpret_cast<const char*>(value), size));\n"
+        "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
+        "}\n"
+        "inline ::std::string* $classname$::mutable_$name$() {\n"
+        "  $set_hasbit$\n"
+        "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+        "  return $name$_.MutableNoArena($default_variable$);\n"
+        "}\n"
+        "inline ::std::string* $classname$::$release_name$() {\n"
+        "  // @@protoc_insertion_point(field_release:$full_name$)\n");
+
+    if (HasFieldPresence(descriptor_->file())) {
+      printer->Print(variables_,
+        "  if (!has_$name$()) {\n"
+        "    return NULL;\n"
+        "  }\n"
+        "  $clear_hasbit$\n"
+        "  return $name$_.ReleaseNonDefaultNoArena($default_variable$);\n");
+    } else {
+      printer->Print(variables_,
+        "  $clear_hasbit$\n"
+        "  return $name$_.ReleaseNoArena($default_variable$);\n");
+    }
+
+    printer->Print(variables_,
+        "}\n"
+        "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+        "  if ($name$ != NULL) {\n"
+        "    $set_hasbit$\n"
+        "  } else {\n"
+        "    $clear_hasbit$\n"
+        "  }\n"
+        "  $name$_.SetAllocatedNoArena($default_variable$, $name$);\n"
+        "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+        "}\n");
   }
 }
 
@@ -281,7 +395,8 @@
   if (!descriptor_->default_value_string().empty()) {
     // Initialized in GenerateDefaultInstanceAllocator.
     printer->Print(variables_,
-      "::std::string* $classname$::$default_variable$ = NULL;\n");
+                   "::google::protobuf::internal::ExplicitlyConstructed<::std::string> "
+                   "$classname$::$default_variable_name$;\n");
   }
 }
 
@@ -311,6 +426,68 @@
 }
 
 void StringFieldGenerator::
+GenerateMessageClearingCode(io::Printer* printer) const {
+  // Two-dimension specialization here: supporting arenas, field presence, or
+  // not, and default value is the empty string or not. Complexity here ensures
+  // the minimal number of branches / amount of extraneous code at runtime
+  // (given that the below methods are inlined one-liners)!
+
+  // If we have field presence, then the Clear() method of the protocol buffer
+  // will have checked that this field is set.  If so, we can avoid redundant
+  // checks against default_variable.
+  const bool must_be_present =
+      HasFieldPresence(descriptor_->file());
+
+  if (inlined_ && must_be_present) {
+    // Calling mutable_$name$() gives us a string reference and sets the has bit
+    // for $name$ (in proto2).  We may get here when the string field is inlined
+    // but the string's contents have not been changed by the user, so we cannot
+    // make an assertion about the contents of the string and could never make
+    // an assertion about the string instance.
+    //
+    // For non-inlined strings, we distinguish from non-default by comparing
+    // instances, rather than contents.
+    printer->Print(variables_,
+      "GOOGLE_DCHECK(!$name$_.IsDefault($default_variable$));\n");
+  }
+
+  if (SupportsArenas(descriptor_)) {
+    if (descriptor_->default_value_string().empty()) {
+      if (must_be_present) {
+        printer->Print(variables_,
+          "$name$_.ClearNonDefaultToEmpty();\n");
+      } else {
+        printer->Print(variables_,
+          "$name$_.ClearToEmpty($default_variable$, GetArenaNoVirtual());\n");
+      }
+    } else {
+      // Clear to a non-empty default is more involved, as we try to use the
+      // Arena if one is present and may need to reallocate the string.
+      printer->Print(variables_,
+        "$name$_.ClearToDefault($default_variable$, GetArenaNoVirtual());\n");
+    }
+  } else if (must_be_present) {
+    // When Arenas are disabled and field presence has been checked, we can
+    // safely treat the ArenaStringPtr as a string*.
+    if (descriptor_->default_value_string().empty()) {
+      printer->Print(variables_, "$name$_.ClearNonDefaultToEmptyNoArena();\n");
+    } else {
+      printer->Print(
+          variables_,
+          "$name$_.UnsafeMutablePointer()->assign(*$default_variable$);\n");
+    }
+  } else {
+    if (descriptor_->default_value_string().empty()) {
+      printer->Print(variables_,
+        "$name$_.ClearToEmptyNoArena($default_variable$);\n");
+    } else {
+      printer->Print(variables_,
+        "$name$_.ClearToDefaultNoArena($default_variable$);\n");
+    }
+  }
+}
+
+void StringFieldGenerator::
 GenerateMergingCode(io::Printer* printer) const {
   if (SupportsArenas(descriptor_) || descriptor_->containing_oneof() != NULL) {
     // TODO(gpike): improve this
@@ -324,40 +501,91 @@
 
 void StringFieldGenerator::
 GenerateSwappingCode(io::Printer* printer) const {
-  printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
+  if (inlined_) {
+    printer->Print(
+        variables_,
+        "$name$_.Swap(&other->$name$_);\n");
+  } else {
+    printer->Print(
+        variables_,
+        "$name$_.Swap(&other->$name$_, $default_variable$,\n"
+        "  GetArenaNoVirtual());\n");
+  }
 }
 
 void StringFieldGenerator::
 GenerateConstructorCode(io::Printer* printer) const {
+  // TODO(ckennelly): Construct non-empty strings as part of the initializer
+  // list.
+  if (inlined_ && descriptor_->default_value_string().empty()) {
+    // Automatic initialization will construct the string.
+    return;
+  }
+
   printer->Print(variables_,
-      "$name$_.UnsafeSetDefault($default_variable$);\n");
+                 "$name$_.UnsafeSetDefault($default_variable$);\n");
+}
+
+void StringFieldGenerator::
+GenerateCopyConstructorCode(io::Printer* printer) const {
+  GenerateConstructorCode(printer);
+
+  if (HasFieldPresence(descriptor_->file())) {
+    printer->Print(variables_,
+        "if (from.has_$name$()) {\n");
+  } else {
+    printer->Print(variables_,
+        "if (from.$name$().size() > 0) {\n");
+  }
+
+  printer->Indent();
+
+  if (SupportsArenas(descriptor_) || descriptor_->containing_oneof() != NULL) {
+    // TODO(gpike): improve this
+    printer->Print(variables_,
+      "$name$_.Set$lite$($default_variable$, from.$name$(),\n"
+      "  GetArenaNoVirtual());\n");
+  } else {
+    printer->Print(variables_,
+      "$name$_.AssignWithDefault($default_variable$, from.$name$_);\n");
+  }
+
+  printer->Outdent();
+  printer->Print("}\n");
 }
 
 void StringFieldGenerator::
 GenerateDestructorCode(io::Printer* printer) const {
-  if (SupportsArenas(descriptor_)) {
-    printer->Print(variables_,
-      "$name$_.Destroy($default_variable$, GetArenaNoVirtual());\n");
-  } else {
-    printer->Print(variables_,
-      "$name$_.DestroyNoArena($default_variable$);\n");
+  if (inlined_) {
+    // The destructor is automatically invoked.
+    return;
   }
+
+  printer->Print(variables_, "$name$_.DestroyNoArena($default_variable$);\n");
+}
+
+bool StringFieldGenerator::GenerateArenaDestructorCode(
+    io::Printer* printer) const {
+  if (!inlined_) {
+    return false;
+  }
+
+  printer->Print(variables_,
+                 "_this->$name$_.DestroyNoArena($default_variable$);\n");
+  return true;
 }
 
 void StringFieldGenerator::
 GenerateDefaultInstanceAllocator(io::Printer* printer) const {
   if (!descriptor_->default_value_string().empty()) {
-    printer->Print(variables_,
-      "$classname$::$default_variable$ =\n"
-      "    new ::std::string($default$, $default_length$);\n");
-  }
-}
-
-void StringFieldGenerator::
-GenerateShutdownCode(io::Printer* printer) const {
-  if (!descriptor_->default_value_string().empty()) {
-    printer->Print(variables_,
-      "delete $classname$::$default_variable$;\n");
+    printer->Print(
+        variables_,
+        "$ns$::$classname$::$default_variable_name$.DefaultConstruct();\n"
+        "*$ns$::$classname$::$default_variable_name$.get_mutable() = "
+        "::std::string($default$, $default_length$);\n"
+        "::google::protobuf::internal::OnShutdownDestroyString(\n"
+        "    $ns$::$classname$::$default_variable_name$.get_mutable());\n"
+    );
   }
 }
 
@@ -369,17 +597,24 @@
 
   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
     GenerateUtf8CheckCodeForString(
-        descriptor_, true, variables_,
-        "this->$name$().data(), this->$name$().length(),\n", printer);
+        descriptor_, options_, true, variables_,
+        "this->$name$().data(), static_cast<int>(this->$name$().length()),\n",
+        printer);
   }
 }
 
+bool StringFieldGenerator::
+MergeFromCodedStreamNeedsArena() const {
+  return false;
+}
+
 void StringFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
     GenerateUtf8CheckCodeForString(
-        descriptor_, false, variables_,
-        "this->$name$().data(), this->$name$().length(),\n", printer);
+        descriptor_, options_, false, variables_,
+        "this->$name$().data(), static_cast<int>(this->$name$().length()),\n",
+        printer);
   }
   printer->Print(variables_,
     "::google::protobuf::internal::WireFormatLite::Write$declared_type$MaybeAliased(\n"
@@ -390,8 +625,9 @@
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
     GenerateUtf8CheckCodeForString(
-        descriptor_, false, variables_,
-        "this->$name$().data(), this->$name$().length(),\n", printer);
+        descriptor_, options_, false, variables_,
+        "this->$name$().data(), static_cast<int>(this->$name$().length()),\n",
+        printer);
   }
   printer->Print(variables_,
     "target =\n"
@@ -407,247 +643,265 @@
     "    this->$name$());\n");
 }
 
+uint32 StringFieldGenerator::CalculateFieldTag() const {
+  return inlined_ ? 1 : 0;
+}
+
 // ===================================================================
 
-StringOneofFieldGenerator::
-StringOneofFieldGenerator(const FieldDescriptor* descriptor,
-                          const Options& options)
-    : StringFieldGenerator(descriptor, options),
-      dependent_field_(options.proto_h) {
+StringOneofFieldGenerator::StringOneofFieldGenerator(
+    const FieldDescriptor* descriptor, const Options& options)
+    : StringFieldGenerator(descriptor, options) {
+  inlined_ = false;
+
   SetCommonOneofFieldVariables(descriptor, &variables_);
 }
 
 StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
 
 void StringOneofFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                  bool is_inline) const {
-  map<string, string> variables(variables_);
-  variables["inline"] = is_inline ? "inline" : "";
+GenerateInlineAccessorDefinitions(io::Printer* printer) const {
   if (SupportsArenas(descriptor_)) {
-    printer->Print(variables,
-      "$inline$ const ::std::string& $classname$::$name$() const {\n"
-      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
-      "  if (has_$name$()) {\n"
-      "    return $oneof_prefix$$name$_.Get($default_variable$);\n"
-      "  }\n"
-      "  return *$default_variable$;\n"
-      "}\n"
-      "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
-      "  if (!has_$name$()) {\n"
-      "    clear_$oneof_name$();\n"
-      "    set_has_$name$();\n"
-      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
-      "  }\n"
-      "  $oneof_prefix$$name$_.Set($default_variable$, value,\n"
-      "      GetArenaNoVirtual());\n"
-      "  // @@protoc_insertion_point(field_set:$full_name$)\n"
-      "}\n"
-      "$inline$ void $classname$::set_$name$(const char* value) {\n"
-      "  if (!has_$name$()) {\n"
-      "    clear_$oneof_name$();\n"
-      "    set_has_$name$();\n"
-      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
-      "  }\n"
-      "  $oneof_prefix$$name$_.Set($default_variable$,\n"
-      "      $string_piece$(value), GetArenaNoVirtual());\n"
-      "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
-      "}\n"
-      "$inline$ "
-      "void $classname$::set_$name$(const $pointer_type$* value,\n"
-      "                             size_t size) {\n"
-      "  if (!has_$name$()) {\n"
-      "    clear_$oneof_name$();\n"
-      "    set_has_$name$();\n"
-      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
-      "  }\n"
-      "  $oneof_prefix$$name$_.Set($default_variable$, $string_piece$(\n"
-      "      reinterpret_cast<const char*>(value), size),\n"
-      "      GetArenaNoVirtual());\n"
-      "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
-      "}\n"
-      "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
-      "  if (!has_$name$()) {\n"
-      "    clear_$oneof_name$();\n"
-      "    set_has_$name$();\n"
-      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
-      "  }\n"
-      "  return $oneof_prefix$$name$_.Mutable($default_variable$,\n"
-      "      GetArenaNoVirtual());\n"
-      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
-      "}\n"
-      "$inline$ ::std::string* $classname$::$release_name$() {\n"
-      "  if (has_$name$()) {\n"
-      "    clear_has_$oneof_name$();\n"
-      "    return $oneof_prefix$$name$_.Release($default_variable$,\n"
-      "        GetArenaNoVirtual());\n"
-      "  } else {\n"
-      "    return NULL;\n"
-      "  }\n"
-      "}\n"
-      "$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
-      "  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
-      "  if (has_$name$()) {\n"
-      "    clear_has_$oneof_name$();\n"
-      "    return $oneof_prefix$$name$_.UnsafeArenaRelease(\n"
-      "        $default_variable$, GetArenaNoVirtual());\n"
-      "  } else {\n"
-      "    return NULL;\n"
-      "  }\n"
-      "}\n"
-      "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
-      "  if (!has_$name$()) {\n"
-      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
-      "  }\n"
-      "  clear_$oneof_name$();\n"
-      "  if ($name$ != NULL) {\n"
-      "    set_has_$name$();\n"
-      "    $oneof_prefix$$name$_.SetAllocated($default_variable$, $name$,\n"
-      "        GetArenaNoVirtual());\n"
-      "  }\n"
-      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
-      "}\n"
-      "$inline$ void $classname$::unsafe_arena_set_allocated_$name$("
-      "::std::string* $name$) {\n"
-      "  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
-      "  if (!has_$name$()) {\n"
-      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
-      "  }\n"
-      "  clear_$oneof_name$();\n"
-      "  if ($name$) {\n"
-      "    set_has_$name$();\n"
-      "    $oneof_prefix$$name$_.UnsafeArenaSetAllocated($default_variable$, "
-      "$name$, GetArenaNoVirtual());\n"
-      "  }\n"
-      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
-      "}\n");
+    printer->Print(
+        variables_,
+        "inline const ::std::string& $classname$::$name$() const {\n"
+        "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+        "  if (has_$name$()) {\n"
+        "    return $field_member$.Get();\n"
+        "  }\n"
+        "  return *$default_variable$;\n"
+        "}\n"
+        "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+        "  if (!has_$name$()) {\n"
+        "    clear_$oneof_name$();\n"
+        "    set_has_$name$();\n"
+        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
+        "  }\n"
+        "  $field_member$.Set$lite$($default_variable$, value,\n"
+        "      GetArenaNoVirtual());\n"
+        "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+        "}\n"
+        "#if LANG_CXX11\n"
+        "inline void $classname$::set_$name$(::std::string&& value) {\n"
+        "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+        "  if (!has_$name$()) {\n"
+        "    clear_$oneof_name$();\n"
+        "    set_has_$name$();\n"
+        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
+        "  }\n"
+        "  $field_member$.Set$lite$(\n"
+        "    $default_variable$, ::std::move(value), GetArenaNoVirtual());\n"
+        "  // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
+        "}\n"
+        "#endif\n"
+        "inline void $classname$::set_$name$(const char* value) {\n"
+        "  $null_check$"
+        "  if (!has_$name$()) {\n"
+        "    clear_$oneof_name$();\n"
+        "    set_has_$name$();\n"
+        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
+        "  }\n"
+        "  $field_member$.Set$lite$($default_variable$,\n"
+        "      $string_piece$(value), GetArenaNoVirtual());\n"
+        "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
+        "}\n"
+        "inline "
+        "void $classname$::set_$name$(const $pointer_type$* value,\n"
+        "                             size_t size) {\n"
+        "  if (!has_$name$()) {\n"
+        "    clear_$oneof_name$();\n"
+        "    set_has_$name$();\n"
+        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
+        "  }\n"
+        "  $field_member$.Set$lite$(\n"
+        "      $default_variable$, $string_piece$(\n"
+        "      reinterpret_cast<const char*>(value), size),\n"
+        "      GetArenaNoVirtual());\n"
+        "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
+        "}\n"
+        "inline ::std::string* $classname$::mutable_$name$() {\n"
+        "  if (!has_$name$()) {\n"
+        "    clear_$oneof_name$();\n"
+        "    set_has_$name$();\n"
+        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
+        "  }\n"
+        "  return $field_member$.Mutable($default_variable$,\n"
+        "      GetArenaNoVirtual());\n"
+        "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+        "}\n"
+        "inline ::std::string* $classname$::$release_name$() {\n"
+        "  // @@protoc_insertion_point(field_release:$full_name$)\n"
+        "  if (has_$name$()) {\n"
+        "    clear_has_$oneof_name$();\n"
+        "    return $field_member$.Release($default_variable$,\n"
+        "        GetArenaNoVirtual());\n"
+        "  } else {\n"
+        "    return NULL;\n"
+        "  }\n"
+        "}\n"
+        "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+        "  if (!has_$name$()) {\n"
+        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
+        "  }\n"
+        "  clear_$oneof_name$();\n"
+        "  if ($name$ != NULL) {\n"
+        "    set_has_$name$();\n"
+        "    $field_member$.SetAllocated($default_variable$, $name$,\n"
+        "        GetArenaNoVirtual());\n"
+        "  }\n"
+        "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+        "}\n"
+        "inline ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
+        "  // "
+        "@@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
+        "  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
+        "  if (has_$name$()) {\n"
+        "    clear_has_$oneof_name$();\n"
+        "    return $field_member$.UnsafeArenaRelease(\n"
+        "        $default_variable$, GetArenaNoVirtual());\n"
+        "  } else {\n"
+        "    return NULL;\n"
+        "  }\n"
+        "}\n"
+        "inline void $classname$::unsafe_arena_set_allocated_$name$("
+        "::std::string* $name$) {\n"
+        "  GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
+        "  if (!has_$name$()) {\n"
+        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
+        "  }\n"
+        "  clear_$oneof_name$();\n"
+        "  if ($name$) {\n"
+        "    set_has_$name$();\n"
+        "    $field_member$.UnsafeArenaSetAllocated($default_variable$, "
+        "$name$, GetArenaNoVirtual());\n"
+        "  }\n"
+        "  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
+        "$full_name$)\n"
+        "}\n");
   } else {
     // No-arena case.
-    printer->Print(variables,
-      "$inline$ const ::std::string& $classname$::$name$() const {\n"
-      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
-      "  if (has_$name$()) {\n"
-      "    return $oneof_prefix$$name$_.GetNoArena($default_variable$);\n"
-      "  }\n"
-      "  return *$default_variable$;\n"
-      "}\n"
-      "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
-      "  // @@protoc_insertion_point(field_set:$full_name$)\n"
-      "  if (!has_$name$()) {\n"
-      "    clear_$oneof_name$();\n"
-      "    set_has_$name$();\n"
-      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
-      "  }\n"
-      "  $oneof_prefix$$name$_.SetNoArena($default_variable$, value);\n"
-      "  // @@protoc_insertion_point(field_set:$full_name$)\n"
-      "}\n"
-      "$inline$ void $classname$::set_$name$(const char* value) {\n"
-      "  if (!has_$name$()) {\n"
-      "    clear_$oneof_name$();\n"
-      "    set_has_$name$();\n"
-      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
-      "  }\n"
-      "  $oneof_prefix$$name$_.SetNoArena($default_variable$,\n"
-      "      $string_piece$(value));\n"
-      "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
-      "}\n"
-      "$inline$ "
-      "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
-      "  if (!has_$name$()) {\n"
-      "    clear_$oneof_name$();\n"
-      "    set_has_$name$();\n"
-      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
-      "  }\n"
-      "  $oneof_prefix$$name$_.SetNoArena($default_variable$, $string_piece$(\n"
-      "      reinterpret_cast<const char*>(value), size));\n"
-      "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
-      "}\n"
-      "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
-      "  if (!has_$name$()) {\n"
-      "    clear_$oneof_name$();\n"
-      "    set_has_$name$();\n"
-      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
-      "  }\n"
-      "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
-      "  return $oneof_prefix$$name$_.MutableNoArena($default_variable$);\n"
-      "}\n"
-      "$inline$ ::std::string* $classname$::$release_name$() {\n"
-      "  if (has_$name$()) {\n"
-      "    clear_has_$oneof_name$();\n"
-      "    return $oneof_prefix$$name$_.ReleaseNoArena($default_variable$);\n"
-      "  } else {\n"
-      "    return NULL;\n"
-      "  }\n"
-      "}\n"
-      "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
-      "  if (!has_$name$()) {\n"
-      "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
-      "  }\n"
-      "  clear_$oneof_name$();\n"
-      "  if ($name$ != NULL) {\n"
-      "    set_has_$name$();\n"
-      "    $oneof_prefix$$name$_.SetAllocatedNoArena($default_variable$,\n"
-      "        $name$);\n"
-      "  }\n"
-      "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
-      "}\n");
+    printer->Print(
+        variables_,
+        "inline const ::std::string& $classname$::$name$() const {\n"
+        "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+        "  if (has_$name$()) {\n"
+        "    return $field_member$.GetNoArena();\n"
+        "  }\n"
+        "  return *$default_variable$;\n"
+        "}\n"
+        "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+        "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+        "  if (!has_$name$()) {\n"
+        "    clear_$oneof_name$();\n"
+        "    set_has_$name$();\n"
+        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
+        "  }\n"
+        "  $field_member$.SetNoArena($default_variable$, value);\n"
+        "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+        "}\n"
+        "#if LANG_CXX11\n"
+        "inline void $classname$::set_$name$(::std::string&& value) {\n"
+        "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+        "  if (!has_$name$()) {\n"
+        "    clear_$oneof_name$();\n"
+        "    set_has_$name$();\n"
+        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
+        "  }\n"
+        "  $field_member$.SetNoArena($default_variable$, ::std::move(value));\n"
+        "  // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
+        "}\n"
+        "#endif\n"
+        "inline void $classname$::set_$name$(const char* value) {\n"
+        "  $null_check$"
+        "  if (!has_$name$()) {\n"
+        "    clear_$oneof_name$();\n"
+        "    set_has_$name$();\n"
+        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
+        "  }\n"
+        "  $field_member$.SetNoArena($default_variable$,\n"
+        "      $string_piece$(value));\n"
+        "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
+        "}\n"
+        "inline "
+        "void $classname$::set_$name$(const $pointer_type$* value, size_t "
+        "size) {\n"
+        "  if (!has_$name$()) {\n"
+        "    clear_$oneof_name$();\n"
+        "    set_has_$name$();\n"
+        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
+        "  }\n"
+        "  $field_member$.SetNoArena($default_variable$, $string_piece$(\n"
+        "      reinterpret_cast<const char*>(value), size));\n"
+        "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
+        "}\n"
+        "inline ::std::string* $classname$::mutable_$name$() {\n"
+        "  if (!has_$name$()) {\n"
+        "    clear_$oneof_name$();\n"
+        "    set_has_$name$();\n"
+        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
+        "  }\n"
+        "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+        "  return $field_member$.MutableNoArena($default_variable$);\n"
+        "}\n"
+        "inline ::std::string* $classname$::$release_name$() {\n"
+        "  // @@protoc_insertion_point(field_release:$full_name$)\n"
+        "  if (has_$name$()) {\n"
+        "    clear_has_$oneof_name$();\n"
+        "    return $field_member$.ReleaseNoArena($default_variable$);\n"
+        "  } else {\n"
+        "    return NULL;\n"
+        "  }\n"
+        "}\n"
+        "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+        "  if (!has_$name$()) {\n"
+        "    $field_member$.UnsafeSetDefault($default_variable$);\n"
+        "  }\n"
+        "  clear_$oneof_name$();\n"
+        "  if ($name$ != NULL) {\n"
+        "    set_has_$name$();\n"
+        "    $field_member$.SetAllocatedNoArena($default_variable$, $name$);\n"
+        "  }\n"
+        "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+        "}\n");
   }
 }
 
 void StringOneofFieldGenerator::
 GenerateClearingCode(io::Printer* printer) const {
-  map<string, string> variables(variables_);
-  if (dependent_field_) {
-    variables["this_message"] = DependentBaseDownCast();
-    // This clearing code may be in the dependent base class. If the default
-    // value is an empty string, then the $default_variable$ is a global
-    // singleton. If the default is not empty, we need to down-cast to get the
-    // default value's global singleton instance. See SetStringVariables() for
-    // possible values of default_variable.
-    if (!descriptor_->default_value_string().empty()) {
-      variables["default_variable"] =
-          DependentBaseDownCast() + variables["default_variable"];
-    }
-  } else {
-    variables["this_message"] = "";
-  }
   if (SupportsArenas(descriptor_)) {
-    printer->Print(variables,
-      "$this_message$$oneof_prefix$$name$_.Destroy($default_variable$,\n"
-      "    $this_message$GetArenaNoVirtual());\n");
+    printer->Print(variables_,
+      "$field_member$.Destroy($default_variable$,\n"
+      "    GetArenaNoVirtual());\n");
   } else {
-    printer->Print(variables,
-      "$this_message$$oneof_prefix$$name$_."
-      "DestroyNoArena($default_variable$);\n");
+    printer->Print(variables_,
+      "$field_member$.DestroyNoArena($default_variable$);\n");
   }
 }
 
 void StringOneofFieldGenerator::
+GenerateMessageClearingCode(io::Printer* printer) const {
+  return GenerateClearingCode(printer);
+}
+
+void StringOneofFieldGenerator::
 GenerateSwappingCode(io::Printer* printer) const {
   // Don't print any swapping code. Swapping the union will swap this field.
 }
 
 void StringOneofFieldGenerator::
 GenerateConstructorCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "  $classname$_default_oneof_instance_->$name$_.UnsafeSetDefault("
-    "$default_variable$);\n");
+  printer->Print(
+      variables_,
+      "$ns$::_$classname$_default_instance_.$name$_.UnsafeSetDefault(\n"
+      "    $default_variable$);\n");
 }
 
 void StringOneofFieldGenerator::
 GenerateDestructorCode(io::Printer* printer) const {
-  if (SupportsArenas(descriptor_)) {
-    printer->Print(variables_,
-      "if (has_$name$()) {\n"
-      "  $oneof_prefix$$name$_.Destroy($default_variable$,\n"
-      "      GetArenaNoVirtual());\n"
-      "}\n");
-  } else {
-    printer->Print(variables_,
-      "if (has_$name$()) {\n"
-      "  $oneof_prefix$$name$_.DestroyNoArena($default_variable$);\n"
-      "}\n");
-  }
+  printer->Print(variables_,
+    "if (has_$name$()) {\n"
+    "  $field_member$.DestroyNoArena($default_variable$);\n"
+    "}\n");
 }
 
 void StringOneofFieldGenerator::
@@ -658,18 +912,18 @@
 
   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
     GenerateUtf8CheckCodeForString(
-        descriptor_, true, variables_,
-        "this->$name$().data(), this->$name$().length(),\n", printer);
+        descriptor_, options_, true, variables_,
+        "this->$name$().data(), static_cast<int>(this->$name$().length()),\n",
+        printer);
   }
 }
 
 
 // ===================================================================
 
-RepeatedStringFieldGenerator::
-RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
-                             const Options& options)
-    : descriptor_(descriptor) {
+RepeatedStringFieldGenerator::RepeatedStringFieldGenerator(
+    const FieldDescriptor* descriptor, const Options& options)
+    : FieldGenerator(options), descriptor_(descriptor) {
   SetStringVariables(descriptor, &variables_, options);
 }
 
@@ -696,24 +950,62 @@
   }
 
   printer->Print(variables_,
-    "const ::std::string& $name$(int index) const$deprecation$;\n"
-    "::std::string* mutable_$name$(int index)$deprecation$;\n"
-    "void set_$name$(int index, const ::std::string& value)$deprecation$;\n"
-    "void set_$name$(int index, const char* value)$deprecation$;\n"
-    ""
-    "void set_$name$(int index, const $pointer_type$* value, size_t size)"
-                 "$deprecation$;\n"
-    "::std::string* add_$name$()$deprecation$;\n"
-    "void add_$name$(const ::std::string& value)$deprecation$;\n"
-    "void add_$name$(const char* value)$deprecation$;\n"
-    "void add_$name$(const $pointer_type$* value, size_t size)"
-                 "$deprecation$;\n");
-
+                 "$deprecated_attr$const ::std::string& $name$(int index) const;\n");
+  printer->Annotate("name", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecated_attr$::std::string* ${$mutable_$name$$}$(int index);\n");
+  printer->Annotate("{", "}", descriptor_);
   printer->Print(variables_,
-    "const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const"
-                 "$deprecation$;\n"
-    "::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
-                 "$deprecation$;\n");
+                 "$deprecated_attr$void ${$set_$name$$}$(int index, const "
+                 "::std::string& value);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(
+      variables_,
+      "#if LANG_CXX11\n"
+      "$deprecated_attr$void ${$set_$name$$}$(int index, ::std::string&& value);\n"
+      "#endif\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$void ${$set_$name$$}$(int index, const "
+                 "char* value);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 ""
+                 "$deprecated_attr$void ${$set_$name$$}$("
+                 "int index, const $pointer_type$* value, size_t size);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$::std::string* ${$add_$name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecated_attr$void ${$add_$name$$}$(const ::std::string& value);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 "#if LANG_CXX11\n"
+                 "$deprecated_attr$void ${$add_$name$$}$(::std::string&& value);\n"
+                 "#endif\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecated_attr$void ${$add_$name$$}$(const char* value);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$void ${$add_$name$$}$(const $pointer_type$* "
+                 "value, size_t size)"
+                 ";\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() "
+      "const;\n");
+  printer->Annotate("name", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$::google::protobuf::RepeatedPtrField< ::std::string>* "
+                 "${$mutable_$name$$}$()"
+                 ";\n");
+  printer->Annotate("{", "}", descriptor_);
 
   if (unknown_ctype) {
     printer->Outdent();
@@ -723,57 +1015,78 @@
 }
 
 void RepeatedStringFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                  bool is_inline) const {
-  map<string, string> variables(variables_);
-  variables["inline"] = is_inline ? "inline" : "";
-  printer->Print(variables,
-    "$inline$ const ::std::string& $classname$::$name$(int index) const {\n"
-    "  // @@protoc_insertion_point(field_get:$full_name$)\n"
-    "  return $name$_.$cppget$(index);\n"
-    "}\n"
-    "$inline$ ::std::string* $classname$::mutable_$name$(int index) {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+  if (options_.safe_boundary_check) {
+    printer->Print(variables_,
+      "inline const ::std::string& $classname$::$name$(int index) const {\n"
+      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+      "  return $name$_.InternalCheckedGet(\n"
+      "      index, ::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "inline const ::std::string& $classname$::$name$(int index) const {\n"
+      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
+      "  return $name$_.Get(index);\n"
+      "}\n");
+  }
+  printer->Print(variables_,
+    "inline ::std::string* $classname$::mutable_$name$(int index) {\n"
     "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
     "  return $name$_.Mutable(index);\n"
     "}\n"
-    "$inline$ void $classname$::set_$name$(int index, const ::std::string& value) {\n"
+    "inline void $classname$::set_$name$(int index, const ::std::string& value) {\n"
     "  // @@protoc_insertion_point(field_set:$full_name$)\n"
     "  $name$_.Mutable(index)->assign(value);\n"
     "}\n"
-    "$inline$ void $classname$::set_$name$(int index, const char* value) {\n"
+    "#if LANG_CXX11\n"
+    "inline void $classname$::set_$name$(int index, ::std::string&& value) {\n"
+    "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+    "  $name$_.Mutable(index)->assign(std::move(value));\n"
+    "}\n"
+    "#endif\n"
+    "inline void $classname$::set_$name$(int index, const char* value) {\n"
+    "  $null_check$"
     "  $name$_.Mutable(index)->assign(value);\n"
     "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
     "}\n"
-    "$inline$ void "
+    "inline void "
     "$classname$::set_$name$"
     "(int index, const $pointer_type$* value, size_t size) {\n"
     "  $name$_.Mutable(index)->assign(\n"
     "    reinterpret_cast<const char*>(value), size);\n"
     "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
     "}\n"
-    "$inline$ ::std::string* $classname$::add_$name$() {\n"
+    "inline ::std::string* $classname$::add_$name$() {\n"
+    "  // @@protoc_insertion_point(field_add_mutable:$full_name$)\n"
     "  return $name$_.Add();\n"
     "}\n"
-    "$inline$ void $classname$::add_$name$(const ::std::string& value) {\n"
+    "inline void $classname$::add_$name$(const ::std::string& value) {\n"
     "  $name$_.Add()->assign(value);\n"
     "  // @@protoc_insertion_point(field_add:$full_name$)\n"
     "}\n"
-    "$inline$ void $classname$::add_$name$(const char* value) {\n"
+    "#if LANG_CXX11\n"
+    "inline void $classname$::add_$name$(::std::string&& value) {\n"
+    "  $name$_.Add(std::move(value));\n"
+    "  // @@protoc_insertion_point(field_add:$full_name$)\n"
+    "}\n"
+    "#endif\n"
+    "inline void $classname$::add_$name$(const char* value) {\n"
+    "  $null_check$"
     "  $name$_.Add()->assign(value);\n"
     "  // @@protoc_insertion_point(field_add_char:$full_name$)\n"
     "}\n"
-    "$inline$ void "
+    "inline void "
     "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
     "  $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
     "  // @@protoc_insertion_point(field_add_pointer:$full_name$)\n"
-    "}\n");
-  printer->Print(variables,
-    "$inline$ const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
+    "}\n"
+    "inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
     "$classname$::$name$() const {\n"
     "  // @@protoc_insertion_point(field_list:$full_name$)\n"
     "  return $name$_;\n"
     "}\n"
-    "$inline$ ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
+    "inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
     "$classname$::mutable_$name$() {\n"
     "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
     "  return &$name$_;\n"
@@ -792,7 +1105,8 @@
 
 void RepeatedStringFieldGenerator::
 GenerateSwappingCode(io::Printer* printer) const {
-  printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
+  printer->Print(variables_,
+                 "$name$_.InternalSwap(CastToBase(&other->$name$_));\n");
 }
 
 void RepeatedStringFieldGenerator::
@@ -801,15 +1115,20 @@
 }
 
 void RepeatedStringFieldGenerator::
+GenerateCopyConstructorCode(io::Printer* printer) const {
+  printer->Print(variables_, "$name$_.CopyFrom(from.$name$_);");
+}
+
+void RepeatedStringFieldGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) const {
   printer->Print(variables_,
     "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
     "      input, this->add_$name$()));\n");
   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
     GenerateUtf8CheckCodeForString(
-        descriptor_, true, variables_,
+        descriptor_, options_, true, variables_,
         "this->$name$(this->$name$_size() - 1).data(),\n"
-        "this->$name$(this->$name$_size() - 1).length(),\n",
+        "static_cast<int>(this->$name$(this->$name$_size() - 1).length()),\n",
         printer);
   }
 }
@@ -817,12 +1136,13 @@
 void RepeatedStringFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
   printer->Print(variables_,
-    "for (int i = 0; i < this->$name$_size(); i++) {\n");
+        "for (int i = 0, n = this->$name$_size(); i < n; i++) {\n");
   printer->Indent();
   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
     GenerateUtf8CheckCodeForString(
-        descriptor_, false, variables_,
-        "this->$name$(i).data(), this->$name$(i).length(),\n", printer);
+        descriptor_, options_, false, variables_,
+        "this->$name$(i).data(), static_cast<int>(this->$name$(i).length()),\n",
+        printer);
   }
   printer->Outdent();
   printer->Print(variables_,
@@ -834,12 +1154,13 @@
 void RepeatedStringFieldGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
   printer->Print(variables_,
-    "for (int i = 0; i < this->$name$_size(); i++) {\n");
+    "for (int i = 0, n = this->$name$_size(); i < n; i++) {\n");
   printer->Indent();
   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
     GenerateUtf8CheckCodeForString(
-        descriptor_, false, variables_,
-        "this->$name$(i).data(), this->$name$(i).length(),\n", printer);
+        descriptor_, options_, false, variables_,
+        "this->$name$(i).data(), static_cast<int>(this->$name$(i).length()),\n",
+        printer);
   }
   printer->Outdent();
   printer->Print(variables_,
@@ -851,8 +1172,9 @@
 void RepeatedStringFieldGenerator::
 GenerateByteSize(io::Printer* printer) const {
   printer->Print(variables_,
-    "total_size += $tag_size$ * this->$name$_size();\n"
-    "for (int i = 0; i < this->$name$_size(); i++) {\n"
+    "total_size += $tag_size$ *\n"
+    "    ::google::protobuf::internal::FromIntSize(this->$name$_size());\n"
+    "for (int i = 0, n = this->$name$_size(); i < n; i++) {\n"
     "  total_size += ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
     "    this->$name$(i));\n"
     "}\n");
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h
index 616e206..6cbf722 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -46,32 +46,39 @@
 
 class StringFieldGenerator : public FieldGenerator {
  public:
-  explicit StringFieldGenerator(const FieldDescriptor* descriptor,
-                                const Options& options);
+  StringFieldGenerator(const FieldDescriptor* descriptor,
+                       const Options& options);
   ~StringFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
   void GeneratePrivateMembers(io::Printer* printer) const;
   void GenerateStaticMembers(io::Printer* printer) const;
   void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                         bool is_inline) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
   void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
   void GenerateClearingCode(io::Printer* printer) const;
+  void GenerateMessageClearingCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateDestructorCode(io::Printer* printer) const;
+  bool GenerateArenaDestructorCode(io::Printer* printer) const;
   void GenerateDefaultInstanceAllocator(io::Printer* printer) const;
-  void GenerateShutdownCode(io::Printer* printer) const;
   void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  uint32 CalculateFieldTag() const;
+  bool IsInlined() const { return inlined_; }
+
+  bool MergeFromCodedStreamNeedsArena() const;
 
  protected:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
+  const bool lite_;
+  bool inlined_;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator);
@@ -79,39 +86,41 @@
 
 class StringOneofFieldGenerator : public StringFieldGenerator {
  public:
-  explicit StringOneofFieldGenerator(const FieldDescriptor* descriptor,
-                                     const Options& options);
+  StringOneofFieldGenerator(const FieldDescriptor* descriptor,
+                            const Options& options);
   ~StringOneofFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
-  void GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                         bool is_inline) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
   void GenerateClearingCode(io::Printer* printer) const;
+
+  // StringFieldGenerator, from which we inherit, overrides this so we need to
+  // override it as well.
+  void GenerateMessageClearingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
   void GenerateDestructorCode(io::Printer* printer) const;
   void GenerateMergeFromCodedStream(io::Printer* printer) const;
 
  private:
-  const bool dependent_field_;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator);
 };
 
 class RepeatedStringFieldGenerator : public FieldGenerator {
  public:
-  explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
-                                        const Options& options);
+  RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
+                               const Options& options);
   ~RepeatedStringFieldGenerator();
 
   // implements FieldGenerator ---------------------------------------
   void GeneratePrivateMembers(io::Printer* printer) const;
   void GenerateAccessorDeclarations(io::Printer* printer) const;
-  void GenerateInlineAccessorDefinitions(io::Printer* printer,
-                                         bool is_inline) const;
+  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
   void GenerateClearingCode(io::Printer* printer) const;
   void GenerateMergingCode(io::Printer* printer) const;
   void GenerateSwappingCode(io::Printer* printer) const;
   void GenerateConstructorCode(io::Printer* printer) const;
+  void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
@@ -119,7 +128,7 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator);
 };
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 4e25b2e..7fe9875 100644
--- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -151,6 +151,10 @@
 
 message DummyMessage {}
 
+// Message names that could conflict.
+message Shutdown {}
+message TableStruct {}
+
 service TestConflictingMethodNames {
   rpc Closure(DummyMessage) returns (DummyMessage);
 }
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index 9942a34..22b759a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -46,43 +46,29 @@
 
 #include <google/protobuf/compiler/cpp/cpp_unittest.h>
 
-#include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
-#include <vector>
-
 #include <google/protobuf/unittest.pb.h>
 #include <google/protobuf/unittest_optimize_for.pb.h>
 #include <google/protobuf/unittest_embed_optimize_for.pb.h>
-#if !defined(GOOGLE_PROTOBUF_CMAKE_BUILD) && !defined(_MSC_VER)
-// We exclude this large proto from cmake build because it's too large for
-// visual studio to compile (report internal errors).
-#include <google/protobuf/unittest_enormous_descriptor.pb.h>
-#endif
-#include <google/protobuf/unittest_no_generic_services.pb.h>
-#include <google/protobuf/test_util.h>
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
-#include <google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h>
-#include <google/protobuf/compiler/importer.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/dynamic_message.h>
 
-#include <google/protobuf/stubs/callback.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/testing/googletest.h>
-#include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util.h>
+#include <google/protobuf/test_util.h>
+
+#define MESSAGE_TEST_NAME MessageTest
+#define GENERATED_DESCRIPTOR_TEST_NAME GeneratedDescriptorTest
+#define GENERATED_MESSAGE_TEST_NAME GeneratedMessageTest
+#define GENERATED_ENUM_TEST_NAME GeneratedEnumTest
+#define GENERATED_SERVICE_TEST_NAME GeneratedServiceTest
+#define HELPERS_TEST_NAME HelpersTest
+#define DESCRIPTOR_INIT_TEST_NAME DescriptorInitializationTest
+
+#define UNITTEST_PROTO_PATH "google/protobuf/unittest.proto"
+#define UNITTEST ::protobuf_unittest
+#define UNITTEST_IMPORT ::protobuf_unittest_import
+
+// Must include after the above macros.
+#include <google/protobuf/compiler/cpp/cpp_unittest.inc>
 
 namespace google {
 namespace protobuf {
-using internal::NewPermanentCallback;
 namespace compiler {
 namespace cpp {
 
@@ -91,715 +77,14 @@
 
 namespace protobuf_unittest = ::protobuf_unittest;
 
-
-class MockErrorCollector : public MultiFileErrorCollector {
- public:
-  MockErrorCollector() {}
-  ~MockErrorCollector() {}
-
-  string text_;
-
-  // implements ErrorCollector ---------------------------------------
-  void AddError(const string& filename, int line, int column,
-                const string& message) {
-    strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n",
-                                 filename, line, column, message);
-  }
-};
-
-#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
-
-// Test that generated code has proper descriptors:
-// Parse a descriptor directly (using google::protobuf::compiler::Importer) and
-// compare it to the one that was produced by generated code.
-TEST(GeneratedDescriptorTest, IdenticalDescriptors) {
-  const FileDescriptor* generated_descriptor =
-    unittest::TestAllTypes::descriptor()->file();
-
-  // Set up the Importer.
-  MockErrorCollector error_collector;
-  DiskSourceTree source_tree;
-  source_tree.MapPath("", TestSourceDir());
-  Importer importer(&source_tree, &error_collector);
-
-  // Import (parse) unittest.proto.
-  const FileDescriptor* parsed_descriptor =
-    importer.Import("google/protobuf/unittest.proto");
-  EXPECT_EQ("", error_collector.text_);
-  ASSERT_TRUE(parsed_descriptor != NULL);
-
-  // Test that descriptors are generated correctly by converting them to
-  // FileDescriptorProtos and comparing.
-  FileDescriptorProto generated_decsriptor_proto, parsed_descriptor_proto;
-  generated_descriptor->CopyTo(&generated_decsriptor_proto);
-  parsed_descriptor->CopyTo(&parsed_descriptor_proto);
-
-  EXPECT_EQ(parsed_descriptor_proto.DebugString(),
-            generated_decsriptor_proto.DebugString());
-}
-
-#if !defined(GOOGLE_PROTOBUF_CMAKE_BUILD) && !defined(_MSC_VER)
-// Test that generated code has proper descriptors:
-// Touch a descriptor generated from an enormous message to validate special
-// handling for descriptors exceeding the C++ standard's recommended minimum
-// limit for string literal size
-TEST(GeneratedDescriptorTest, EnormousDescriptor) {
-  const Descriptor* generated_descriptor =
-    TestEnormousDescriptor::descriptor();
-
-  EXPECT_TRUE(generated_descriptor != NULL);
-}
-#endif
-
-#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
-
-// ===================================================================
-
-TEST(GeneratedMessageTest, Defaults) {
-  // Check that all default values are set correctly in the initial message.
-  unittest::TestAllTypes message;
-
-  TestUtil::ExpectClear(message);
-
-  // Messages should return pointers to default instances until first use.
-  // (This is not checked by ExpectClear() since it is not actually true after
-  // the fields have been set and then cleared.)
-  EXPECT_EQ(&unittest::TestAllTypes::OptionalGroup::default_instance(),
-            &message.optionalgroup());
-  EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(),
-            &message.optional_nested_message());
-  EXPECT_EQ(&unittest::ForeignMessage::default_instance(),
-            &message.optional_foreign_message());
-  EXPECT_EQ(&unittest_import::ImportMessage::default_instance(),
-            &message.optional_import_message());
-}
-
-#ifndef PROTOBUF_USE_DLLS
-TEST(GeneratedMessageTest, Int32StringConversion) {
-  EXPECT_EQ("971", Int32ToString(971));
-  EXPECT_EQ("(~0x7fffffff)", Int32ToString(kint32min));
-  EXPECT_EQ("2147483647", Int32ToString(kint32max));
-}
-
-TEST(GeneratedMessageTest, Int64StringConversion) {
-  EXPECT_EQ("GOOGLE_LONGLONG(971)", Int64ToString(971));
-  EXPECT_EQ("GOOGLE_LONGLONG(-2147483648)", Int64ToString(kint32min));
-  EXPECT_EQ("GOOGLE_LONGLONG(~0x7fffffffffffffff)", Int64ToString(kint64min));
-  EXPECT_EQ("GOOGLE_LONGLONG(9223372036854775807)", Int64ToString(kint64max));
-}
-#endif  // !PROTOBUF_USE_DLLS
-
-TEST(GeneratedMessageTest, FloatingPointDefaults) {
-  const unittest::TestExtremeDefaultValues& extreme_default =
-      unittest::TestExtremeDefaultValues::default_instance();
-
-  EXPECT_EQ(0.0f, extreme_default.zero_float());
-  EXPECT_EQ(1.0f, extreme_default.one_float());
-  EXPECT_EQ(1.5f, extreme_default.small_float());
-  EXPECT_EQ(-1.0f, extreme_default.negative_one_float());
-  EXPECT_EQ(-1.5f, extreme_default.negative_float());
-  EXPECT_EQ(2.0e8f, extreme_default.large_float());
-  EXPECT_EQ(-8e-28f, extreme_default.small_negative_float());
-  EXPECT_EQ(numeric_limits<double>::infinity(),
-            extreme_default.inf_double());
-  EXPECT_EQ(-numeric_limits<double>::infinity(),
-            extreme_default.neg_inf_double());
-  EXPECT_TRUE(extreme_default.nan_double() != extreme_default.nan_double());
-  EXPECT_EQ(numeric_limits<float>::infinity(),
-            extreme_default.inf_float());
-  EXPECT_EQ(-numeric_limits<float>::infinity(),
-            extreme_default.neg_inf_float());
-  EXPECT_TRUE(extreme_default.nan_float() != extreme_default.nan_float());
-}
-
-TEST(GeneratedMessageTest, Trigraph) {
-  const unittest::TestExtremeDefaultValues& extreme_default =
-      unittest::TestExtremeDefaultValues::default_instance();
-
-  EXPECT_EQ("? ? ?? ?? ??? ?\?/ ?\?-", extreme_default.cpp_trigraph());
-}
-
-TEST(GeneratedMessageTest, ExtremeSmallIntegerDefault) {
-  const unittest::TestExtremeDefaultValues& extreme_default =
-      unittest::TestExtremeDefaultValues::default_instance();
-  EXPECT_EQ(~0x7fffffff, kint32min);
-  EXPECT_EQ(GOOGLE_LONGLONG(~0x7fffffffffffffff), kint64min);
-  EXPECT_EQ(kint32min, extreme_default.really_small_int32());
-  EXPECT_EQ(kint64min, extreme_default.really_small_int64());
-}
-
-TEST(GeneratedMessageTest, Accessors) {
-  // Set every field to a unique value then go back and check all those
-  // values.
-  unittest::TestAllTypes message;
-
-  TestUtil::SetAllFields(&message);
-  TestUtil::ExpectAllFieldsSet(message);
-
-  TestUtil::ModifyRepeatedFields(&message);
-  TestUtil::ExpectRepeatedFieldsModified(message);
-}
-
-TEST(GeneratedMessageTest, MutableStringDefault) {
-  // mutable_foo() for a string should return a string initialized to its
-  // default value.
-  unittest::TestAllTypes message;
-
-  EXPECT_EQ("hello", *message.mutable_default_string());
-
-  // Note that the first time we call mutable_foo(), we get a newly-allocated
-  // string, but if we clear it and call it again, we get the same object again.
-  // We should verify that it has its default value in both cases.
-  message.set_default_string("blah");
-  message.Clear();
-
-  EXPECT_EQ("hello", *message.mutable_default_string());
-}
-
-TEST(GeneratedMessageTest, StringDefaults) {
-  unittest::TestExtremeDefaultValues message;
-  // Check if '\000' can be used in default string value.
-  EXPECT_EQ(string("hel\000lo", 6), message.string_with_zero());
-  EXPECT_EQ(string("wor\000ld", 6), message.bytes_with_zero());
-}
-
-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());
-  google::protobuf::scoped_ptr<string> str(message.release_default_string());
-  EXPECT_FALSE(message.has_default_string());
-  ASSERT_TRUE(str != NULL);
-  EXPECT_EQ("blah", *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);
-  google::protobuf::scoped_ptr<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());
-
-  EXPECT_EQ(NULL, message.release_optional_nested_message());
-  EXPECT_FALSE(message.has_optional_nested_message());
-}
-
-TEST(GeneratedMessageTest, SetAllocatedString) {
-  // Check that set_allocated_foo() works for strings.
-  unittest::TestAllTypes message;
-
-  EXPECT_FALSE(message.has_optional_string());
-  const string kHello("hello");
-  message.set_optional_string(kHello);
-  EXPECT_TRUE(message.has_optional_string());
-
-  message.set_allocated_optional_string(NULL);
-  EXPECT_FALSE(message.has_optional_string());
-  EXPECT_EQ("", message.optional_string());
-
-  message.set_allocated_optional_string(new string(kHello));
-  EXPECT_TRUE(message.has_optional_string());
-  EXPECT_EQ(kHello, message.optional_string());
-}
-
-TEST(GeneratedMessageTest, SetAllocatedMessage) {
-  // Check that set_allocated_foo() can be called in all cases.
-  unittest::TestAllTypes message;
-
-  EXPECT_FALSE(message.has_optional_nested_message());
-
-  message.mutable_optional_nested_message()->set_bb(1);
-  EXPECT_TRUE(message.has_optional_nested_message());
-
-  message.set_allocated_optional_nested_message(NULL);
-  EXPECT_FALSE(message.has_optional_nested_message());
-  EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(),
-            &message.optional_nested_message());
-
-  message.mutable_optional_nested_message()->set_bb(1);
-  unittest::TestAllTypes::NestedMessage* nest =
-      message.release_optional_nested_message();
-  ASSERT_TRUE(nest != NULL);
-  EXPECT_FALSE(message.has_optional_nested_message());
-
-  message.set_allocated_optional_nested_message(nest);
-  EXPECT_TRUE(message.has_optional_nested_message());
-  EXPECT_EQ(1, message.optional_nested_message().bb());
-}
-
-TEST(GeneratedMessageTest, Clear) {
-  // Set every field to a unique value, clear the message, then check that
-  // it is cleared.
-  unittest::TestAllTypes message;
-
-  TestUtil::SetAllFields(&message);
-  message.Clear();
-  TestUtil::ExpectClear(message);
-
-  // Unlike with the defaults test, we do NOT expect that requesting embedded
-  // messages will return a pointer to the default instance.  Instead, they
-  // should return the objects that were created when mutable_blah() was
-  // called.
-  EXPECT_NE(&unittest::TestAllTypes::OptionalGroup::default_instance(),
-            &message.optionalgroup());
-  EXPECT_NE(&unittest::TestAllTypes::NestedMessage::default_instance(),
-            &message.optional_nested_message());
-  EXPECT_NE(&unittest::ForeignMessage::default_instance(),
-            &message.optional_foreign_message());
-  EXPECT_NE(&unittest_import::ImportMessage::default_instance(),
-            &message.optional_import_message());
-}
-
-TEST(GeneratedMessageTest, EmbeddedNullsInBytesCharStar) {
-  unittest::TestAllTypes message;
-
-  const char* value = "\0lalala\0\0";
-  message.set_optional_bytes(value, 9);
-  ASSERT_EQ(9, message.optional_bytes().size());
-  EXPECT_EQ(0, memcmp(value, message.optional_bytes().data(), 9));
-
-  message.add_repeated_bytes(value, 9);
-  ASSERT_EQ(9, message.repeated_bytes(0).size());
-  EXPECT_EQ(0, memcmp(value, message.repeated_bytes(0).data(), 9));
-}
-
-TEST(GeneratedMessageTest, ClearOneField) {
-  // Set every field to a unique value, then clear one value and insure that
-  // only that one value is cleared.
-  unittest::TestAllTypes message;
-
-  TestUtil::SetAllFields(&message);
-  int64 original_value = message.optional_int64();
-
-  // Clear the field and make sure it shows up as cleared.
-  message.clear_optional_int64();
-  EXPECT_FALSE(message.has_optional_int64());
-  EXPECT_EQ(0, message.optional_int64());
-
-  // Other adjacent fields should not be cleared.
-  EXPECT_TRUE(message.has_optional_int32());
-  EXPECT_TRUE(message.has_optional_uint32());
-
-  // Make sure if we set it again, then all fields are set.
-  message.set_optional_int64(original_value);
-  TestUtil::ExpectAllFieldsSet(message);
-}
-
-TEST(GeneratedMessageTest, StringCharStarLength) {
-  // Verify that we can use a char*,length to set one of the string fields.
-  unittest::TestAllTypes message;
-  message.set_optional_string("abcdef", 3);
-  EXPECT_EQ("abc", message.optional_string());
-
-  // Verify that we can use a char*,length to add to a repeated string field.
-  message.add_repeated_string("abcdef", 3);
-  EXPECT_EQ(1, message.repeated_string_size());
-  EXPECT_EQ("abc", message.repeated_string(0));
-
-  // Verify that we can use a char*,length to set a repeated string field.
-  message.set_repeated_string(0, "wxyz", 2);
-  EXPECT_EQ("wx", message.repeated_string(0));
-}
-
-
-TEST(GeneratedMessageTest, CopyFrom) {
-  unittest::TestAllTypes message1, message2;
-
-  TestUtil::SetAllFields(&message1);
-  message2.CopyFrom(message1);
-  TestUtil::ExpectAllFieldsSet(message2);
-
-  // Copying from self should be a no-op.
-  message2.CopyFrom(message2);
-  TestUtil::ExpectAllFieldsSet(message2);
-}
-
-
-TEST(GeneratedMessageTest, SwapWithEmpty) {
-  unittest::TestAllTypes message1, message2;
-  TestUtil::SetAllFields(&message1);
-
-  TestUtil::ExpectAllFieldsSet(message1);
-  TestUtil::ExpectClear(message2);
-  message1.Swap(&message2);
-  TestUtil::ExpectAllFieldsSet(message2);
-  TestUtil::ExpectClear(message1);
-}
-
-TEST(GeneratedMessageTest, SwapWithSelf) {
-  unittest::TestAllTypes message;
-  TestUtil::SetAllFields(&message);
-  TestUtil::ExpectAllFieldsSet(message);
-  message.Swap(&message);
-  TestUtil::ExpectAllFieldsSet(message);
-}
-
-TEST(GeneratedMessageTest, SwapWithOther) {
-  unittest::TestAllTypes message1, message2;
-
-  message1.set_optional_int32(123);
-  message1.set_optional_string("abc");
-  message1.mutable_optional_nested_message()->set_bb(1);
-  message1.set_optional_nested_enum(unittest::TestAllTypes::FOO);
-  message1.add_repeated_int32(1);
-  message1.add_repeated_int32(2);
-  message1.add_repeated_string("a");
-  message1.add_repeated_string("b");
-  message1.add_repeated_nested_message()->set_bb(7);
-  message1.add_repeated_nested_message()->set_bb(8);
-  message1.add_repeated_nested_enum(unittest::TestAllTypes::FOO);
-  message1.add_repeated_nested_enum(unittest::TestAllTypes::BAR);
-
-  message2.set_optional_int32(456);
-  message2.set_optional_string("def");
-  message2.mutable_optional_nested_message()->set_bb(2);
-  message2.set_optional_nested_enum(unittest::TestAllTypes::BAR);
-  message2.add_repeated_int32(3);
-  message2.add_repeated_string("c");
-  message2.add_repeated_nested_message()->set_bb(9);
-  message2.add_repeated_nested_enum(unittest::TestAllTypes::BAZ);
-
-  message1.Swap(&message2);
-
-  EXPECT_EQ(456, message1.optional_int32());
-  EXPECT_EQ("def", message1.optional_string());
-  EXPECT_EQ(2, message1.optional_nested_message().bb());
-  EXPECT_EQ(unittest::TestAllTypes::BAR, message1.optional_nested_enum());
-  ASSERT_EQ(1, message1.repeated_int32_size());
-  EXPECT_EQ(3, message1.repeated_int32(0));
-  ASSERT_EQ(1, message1.repeated_string_size());
-  EXPECT_EQ("c", message1.repeated_string(0));
-  ASSERT_EQ(1, message1.repeated_nested_message_size());
-  EXPECT_EQ(9, message1.repeated_nested_message(0).bb());
-  ASSERT_EQ(1, message1.repeated_nested_enum_size());
-  EXPECT_EQ(unittest::TestAllTypes::BAZ, message1.repeated_nested_enum(0));
-
-  EXPECT_EQ(123, message2.optional_int32());
-  EXPECT_EQ("abc", message2.optional_string());
-  EXPECT_EQ(1, message2.optional_nested_message().bb());
-  EXPECT_EQ(unittest::TestAllTypes::FOO, message2.optional_nested_enum());
-  ASSERT_EQ(2, message2.repeated_int32_size());
-  EXPECT_EQ(1, message2.repeated_int32(0));
-  EXPECT_EQ(2, message2.repeated_int32(1));
-  ASSERT_EQ(2, message2.repeated_string_size());
-  EXPECT_EQ("a", message2.repeated_string(0));
-  EXPECT_EQ("b", message2.repeated_string(1));
-  ASSERT_EQ(2, message2.repeated_nested_message_size());
-  EXPECT_EQ(7, message2.repeated_nested_message(0).bb());
-  EXPECT_EQ(8, message2.repeated_nested_message(1).bb());
-  ASSERT_EQ(2, message2.repeated_nested_enum_size());
-  EXPECT_EQ(unittest::TestAllTypes::FOO, message2.repeated_nested_enum(0));
-  EXPECT_EQ(unittest::TestAllTypes::BAR, message2.repeated_nested_enum(1));
-}
-
-TEST(GeneratedMessageTest, CopyConstructor) {
-  unittest::TestAllTypes message1;
-  TestUtil::SetAllFields(&message1);
-
-  unittest::TestAllTypes message2(message1);
-  TestUtil::ExpectAllFieldsSet(message2);
-}
-
-TEST(GeneratedMessageTest, CopyAssignmentOperator) {
-  unittest::TestAllTypes message1;
-  TestUtil::SetAllFields(&message1);
-
-  unittest::TestAllTypes message2;
-  message2 = message1;
-  TestUtil::ExpectAllFieldsSet(message2);
-
-  // Make sure that self-assignment does something sane.
-  message2.operator=(message2);
-  TestUtil::ExpectAllFieldsSet(message2);
-}
-
-#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \
-    !defined(GOOGLE_PROTOBUF_NO_RTTI)
-TEST(GeneratedMessageTest, UpcastCopyFrom) {
-  // Test the CopyFrom method that takes in the generic const Message&
-  // parameter.
-  unittest::TestAllTypes message1, message2;
-
-  TestUtil::SetAllFields(&message1);
-
-  const Message* source = implicit_cast<const Message*>(&message1);
-  message2.CopyFrom(*source);
-
-  TestUtil::ExpectAllFieldsSet(message2);
-}
-#endif
-
-#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
-
-TEST(GeneratedMessageTest, DynamicMessageCopyFrom) {
-  // Test copying from a DynamicMessage, which must fall back to using
-  // reflection.
-  unittest::TestAllTypes message2;
-
-  // Construct a new version of the dynamic message via the factory.
-  DynamicMessageFactory factory;
-  google::protobuf::scoped_ptr<Message> message1;
-  message1.reset(factory.GetPrototype(
-                     unittest::TestAllTypes::descriptor())->New());
-
-  TestUtil::ReflectionTester reflection_tester(
-    unittest::TestAllTypes::descriptor());
-  reflection_tester.SetAllFieldsViaReflection(message1.get());
-
-  message2.CopyFrom(*message1);
-
-  TestUtil::ExpectAllFieldsSet(message2);
-}
-
-#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
-
-TEST(GeneratedMessageTest, NonEmptyMergeFrom) {
-  // Test merging with a non-empty message. Code is a modified form
-  // of that found in google/protobuf/reflection_ops_unittest.cc.
-  unittest::TestAllTypes message1, message2;
-
-  TestUtil::SetAllFields(&message1);
-
-  // This field will test merging into an empty spot.
-  message2.set_optional_int32(message1.optional_int32());
-  message1.clear_optional_int32();
-
-  // This tests overwriting.
-  message2.set_optional_string(message1.optional_string());
-  message1.set_optional_string("something else");
-
-  // This tests concatenating.
-  message2.add_repeated_int32(message1.repeated_int32(1));
-  int32 i = message1.repeated_int32(0);
-  message1.clear_repeated_int32();
-  message1.add_repeated_int32(i);
-
-  message1.MergeFrom(message2);
-
-  TestUtil::ExpectAllFieldsSet(message1);
-}
-
-#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \
-    !defined(GOOGLE_PROTOBUF_NO_RTTI)
-#ifdef PROTOBUF_HAS_DEATH_TEST
-
-TEST(GeneratedMessageTest, MergeFromSelf) {
-  unittest::TestAllTypes message;
-  EXPECT_DEATH(message.MergeFrom(message), "Check failed:.*pb[.]cc");
-  EXPECT_DEATH(message.MergeFrom(implicit_cast<const Message&>(message)),
-               "Check failed:.*pb[.]cc");
-}
-
-#endif  // PROTOBUF_HAS_DEATH_TEST
-#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS || !GOOGLE_PROTOBUF_NO_RTTI
-
-// Test the generated SerializeWithCachedSizesToArray(),
-TEST(GeneratedMessageTest, SerializationToArray) {
-  unittest::TestAllTypes message1, message2;
-  string data;
-  TestUtil::SetAllFields(&message1);
-  int size = message1.ByteSize();
-  data.resize(size);
-  uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
-  uint8* end = message1.SerializeWithCachedSizesToArray(start);
-  EXPECT_EQ(size, end - start);
-  EXPECT_TRUE(message2.ParseFromString(data));
-  TestUtil::ExpectAllFieldsSet(message2);
-
-}
-
-TEST(GeneratedMessageTest, PackedFieldsSerializationToArray) {
-  unittest::TestPackedTypes packed_message1, packed_message2;
-  string packed_data;
-  TestUtil::SetPackedFields(&packed_message1);
-  int packed_size = packed_message1.ByteSize();
-  packed_data.resize(packed_size);
-  uint8* start = reinterpret_cast<uint8*>(string_as_array(&packed_data));
-  uint8* end = packed_message1.SerializeWithCachedSizesToArray(start);
-  EXPECT_EQ(packed_size, end - start);
-  EXPECT_TRUE(packed_message2.ParseFromString(packed_data));
-  TestUtil::ExpectPackedFieldsSet(packed_message2);
-}
-
-// Test the generated SerializeWithCachedSizes() by forcing the buffer to write
-// one byte at a time.
-TEST(GeneratedMessageTest, SerializationToStream) {
-  unittest::TestAllTypes message1, message2;
-  TestUtil::SetAllFields(&message1);
-  int size = message1.ByteSize();
-  string data;
-  data.resize(size);
-  {
-    // Allow the output stream to buffer only one byte at a time.
-    io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
-    io::CodedOutputStream output_stream(&array_stream);
-    message1.SerializeWithCachedSizes(&output_stream);
-    EXPECT_FALSE(output_stream.HadError());
-    EXPECT_EQ(size, output_stream.ByteCount());
-  }
-  EXPECT_TRUE(message2.ParseFromString(data));
-  TestUtil::ExpectAllFieldsSet(message2);
-
-}
-
-TEST(GeneratedMessageTest, PackedFieldsSerializationToStream) {
-  unittest::TestPackedTypes message1, message2;
-  TestUtil::SetPackedFields(&message1);
-  int size = message1.ByteSize();
-  string data;
-  data.resize(size);
-  {
-    // Allow the output stream to buffer only one byte at a time.
-    io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
-    io::CodedOutputStream output_stream(&array_stream);
-    message1.SerializeWithCachedSizes(&output_stream);
-    EXPECT_FALSE(output_stream.HadError());
-    EXPECT_EQ(size, output_stream.ByteCount());
-  }
-  EXPECT_TRUE(message2.ParseFromString(data));
-  TestUtil::ExpectPackedFieldsSet(message2);
-}
-
-
-TEST(GeneratedMessageTest, Required) {
-  // Test that IsInitialized() returns false if required fields are missing.
-  unittest::TestRequired message;
-
-  EXPECT_FALSE(message.IsInitialized());
-  message.set_a(1);
-  EXPECT_FALSE(message.IsInitialized());
-  message.set_b(2);
-  EXPECT_FALSE(message.IsInitialized());
-  message.set_c(3);
-  EXPECT_TRUE(message.IsInitialized());
-}
-
-TEST(GeneratedMessageTest, RequiredForeign) {
-  // Test that IsInitialized() returns false if required fields in nested
-  // messages are missing.
-  unittest::TestRequiredForeign message;
-
-  EXPECT_TRUE(message.IsInitialized());
-
-  message.mutable_optional_message();
-  EXPECT_FALSE(message.IsInitialized());
-
-  message.mutable_optional_message()->set_a(1);
-  message.mutable_optional_message()->set_b(2);
-  message.mutable_optional_message()->set_c(3);
-  EXPECT_TRUE(message.IsInitialized());
-
-  message.add_repeated_message();
-  EXPECT_FALSE(message.IsInitialized());
-
-  message.mutable_repeated_message(0)->set_a(1);
-  message.mutable_repeated_message(0)->set_b(2);
-  message.mutable_repeated_message(0)->set_c(3);
-  EXPECT_TRUE(message.IsInitialized());
-}
-
-TEST(GeneratedMessageTest, ForeignNested) {
-  // Test that TestAllTypes::NestedMessage can be embedded directly into
-  // another message.
-  unittest::TestForeignNested message;
-
-  // If this compiles and runs without crashing, it must work.  We have
-  // nothing more to test.
-  unittest::TestAllTypes::NestedMessage* nested =
-    message.mutable_foreign_nested();
-  nested->set_bb(1);
-}
-
-TEST(GeneratedMessageTest, ReallyLargeTagNumber) {
-  // Test that really large tag numbers don't break anything.
-  unittest::TestReallyLargeTagNumber message1, message2;
-  string data;
-
-  // For the most part, if this compiles and runs then we're probably good.
-  // (The most likely cause for failure would be if something were attempting
-  // to allocate a lookup table of some sort using tag numbers as the index.)
-  // We'll try serializing just for fun.
-  message1.set_a(1234);
-  message1.set_bb(5678);
-  message1.SerializeToString(&data);
-  EXPECT_TRUE(message2.ParseFromString(data));
-  EXPECT_EQ(1234, message2.a());
-  EXPECT_EQ(5678, message2.bb());
-}
-
-TEST(GeneratedMessageTest, MutualRecursion) {
-  // Test that mutually-recursive message types work.
-  unittest::TestMutualRecursionA message;
-  unittest::TestMutualRecursionA* nested = message.mutable_bb()->mutable_a();
-  unittest::TestMutualRecursionA* nested2 = nested->mutable_bb()->mutable_a();
-
-  // Again, if the above compiles and runs, that's all we really have to
-  // test, but just for run we'll check that the system didn't somehow come
-  // up with a pointer loop...
-  EXPECT_NE(&message, nested);
-  EXPECT_NE(&message, nested2);
-  EXPECT_NE(nested, nested2);
-}
-
-TEST(GeneratedMessageTest, CamelCaseFieldNames) {
-  // This test is mainly checking that the following compiles, which verifies
-  // that the field names were coerced to lower-case.
-  //
-  // Protocol buffers standard style is to use lowercase-with-underscores for
-  // field names.  Some old proto1 .protos unfortunately used camel-case field
-  // names.  In proto1, these names were forced to lower-case.  So, we do the
-  // same thing in proto2.
-
-  unittest::TestCamelCaseFieldNames message;
-
-  message.set_primitivefield(2);
-  message.set_stringfield("foo");
-  message.set_enumfield(unittest::FOREIGN_FOO);
-  message.mutable_messagefield()->set_c(6);
-
-  message.add_repeatedprimitivefield(8);
-  message.add_repeatedstringfield("qux");
-  message.add_repeatedenumfield(unittest::FOREIGN_BAR);
-  message.add_repeatedmessagefield()->set_c(15);
-
-  EXPECT_EQ(2, message.primitivefield());
-  EXPECT_EQ("foo", message.stringfield());
-  EXPECT_EQ(unittest::FOREIGN_FOO, message.enumfield());
-  EXPECT_EQ(6, message.messagefield().c());
-
-  EXPECT_EQ(8, message.repeatedprimitivefield(0));
-  EXPECT_EQ("qux", message.repeatedstringfield(0));
-  EXPECT_EQ(unittest::FOREIGN_BAR, message.repeatedenumfield(0));
-  EXPECT_EQ(15, message.repeatedmessagefield(0).c());
-}
-
-TEST(GeneratedMessageTest, TestConflictingSymbolNames) {
+TEST(GENERATED_MESSAGE_TEST_NAME, TestConflictingSymbolNames) {
   // test_bad_identifiers.proto successfully compiled, then it works.  The
   // following is just a token usage to insure that the code is, in fact,
   // being compiled and linked.
 
   protobuf_unittest::TestConflictingSymbolNames message;
   message.set_uint32(1);
-  EXPECT_EQ(3, message.ByteSize());
+  EXPECT_EQ(3, message.ByteSizeLong());
 
   message.set_friend_(5);
   EXPECT_EQ(5, message.friend_());
@@ -815,7 +100,7 @@
             message.GetExtension(ExtensionMessage::repeated_int32_ext, 0));
 }
 
-TEST(GeneratedMessageTest, TestConflictingEnumNames) {
+TEST(GENERATED_MESSAGE_TEST_NAME, TestConflictingEnumNames) {
   protobuf_unittest::TestConflictingEnumNames message;
   message.set_conflicting_enum(protobuf_unittest::TestConflictingEnumNames_NestedConflictingEnum_and_);
   EXPECT_EQ(1, message.conflicting_enum());
@@ -830,1311 +115,8 @@
   EXPECT_EQ(3, conflicting_enum);
 }
 
-#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
-
-TEST(GeneratedMessageTest, TestOptimizedForSize) {
-  // We rely on the tests in reflection_ops_unittest and wire_format_unittest
-  // to really test that reflection-based methods work.  Here we are mostly
-  // just making sure that TestOptimizedForSize actually builds and seems to
-  // function.
-
-  protobuf_unittest::TestOptimizedForSize message, message2;
-  message.set_i(1);
-  message.mutable_msg()->set_c(2);
-  message2.CopyFrom(message);
-  EXPECT_EQ(1, message2.i());
-  EXPECT_EQ(2, message2.msg().c());
-}
-
-TEST(GeneratedMessageTest, TestEmbedOptimizedForSize) {
-  // Verifies that something optimized for speed can contain something optimized
-  // for size.
-
-  protobuf_unittest::TestEmbedOptimizedForSize message, message2;
-  message.mutable_optional_message()->set_i(1);
-  message.add_repeated_message()->mutable_msg()->set_c(2);
-  string data;
-  message.SerializeToString(&data);
-  ASSERT_TRUE(message2.ParseFromString(data));
-  EXPECT_EQ(1, message2.optional_message().i());
-  EXPECT_EQ(2, message2.repeated_message(0).msg().c());
-}
-
-TEST(GeneratedMessageTest, TestSpaceUsed) {
-  unittest::TestAllTypes message1;
-  // sizeof provides a lower bound on SpaceUsed().
-  EXPECT_LE(sizeof(unittest::TestAllTypes), message1.SpaceUsed());
-  const int empty_message_size = message1.SpaceUsed();
-
-  // Setting primitive types shouldn't affect the space used.
-  message1.set_optional_int32(123);
-  message1.set_optional_int64(12345);
-  message1.set_optional_uint32(123);
-  message1.set_optional_uint64(12345);
-  EXPECT_EQ(empty_message_size, message1.SpaceUsed());
-
-  // On some STL implementations, setting the string to a small value should
-  // only increase SpaceUsed() by the size of a string object, though this is
-  // not true everywhere.
-  message1.set_optional_string("abc");
-  EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsed());
-
-  // Setting a string to a value larger than the string object itself should
-  // increase SpaceUsed(), because it cannot store the value internally.
-  message1.set_optional_string(string(sizeof(string) + 1, 'x'));
-  int min_expected_increase = message1.optional_string().capacity() +
-      sizeof(string);
-  EXPECT_LE(empty_message_size + min_expected_increase,
-            message1.SpaceUsed());
-
-  int previous_size = message1.SpaceUsed();
-  // Adding an optional message should increase the size by the size of the
-  // nested message type. NestedMessage is simple enough (1 int field) that it
-  // is equal to sizeof(NestedMessage)
-  message1.mutable_optional_nested_message();
-  ASSERT_EQ(sizeof(unittest::TestAllTypes::NestedMessage),
-            message1.optional_nested_message().SpaceUsed());
-  EXPECT_EQ(previous_size +
-            sizeof(unittest::TestAllTypes::NestedMessage),
-            message1.SpaceUsed());
-}
-
-TEST(GeneratedMessageTest, TestOneofSpaceUsed) {
-  unittest::TestOneof2 message1;
-  EXPECT_LE(sizeof(unittest::TestOneof2), message1.SpaceUsed());
-
-  const int empty_message_size = message1.SpaceUsed();
-  // Setting primitive types shouldn't affect the space used.
-  message1.set_foo_int(123);
-  message1.set_bar_int(12345);
-  EXPECT_EQ(empty_message_size, message1.SpaceUsed());
-
-  // Setting a string in oneof to a small value should only increase SpaceUsed()
-  // by the size of a string object.
-  message1.set_foo_string("abc");
-  EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsed());
-
-  // Setting a string in oneof to a value larger than the string object itself
-  // should increase SpaceUsed(), because it cannot store the value internally.
-  message1.set_foo_string(string(sizeof(string) + 1, 'x'));
-  int min_expected_increase = message1.foo_string().capacity() +
-      sizeof(string);
-  EXPECT_LE(empty_message_size + min_expected_increase,
-            message1.SpaceUsed());
-
-  // Setting a message in oneof should delete the other fields and increase the
-  // size by the size of the nested message type. NestedMessage is simple enough
-  // that it is equal to sizeof(NestedMessage)
-  message1.mutable_foo_message();
-  ASSERT_EQ(sizeof(unittest::TestOneof2::NestedMessage),
-            message1.foo_message().SpaceUsed());
-  EXPECT_EQ(empty_message_size +
-            sizeof(unittest::TestOneof2::NestedMessage),
-            message1.SpaceUsed());
-}
-
-#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
-
-
-TEST(GeneratedMessageTest, FieldConstantValues) {
-  unittest::TestRequired message;
-  EXPECT_EQ(unittest::TestAllTypes_NestedMessage::kBbFieldNumber, 1);
-  EXPECT_EQ(unittest::TestAllTypes::kOptionalInt32FieldNumber, 1);
-  EXPECT_EQ(unittest::TestAllTypes::kOptionalgroupFieldNumber, 16);
-  EXPECT_EQ(unittest::TestAllTypes::kOptionalNestedMessageFieldNumber, 18);
-  EXPECT_EQ(unittest::TestAllTypes::kOptionalNestedEnumFieldNumber, 21);
-  EXPECT_EQ(unittest::TestAllTypes::kRepeatedInt32FieldNumber, 31);
-  EXPECT_EQ(unittest::TestAllTypes::kRepeatedgroupFieldNumber, 46);
-  EXPECT_EQ(unittest::TestAllTypes::kRepeatedNestedMessageFieldNumber, 48);
-  EXPECT_EQ(unittest::TestAllTypes::kRepeatedNestedEnumFieldNumber, 51);
-}
-
-TEST(GeneratedMessageTest, ExtensionConstantValues) {
-  EXPECT_EQ(unittest::TestRequired::kSingleFieldNumber, 1000);
-  EXPECT_EQ(unittest::TestRequired::kMultiFieldNumber, 1001);
-  EXPECT_EQ(unittest::kOptionalInt32ExtensionFieldNumber, 1);
-  EXPECT_EQ(unittest::kOptionalgroupExtensionFieldNumber, 16);
-  EXPECT_EQ(unittest::kOptionalNestedMessageExtensionFieldNumber, 18);
-  EXPECT_EQ(unittest::kOptionalNestedEnumExtensionFieldNumber, 21);
-  EXPECT_EQ(unittest::kRepeatedInt32ExtensionFieldNumber, 31);
-  EXPECT_EQ(unittest::kRepeatedgroupExtensionFieldNumber, 46);
-  EXPECT_EQ(unittest::kRepeatedNestedMessageExtensionFieldNumber, 48);
-  EXPECT_EQ(unittest::kRepeatedNestedEnumExtensionFieldNumber, 51);
-}
-
-TEST(GeneratedMessageTest, ParseFromTruncated) {
-  const string long_string = string(128, 'q');
-  FileDescriptorProto p;
-  p.add_extension()->set_name(long_string);
-  const string msg = p.SerializeAsString();
-  int successful_count = 0;
-  for (int i = 0; i <= msg.size(); i++) {
-    if (p.ParseFromArray(msg.c_str(), i)) {
-      ++successful_count;
-    }
-  }
-  // We don't really care about how often we succeeded.
-  // As long as we didn't crash, we're happy.
-  EXPECT_GE(successful_count, 1);
-}
-
-// ===================================================================
-
-TEST(GeneratedEnumTest, EnumValuesAsSwitchCases) {
-  // Test that our nested enum values can be used as switch cases.  This test
-  // doesn't actually do anything, the proof that it works is that it
-  // compiles.
-  int i =0;
-  unittest::TestAllTypes::NestedEnum a = unittest::TestAllTypes::BAR;
-  switch (a) {
-    case unittest::TestAllTypes::FOO:
-      i = 1;
-      break;
-    case unittest::TestAllTypes::BAR:
-      i = 2;
-      break;
-    case unittest::TestAllTypes::BAZ:
-      i = 3;
-      break;
-    case unittest::TestAllTypes::NEG:
-      i = -1;
-      break;
-    // no default case:  We want to make sure the compiler recognizes that
-    //   all cases are covered.  (GCC warns if you do not cover all cases of
-    //   an enum in a switch.)
-  }
-
-  // Token check just for fun.
-  EXPECT_EQ(2, i);
-}
-
-TEST(GeneratedEnumTest, IsValidValue) {
-  // Test enum IsValidValue.
-  EXPECT_TRUE(unittest::TestAllTypes::NestedEnum_IsValid(1));
-  EXPECT_TRUE(unittest::TestAllTypes::NestedEnum_IsValid(2));
-  EXPECT_TRUE(unittest::TestAllTypes::NestedEnum_IsValid(3));
-
-  EXPECT_FALSE(unittest::TestAllTypes::NestedEnum_IsValid(0));
-  EXPECT_FALSE(unittest::TestAllTypes::NestedEnum_IsValid(4));
-
-  // Make sure it also works when there are dups.
-  EXPECT_TRUE(unittest::TestEnumWithDupValue_IsValid(1));
-  EXPECT_TRUE(unittest::TestEnumWithDupValue_IsValid(2));
-  EXPECT_TRUE(unittest::TestEnumWithDupValue_IsValid(3));
-
-  EXPECT_FALSE(unittest::TestEnumWithDupValue_IsValid(0));
-  EXPECT_FALSE(unittest::TestEnumWithDupValue_IsValid(4));
-}
-
-TEST(GeneratedEnumTest, MinAndMax) {
-  EXPECT_EQ(unittest::TestAllTypes::NEG,
-            unittest::TestAllTypes::NestedEnum_MIN);
-  EXPECT_EQ(unittest::TestAllTypes::BAZ,
-            unittest::TestAllTypes::NestedEnum_MAX);
-  EXPECT_EQ(4, unittest::TestAllTypes::NestedEnum_ARRAYSIZE);
-
-  EXPECT_EQ(unittest::FOREIGN_FOO, unittest::ForeignEnum_MIN);
-  EXPECT_EQ(unittest::FOREIGN_BAZ, unittest::ForeignEnum_MAX);
-  EXPECT_EQ(7, unittest::ForeignEnum_ARRAYSIZE);
-
-  EXPECT_EQ(1, unittest::TestEnumWithDupValue_MIN);
-  EXPECT_EQ(3, unittest::TestEnumWithDupValue_MAX);
-  EXPECT_EQ(4, unittest::TestEnumWithDupValue_ARRAYSIZE);
-
-  EXPECT_EQ(unittest::SPARSE_E, unittest::TestSparseEnum_MIN);
-  EXPECT_EQ(unittest::SPARSE_C, unittest::TestSparseEnum_MAX);
-  EXPECT_EQ(12589235, unittest::TestSparseEnum_ARRAYSIZE);
-
-  // Make sure we can take the address of _MIN, _MAX and _ARRAYSIZE.
-  void* null_pointer = 0;  // NULL may be integer-type, not pointer-type.
-  EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_MIN);
-  EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_MAX);
-  EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_ARRAYSIZE);
-
-  EXPECT_NE(null_pointer, &unittest::ForeignEnum_MIN);
-  EXPECT_NE(null_pointer, &unittest::ForeignEnum_MAX);
-  EXPECT_NE(null_pointer, &unittest::ForeignEnum_ARRAYSIZE);
-
-  // Make sure we can use _MIN and _MAX as switch cases.
-  switch (unittest::SPARSE_A) {
-    case unittest::TestSparseEnum_MIN:
-    case unittest::TestSparseEnum_MAX:
-      break;
-    default:
-      break;
-  }
-}
-
-#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
-
-TEST(GeneratedEnumTest, Name) {
-  // "Names" in the presence of dup values are a bit arbitrary.
-  EXPECT_EQ("FOO1", unittest::TestEnumWithDupValue_Name(unittest::FOO1));
-  EXPECT_EQ("FOO1", unittest::TestEnumWithDupValue_Name(unittest::FOO2));
-
-  EXPECT_EQ("SPARSE_A", unittest::TestSparseEnum_Name(unittest::SPARSE_A));
-  EXPECT_EQ("SPARSE_B", unittest::TestSparseEnum_Name(unittest::SPARSE_B));
-  EXPECT_EQ("SPARSE_C", unittest::TestSparseEnum_Name(unittest::SPARSE_C));
-  EXPECT_EQ("SPARSE_D", unittest::TestSparseEnum_Name(unittest::SPARSE_D));
-  EXPECT_EQ("SPARSE_E", unittest::TestSparseEnum_Name(unittest::SPARSE_E));
-  EXPECT_EQ("SPARSE_F", unittest::TestSparseEnum_Name(unittest::SPARSE_F));
-  EXPECT_EQ("SPARSE_G", unittest::TestSparseEnum_Name(unittest::SPARSE_G));
-}
-
-TEST(GeneratedEnumTest, Parse) {
-  unittest::TestEnumWithDupValue dup_value = unittest::FOO1;
-  EXPECT_TRUE(unittest::TestEnumWithDupValue_Parse("FOO1", &dup_value));
-  EXPECT_EQ(unittest::FOO1, dup_value);
-  EXPECT_TRUE(unittest::TestEnumWithDupValue_Parse("FOO2", &dup_value));
-  EXPECT_EQ(unittest::FOO2, dup_value);
-  EXPECT_FALSE(unittest::TestEnumWithDupValue_Parse("FOO", &dup_value));
-}
-
-TEST(GeneratedEnumTest, GetEnumDescriptor) {
-  EXPECT_EQ(unittest::TestAllTypes::NestedEnum_descriptor(),
-            GetEnumDescriptor<unittest::TestAllTypes::NestedEnum>());
-  EXPECT_EQ(unittest::ForeignEnum_descriptor(),
-            GetEnumDescriptor<unittest::ForeignEnum>());
-  EXPECT_EQ(unittest::TestEnumWithDupValue_descriptor(),
-            GetEnumDescriptor<unittest::TestEnumWithDupValue>());
-  EXPECT_EQ(unittest::TestSparseEnum_descriptor(),
-            GetEnumDescriptor<unittest::TestSparseEnum>());
-}
-
-enum NonProtoEnum {
-  kFoo = 1,
-};
-
-TEST(GeneratedEnumTest, IsProtoEnumTypeTrait) {
-  EXPECT_TRUE(is_proto_enum<unittest::TestAllTypes::NestedEnum>::value);
-  EXPECT_TRUE(is_proto_enum<unittest::ForeignEnum>::value);
-  EXPECT_TRUE(is_proto_enum<unittest::TestEnumWithDupValue>::value);
-  EXPECT_TRUE(is_proto_enum<unittest::TestSparseEnum>::value);
-
-  EXPECT_FALSE(is_proto_enum<int>::value);
-  EXPECT_FALSE(is_proto_enum<NonProtoEnum>::value);
-}
-
-#endif  // PROTOBUF_TEST_NO_DESCRIPTORS
-
-// ===================================================================
-
-#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
-
-// Support code for testing services.
-class GeneratedServiceTest : public testing::Test {
- protected:
-  class MockTestService : public unittest::TestService {
-   public:
-    MockTestService()
-      : called_(false),
-        method_(""),
-        controller_(NULL),
-        request_(NULL),
-        response_(NULL),
-        done_(NULL) {}
-
-    ~MockTestService() {}
-
-    void Reset() { called_ = false; }
-
-    // implements TestService ----------------------------------------
-
-    void Foo(RpcController* controller,
-             const unittest::FooRequest* request,
-             unittest::FooResponse* response,
-             Closure* done) {
-      ASSERT_FALSE(called_);
-      called_ = true;
-      method_ = "Foo";
-      controller_ = controller;
-      request_ = request;
-      response_ = response;
-      done_ = done;
-    }
-
-    void Bar(RpcController* controller,
-             const unittest::BarRequest* request,
-             unittest::BarResponse* response,
-             Closure* done) {
-      ASSERT_FALSE(called_);
-      called_ = true;
-      method_ = "Bar";
-      controller_ = controller;
-      request_ = request;
-      response_ = response;
-      done_ = done;
-    }
-
-    // ---------------------------------------------------------------
-
-    bool called_;
-    string method_;
-    RpcController* controller_;
-    const Message* request_;
-    Message* response_;
-    Closure* done_;
-  };
-
-  class MockRpcChannel : public RpcChannel {
-   public:
-    MockRpcChannel()
-      : called_(false),
-        method_(NULL),
-        controller_(NULL),
-        request_(NULL),
-        response_(NULL),
-        done_(NULL),
-        destroyed_(NULL) {}
-
-    ~MockRpcChannel() {
-      if (destroyed_ != NULL) *destroyed_ = true;
-    }
-
-    void Reset() { called_ = false; }
-
-    // implements TestService ----------------------------------------
-
-    void CallMethod(const MethodDescriptor* method,
-                    RpcController* controller,
-                    const Message* request,
-                    Message* response,
-                    Closure* done) {
-      ASSERT_FALSE(called_);
-      called_ = true;
-      method_ = method;
-      controller_ = controller;
-      request_ = request;
-      response_ = response;
-      done_ = done;
-    }
-
-    // ---------------------------------------------------------------
-
-    bool called_;
-    const MethodDescriptor* method_;
-    RpcController* controller_;
-    const Message* request_;
-    Message* response_;
-    Closure* done_;
-    bool* destroyed_;
-  };
-
-  class MockController : public RpcController {
-   public:
-    void Reset() {
-      ADD_FAILURE() << "Reset() not expected during this test.";
-    }
-    bool Failed() const {
-      ADD_FAILURE() << "Failed() not expected during this test.";
-      return false;
-    }
-    string ErrorText() const {
-      ADD_FAILURE() << "ErrorText() not expected during this test.";
-      return "";
-    }
-    void StartCancel() {
-      ADD_FAILURE() << "StartCancel() not expected during this test.";
-    }
-    void SetFailed(const string& reason) {
-      ADD_FAILURE() << "SetFailed() not expected during this test.";
-    }
-    bool IsCanceled() const {
-      ADD_FAILURE() << "IsCanceled() not expected during this test.";
-      return false;
-    }
-    void NotifyOnCancel(Closure* callback) {
-      ADD_FAILURE() << "NotifyOnCancel() not expected during this test.";
-    }
-  };
-
-  GeneratedServiceTest()
-    : descriptor_(unittest::TestService::descriptor()),
-      foo_(descriptor_->FindMethodByName("Foo")),
-      bar_(descriptor_->FindMethodByName("Bar")),
-      stub_(&mock_channel_),
-      done_(NewPermanentCallback(&DoNothing)) {}
-
-  virtual void SetUp() {
-    ASSERT_TRUE(foo_ != NULL);
-    ASSERT_TRUE(bar_ != NULL);
-  }
-
-  const ServiceDescriptor* descriptor_;
-  const MethodDescriptor* foo_;
-  const MethodDescriptor* bar_;
-
-  MockTestService mock_service_;
-  MockController mock_controller_;
-
-  MockRpcChannel mock_channel_;
-  unittest::TestService::Stub stub_;
-
-  // Just so we don't have to re-define these with every test.
-  unittest::FooRequest foo_request_;
-  unittest::FooResponse foo_response_;
-  unittest::BarRequest bar_request_;
-  unittest::BarResponse bar_response_;
-  google::protobuf::scoped_ptr<Closure> done_;
-};
-
-TEST_F(GeneratedServiceTest, GetDescriptor) {
-  // Test that GetDescriptor() works.
-
-  EXPECT_EQ(descriptor_, mock_service_.GetDescriptor());
-}
-
-TEST_F(GeneratedServiceTest, GetChannel) {
-  EXPECT_EQ(&mock_channel_, stub_.channel());
-}
-
-TEST_F(GeneratedServiceTest, OwnsChannel) {
-  MockRpcChannel* channel = new MockRpcChannel;
-  bool destroyed = false;
-  channel->destroyed_ = &destroyed;
-
-  {
-    unittest::TestService::Stub owning_stub(channel,
-                                            Service::STUB_OWNS_CHANNEL);
-    EXPECT_FALSE(destroyed);
-  }
-
-  EXPECT_TRUE(destroyed);
-}
-
-TEST_F(GeneratedServiceTest, CallMethod) {
-  // Test that CallMethod() works.
-
-  // Call Foo() via CallMethod().
-  mock_service_.CallMethod(foo_, &mock_controller_,
-                           &foo_request_, &foo_response_, done_.get());
-
-  ASSERT_TRUE(mock_service_.called_);
-
-  EXPECT_EQ("Foo"            , mock_service_.method_    );
-  EXPECT_EQ(&mock_controller_, mock_service_.controller_);
-  EXPECT_EQ(&foo_request_    , mock_service_.request_   );
-  EXPECT_EQ(&foo_response_   , mock_service_.response_  );
-  EXPECT_EQ(done_.get()      , mock_service_.done_      );
-
-  // Try again, but call Bar() instead.
-  mock_service_.Reset();
-  mock_service_.CallMethod(bar_, &mock_controller_,
-                           &bar_request_, &bar_response_, done_.get());
-
-  ASSERT_TRUE(mock_service_.called_);
-  EXPECT_EQ("Bar", mock_service_.method_);
-}
-
-TEST_F(GeneratedServiceTest, CallMethodTypeFailure) {
-  // Verify death if we call Foo() with Bar's message types.
-
-#ifdef PROTOBUF_HAS_DEATH_TEST  // death tests do not work on Windows yet
-  EXPECT_DEBUG_DEATH(
-    mock_service_.CallMethod(foo_, &mock_controller_,
-                             &foo_request_, &bar_response_, done_.get()),
-    "dynamic_cast");
-
-  mock_service_.Reset();
-  EXPECT_DEBUG_DEATH(
-    mock_service_.CallMethod(foo_, &mock_controller_,
-                             &bar_request_, &foo_response_, done_.get()),
-    "dynamic_cast");
-#endif  // PROTOBUF_HAS_DEATH_TEST
-}
-
-TEST_F(GeneratedServiceTest, GetPrototypes) {
-  // Test Get{Request,Response}Prototype() methods.
-
-  EXPECT_EQ(&unittest::FooRequest::default_instance(),
-            &mock_service_.GetRequestPrototype(foo_));
-  EXPECT_EQ(&unittest::BarRequest::default_instance(),
-            &mock_service_.GetRequestPrototype(bar_));
-
-  EXPECT_EQ(&unittest::FooResponse::default_instance(),
-            &mock_service_.GetResponsePrototype(foo_));
-  EXPECT_EQ(&unittest::BarResponse::default_instance(),
-            &mock_service_.GetResponsePrototype(bar_));
-}
-
-TEST_F(GeneratedServiceTest, Stub) {
-  // Test that the stub class works.
-
-  // Call Foo() via the stub.
-  stub_.Foo(&mock_controller_, &foo_request_, &foo_response_, done_.get());
-
-  ASSERT_TRUE(mock_channel_.called_);
-
-  EXPECT_EQ(foo_             , mock_channel_.method_    );
-  EXPECT_EQ(&mock_controller_, mock_channel_.controller_);
-  EXPECT_EQ(&foo_request_    , mock_channel_.request_   );
-  EXPECT_EQ(&foo_response_   , mock_channel_.response_  );
-  EXPECT_EQ(done_.get()      , mock_channel_.done_      );
-
-  // Call Bar() via the stub.
-  mock_channel_.Reset();
-  stub_.Bar(&mock_controller_, &bar_request_, &bar_response_, done_.get());
-
-  ASSERT_TRUE(mock_channel_.called_);
-  EXPECT_EQ(bar_, mock_channel_.method_);
-}
-
-TEST_F(GeneratedServiceTest, NotImplemented) {
-  // Test that failing to implement a method of a service causes it to fail
-  // with a "not implemented" error message.
-
-  // A service which doesn't implement any methods.
-  class UnimplementedService : public unittest::TestService {
-   public:
-    UnimplementedService() {}
-  };
-
-  UnimplementedService unimplemented_service;
-
-  // And a controller which expects to get a "not implemented" error.
-  class ExpectUnimplementedController : public MockController {
-   public:
-    ExpectUnimplementedController() : called_(false) {}
-
-    void SetFailed(const string& reason) {
-      EXPECT_FALSE(called_);
-      called_ = true;
-      EXPECT_EQ("Method Foo() not implemented.", reason);
-    }
-
-    bool called_;
-  };
-
-  ExpectUnimplementedController controller;
-
-  // Call Foo.
-  unimplemented_service.Foo(&controller, &foo_request_, &foo_response_,
-                            done_.get());
-
-  EXPECT_TRUE(controller.called_);
-}
-
-// ===================================================================
-
-class OneofTest : public testing::Test {
- protected:
-  virtual void SetUp() {
-  }
-
-  void ExpectEnumCasesWork(const unittest::TestOneof2 &message) {
-    switch (message.foo_case()) {
-      case unittest::TestOneof2::kFooInt:
-        EXPECT_TRUE(message.has_foo_int());
-        break;
-      case unittest::TestOneof2::kFooString:
-        EXPECT_TRUE(message.has_foo_string());
-        break;
-      case unittest::TestOneof2::kFooCord:
-        EXPECT_TRUE(message.has_foo_cord());
-        break;
-      case unittest::TestOneof2::kFooStringPiece:
-        EXPECT_TRUE(message.has_foo_string_piece());
-        break;
-      case unittest::TestOneof2::kFooBytes:
-        EXPECT_TRUE(message.has_foo_bytes());
-        break;
-      case unittest::TestOneof2::kFooEnum:
-        EXPECT_TRUE(message.has_foo_enum());
-        break;
-      case unittest::TestOneof2::kFooMessage:
-        EXPECT_TRUE(message.has_foo_message());
-        break;
-      case unittest::TestOneof2::kFoogroup:
-        EXPECT_TRUE(message.has_foogroup());
-        break;
-      case unittest::TestOneof2::kFooLazyMessage:
-        EXPECT_TRUE(message.has_foo_lazy_message());
-        break;
-      case unittest::TestOneof2::FOO_NOT_SET:
-        break;
-    }
-  }
-};
-
-TEST_F(OneofTest, SettingOneFieldClearsOthers) {
-  unittest::TestOneof2 message;
-
-  message.set_foo_int(123);
-  EXPECT_TRUE(message.has_foo_int());
-  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
-
-  message.set_foo_string("foo");
-  EXPECT_TRUE(message.has_foo_string());
-  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
-
-
-  message.set_foo_bytes("qux");
-  EXPECT_TRUE(message.has_foo_bytes());
-  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
-
-  message.set_foo_enum(unittest::TestOneof2::FOO);
-  EXPECT_TRUE(message.has_foo_enum());
-  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
-
-  message.mutable_foo_message()->set_qux_int(234);
-  EXPECT_TRUE(message.has_foo_message());
-  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
-
-  message.mutable_foogroup()->set_a(345);
-  EXPECT_TRUE(message.has_foogroup());
-  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
-
-
-  // we repeat this because we didn't test if this properly clears other fields
-  // at the beginning.
-  message.set_foo_int(123);
-  EXPECT_TRUE(message.has_foo_int());
-  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
-}
-
-TEST_F(OneofTest, EnumCases) {
-  unittest::TestOneof2 message;
-
-  message.set_foo_int(123);
-  ExpectEnumCasesWork(message);
-  message.set_foo_string("foo");
-  ExpectEnumCasesWork(message);
-  message.set_foo_bytes("qux");
-  ExpectEnumCasesWork(message);
-  message.set_foo_enum(unittest::TestOneof2::FOO);
-  ExpectEnumCasesWork(message);
-  message.mutable_foo_message()->set_qux_int(234);
-  ExpectEnumCasesWork(message);
-  message.mutable_foogroup()->set_a(345);
-  ExpectEnumCasesWork(message);
-}
-
-TEST_F(OneofTest, PrimitiveType) {
-  unittest::TestOneof2 message;
-  // Unset field returns default value
-  EXPECT_EQ(message.foo_int(), 0);
-
-  message.set_foo_int(123);
-  EXPECT_TRUE(message.has_foo_int());
-  EXPECT_EQ(message.foo_int(), 123);
-  message.clear_foo_int();
-  EXPECT_FALSE(message.has_foo_int());
-}
-
-TEST_F(OneofTest, EnumType) {
-  unittest::TestOneof2 message;
-  // Unset field returns default value
-  EXPECT_EQ(message.foo_enum(), 1);
-
-  message.set_foo_enum(unittest::TestOneof2::FOO);
-  EXPECT_TRUE(message.has_foo_enum());
-  EXPECT_EQ(message.foo_enum(), unittest::TestOneof2::FOO);
-  message.clear_foo_enum();
-  EXPECT_FALSE(message.has_foo_enum());
-}
-
-TEST_F(OneofTest, SetString) {
-  // Check that setting a string field in various ways works
-  unittest::TestOneof2 message;
-
-  // Unset field returns default value
-  EXPECT_EQ(message.foo_string(), "");
-
-  message.set_foo_string("foo");
-  EXPECT_TRUE(message.has_foo_string());
-  EXPECT_EQ(message.foo_string(), "foo");
-  message.clear_foo_string();
-  EXPECT_FALSE(message.has_foo_string());
-
-  message.set_foo_string(string("bar"));
-  EXPECT_TRUE(message.has_foo_string());
-  EXPECT_EQ(message.foo_string(), "bar");
-  message.clear_foo_string();
-  EXPECT_FALSE(message.has_foo_string());
-
-
-  message.set_foo_string("qux", 3);
-  EXPECT_TRUE(message.has_foo_string());
-  EXPECT_EQ(message.foo_string(), "qux");
-  message.clear_foo_string();
-  EXPECT_FALSE(message.has_foo_string());
-
-  message.mutable_foo_string()->assign("quux");
-  EXPECT_TRUE(message.has_foo_string());
-  EXPECT_EQ(message.foo_string(), "quux");
-  message.clear_foo_string();
-  EXPECT_FALSE(message.has_foo_string());
-
-  message.set_foo_string("corge");
-  EXPECT_TRUE(message.has_foo_string());
-  EXPECT_EQ(message.foo_string(), "corge");
-  message.clear_foo_string();
-  EXPECT_FALSE(message.has_foo_string());
-}
-
-TEST_F(OneofTest, ReleaseString) {
-  // Check that release_foo() starts out NULL, and gives us a value
-  // that we can delete after it's been set.
-  unittest::TestOneof2 message;
-
-  EXPECT_EQ(NULL, message.release_foo_string());
-  EXPECT_FALSE(message.has_foo_string());
-
-  message.set_foo_string("blah");
-  EXPECT_TRUE(message.has_foo_string());
-  google::protobuf::scoped_ptr<string> str(message.release_foo_string());
-  EXPECT_FALSE(message.has_foo_string());
-  ASSERT_TRUE(str != NULL);
-  EXPECT_EQ("blah", *str);
-
-  EXPECT_EQ(NULL, message.release_foo_string());
-  EXPECT_FALSE(message.has_foo_string());
-}
-
-TEST_F(OneofTest, SetAllocatedString) {
-  // Check that set_allocated_foo() works for strings.
-  unittest::TestOneof2 message;
-
-  EXPECT_FALSE(message.has_foo_string());
-  const string kHello("hello");
-  message.set_foo_string(kHello);
-  EXPECT_TRUE(message.has_foo_string());
-
-  message.set_allocated_foo_string(NULL);
-  EXPECT_FALSE(message.has_foo_string());
-  EXPECT_EQ("", message.foo_string());
-
-  message.set_allocated_foo_string(new string(kHello));
-  EXPECT_TRUE(message.has_foo_string());
-  EXPECT_EQ(kHello, message.foo_string());
-}
-
-
-TEST_F(OneofTest, SetMessage) {
-  // Check that setting a message field works
-  unittest::TestOneof2 message;
-
-  // Unset field returns default instance
-  EXPECT_EQ(&message.foo_message(),
-            &unittest::TestOneof2_NestedMessage::default_instance());
-  EXPECT_EQ(message.foo_message().qux_int(), 0);
-
-  message.mutable_foo_message()->set_qux_int(234);
-  EXPECT_TRUE(message.has_foo_message());
-  EXPECT_EQ(message.foo_message().qux_int(), 234);
-  message.clear_foo_message();
-  EXPECT_FALSE(message.has_foo_message());
-}
-
-TEST_F(OneofTest, ReleaseMessage) {
-  // Check that release_foo() starts out NULL, and gives us a value
-  // that we can delete after it's been set.
-  unittest::TestOneof2 message;
-
-  EXPECT_EQ(NULL, message.release_foo_message());
-  EXPECT_FALSE(message.has_foo_message());
-
-  message.mutable_foo_message()->set_qux_int(1);
-  EXPECT_TRUE(message.has_foo_message());
-  google::protobuf::scoped_ptr<unittest::TestOneof2_NestedMessage> mes(
-      message.release_foo_message());
-  EXPECT_FALSE(message.has_foo_message());
-  ASSERT_TRUE(mes != NULL);
-  EXPECT_EQ(1, mes->qux_int());
-
-  EXPECT_EQ(NULL, message.release_foo_message());
-  EXPECT_FALSE(message.has_foo_message());
-}
-
-TEST_F(OneofTest, SetAllocatedMessage) {
-  // Check that set_allocated_foo() works for messages.
-  unittest::TestOneof2 message;
-
-  EXPECT_FALSE(message.has_foo_message());
-
-  message.mutable_foo_message()->set_qux_int(1);
-  EXPECT_TRUE(message.has_foo_message());
-
-  message.set_allocated_foo_message(NULL);
-  EXPECT_FALSE(message.has_foo_message());
-  EXPECT_EQ(&message.foo_message(),
-            &unittest::TestOneof2_NestedMessage::default_instance());
-
-  message.mutable_foo_message()->set_qux_int(1);
-  unittest::TestOneof2_NestedMessage* mes = message.release_foo_message();
-  ASSERT_TRUE(mes != NULL);
-  EXPECT_FALSE(message.has_foo_message());
-
-  message.set_allocated_foo_message(mes);
-  EXPECT_TRUE(message.has_foo_message());
-  EXPECT_EQ(1, message.foo_message().qux_int());
-}
-
-
-TEST_F(OneofTest, Clear) {
-  unittest::TestOneof2 message;
-
-  message.set_foo_int(1);
-  EXPECT_TRUE(message.has_foo_int());
-  message.clear_foo_int();
-  EXPECT_FALSE(message.has_foo_int());
-}
-
-TEST_F(OneofTest, Defaults) {
-  unittest::TestOneof2 message;
-
-  EXPECT_FALSE(message.has_foo_int());
-  EXPECT_EQ(message.foo_int(), 0);
-
-  EXPECT_FALSE(message.has_foo_string());
-  EXPECT_EQ(message.foo_string(), "");
-
-
-  EXPECT_FALSE(message.has_foo_bytes());
-  EXPECT_EQ(message.foo_bytes(), "");
-
-  EXPECT_FALSE(message.has_foo_enum());
-  EXPECT_EQ(message.foo_enum(), 1);
-
-  EXPECT_FALSE(message.has_foo_message());
-  EXPECT_EQ(message.foo_message().qux_int(), 0);
-
-  EXPECT_FALSE(message.has_foogroup());
-  EXPECT_EQ(message.foogroup().a(), 0);
-
-
-  EXPECT_FALSE(message.has_bar_int());
-  EXPECT_EQ(message.bar_int(), 5);
-
-  EXPECT_FALSE(message.has_bar_string());
-  EXPECT_EQ(message.bar_string(), "STRING");
-
-
-  EXPECT_FALSE(message.has_bar_bytes());
-  EXPECT_EQ(message.bar_bytes(), "BYTES");
-
-  EXPECT_FALSE(message.has_bar_enum());
-  EXPECT_EQ(message.bar_enum(), 2);
-}
-
-TEST_F(OneofTest, SwapWithEmpty) {
-  unittest::TestOneof2 message1, message2;
-  message1.set_foo_string("FOO");
-  EXPECT_TRUE(message1.has_foo_string());
-  message1.Swap(&message2);
-  EXPECT_FALSE(message1.has_foo_string());
-  EXPECT_TRUE(message2.has_foo_string());
-  EXPECT_EQ(message2.foo_string(), "FOO");
-}
-
-TEST_F(OneofTest, SwapWithSelf) {
-  unittest::TestOneof2 message;
-  message.set_foo_string("FOO");
-  EXPECT_TRUE(message.has_foo_string());
-  message.Swap(&message);
-  EXPECT_TRUE(message.has_foo_string());
-  EXPECT_EQ(message.foo_string(), "FOO");
-}
-
-TEST_F(OneofTest, SwapBothHasFields) {
-  unittest::TestOneof2 message1, message2;
-
-  message1.set_foo_string("FOO");
-  EXPECT_TRUE(message1.has_foo_string());
-  message2.mutable_foo_message()->set_qux_int(1);
-  EXPECT_TRUE(message2.has_foo_message());
-
-  message1.Swap(&message2);
-  EXPECT_FALSE(message1.has_foo_string());
-  EXPECT_FALSE(message2.has_foo_message());
-  EXPECT_TRUE(message1.has_foo_message());
-  EXPECT_EQ(message1.foo_message().qux_int(), 1);
-  EXPECT_TRUE(message2.has_foo_string());
-  EXPECT_EQ(message2.foo_string(), "FOO");
-}
-
-TEST_F(OneofTest, CopyConstructor) {
-  unittest::TestOneof2 message1;
-  message1.set_foo_bytes("FOO");
-
-  unittest::TestOneof2 message2(message1);
-  EXPECT_TRUE(message2.has_foo_bytes());
-  EXPECT_EQ(message2.foo_bytes(), "FOO");
-}
-
-TEST_F(OneofTest, CopyFrom) {
-  unittest::TestOneof2 message1, message2;
-  message1.set_foo_enum(unittest::TestOneof2::BAR);
-  EXPECT_TRUE(message1.has_foo_enum());
-
-  message2.CopyFrom(message1);
-  EXPECT_TRUE(message2.has_foo_enum());
-  EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::BAR);
-
-  // Copying from self should be a no-op.
-  message2.CopyFrom(message2);
-  EXPECT_TRUE(message2.has_foo_enum());
-  EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::BAR);
-}
-
-TEST_F(OneofTest, CopyAssignmentOperator) {
-  unittest::TestOneof2 message1;
-  message1.mutable_foo_message()->set_qux_int(123);
-  EXPECT_TRUE(message1.has_foo_message());
-
-  unittest::TestOneof2 message2;
-  message2 = message1;
-  EXPECT_EQ(message2.foo_message().qux_int(), 123);
-
-  // Make sure that self-assignment does something sane.
-  message2 = message2;
-  EXPECT_EQ(message2.foo_message().qux_int(), 123);
-}
-
-TEST_F(OneofTest, UpcastCopyFrom) {
-  // Test the CopyFrom method that takes in the generic const Message&
-  // parameter.
-  unittest::TestOneof2 message1, message2;
-  message1.mutable_foogroup()->set_a(123);
-  EXPECT_TRUE(message1.has_foogroup());
-
-  const Message* source = implicit_cast<const Message*>(&message1);
-  message2.CopyFrom(*source);
-
-  EXPECT_TRUE(message2.has_foogroup());
-  EXPECT_EQ(message2.foogroup().a(), 123);
-}
-
-// Test the generated SerializeWithCachedSizesToArray(),
-// This indirectly tests MergePartialFromCodedStream()
-// We have to test each field type separately because we cannot set them at the
-// same time
-TEST_F(OneofTest, SerializationToArray) {
-  // Primitive type
-  {
-    unittest::TestOneof2 message1, message2;
-    string data;
-    message1.set_foo_int(123);
-    int size = message1.ByteSize();
-    data.resize(size);
-    uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
-    uint8* end = message1.SerializeWithCachedSizesToArray(start);
-    EXPECT_EQ(size, end - start);
-    EXPECT_TRUE(message2.ParseFromString(data));
-    EXPECT_EQ(message2.foo_int(), 123);
-  }
-
-  // String
-  {
-    unittest::TestOneof2 message1, message2;
-    string data;
-    message1.set_foo_string("foo");
-    int size = message1.ByteSize();
-    data.resize(size);
-    uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
-    uint8* end = message1.SerializeWithCachedSizesToArray(start);
-    EXPECT_EQ(size, end - start);
-    EXPECT_TRUE(message2.ParseFromString(data));
-    EXPECT_EQ(message2.foo_string(), "foo");
-  }
-
-
-  // Bytes
-  {
-    unittest::TestOneof2 message1, message2;
-    string data;
-    message1.set_foo_bytes("qux");
-    int size = message1.ByteSize();
-    data.resize(size);
-    uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
-    uint8* end = message1.SerializeWithCachedSizesToArray(start);
-    EXPECT_EQ(size, end - start);
-    EXPECT_TRUE(message2.ParseFromString(data));
-    EXPECT_EQ(message2.foo_bytes(), "qux");
-  }
-
-  // Enum
-  {
-    unittest::TestOneof2 message1, message2;
-    string data;
-    message1.set_foo_enum(unittest::TestOneof2::FOO);
-    int size = message1.ByteSize();
-    data.resize(size);
-    uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
-    uint8* end = message1.SerializeWithCachedSizesToArray(start);
-    EXPECT_EQ(size, end - start);
-    EXPECT_TRUE(message2.ParseFromString(data));
-    EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::FOO);
-  }
-
-  // Message
-  {
-    unittest::TestOneof2 message1, message2;
-    string data;
-    message1.mutable_foo_message()->set_qux_int(234);
-    int size = message1.ByteSize();
-    data.resize(size);
-    uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
-    uint8* end = message1.SerializeWithCachedSizesToArray(start);
-    EXPECT_EQ(size, end - start);
-    EXPECT_TRUE(message2.ParseFromString(data));
-    EXPECT_EQ(message2.foo_message().qux_int(), 234);
-  }
-
-  // Group
-  {
-    unittest::TestOneof2 message1, message2;
-    string data;
-    message1.mutable_foogroup()->set_a(345);
-    int size = message1.ByteSize();
-    data.resize(size);
-    uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
-    uint8* end = message1.SerializeWithCachedSizesToArray(start);
-    EXPECT_EQ(size, end - start);
-    EXPECT_TRUE(message2.ParseFromString(data));
-    EXPECT_EQ(message2.foogroup().a(), 345);
-  }
-
-}
-
-// Test the generated SerializeWithCachedSizes() by forcing the buffer to write
-// one byte at a time.
-// This indirectly tests MergePartialFromCodedStream()
-// We have to test each field type separately because we cannot set them at the
-// same time
-TEST_F(OneofTest, SerializationToStream) {
-  // Primitive type
-  {
-    unittest::TestOneof2 message1, message2;
-    string data;
-    message1.set_foo_int(123);
-    int size = message1.ByteSize();
-    data.resize(size);
-
-    {
-      // Allow the output stream to buffer only one byte at a time.
-      io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
-      io::CodedOutputStream output_stream(&array_stream);
-      message1.SerializeWithCachedSizes(&output_stream);
-      EXPECT_FALSE(output_stream.HadError());
-      EXPECT_EQ(size, output_stream.ByteCount());
-    }
-
-    EXPECT_TRUE(message2.ParseFromString(data));
-    EXPECT_EQ(message2.foo_int(), 123);
-  }
-
-  // String
-  {
-    unittest::TestOneof2 message1, message2;
-    string data;
-    message1.set_foo_string("foo");
-    int size = message1.ByteSize();
-    data.resize(size);
-
-    {
-      // Allow the output stream to buffer only one byte at a time.
-      io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
-      io::CodedOutputStream output_stream(&array_stream);
-      message1.SerializeWithCachedSizes(&output_stream);
-      EXPECT_FALSE(output_stream.HadError());
-      EXPECT_EQ(size, output_stream.ByteCount());
-    }
-
-    EXPECT_TRUE(message2.ParseFromString(data));
-    EXPECT_EQ(message2.foo_string(), "foo");
-  }
-
-
-  // Bytes
-  {
-    unittest::TestOneof2 message1, message2;
-    string data;
-    message1.set_foo_bytes("qux");
-    int size = message1.ByteSize();
-    data.resize(size);
-
-    {
-      // Allow the output stream to buffer only one byte at a time.
-      io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
-      io::CodedOutputStream output_stream(&array_stream);
-      message1.SerializeWithCachedSizes(&output_stream);
-      EXPECT_FALSE(output_stream.HadError());
-      EXPECT_EQ(size, output_stream.ByteCount());
-    }
-
-    EXPECT_TRUE(message2.ParseFromString(data));
-    EXPECT_EQ(message2.foo_bytes(), "qux");
-  }
-
-  // Enum
-  {
-    unittest::TestOneof2 message1, message2;
-    string data;
-    message1.set_foo_enum(unittest::TestOneof2::FOO);
-    int size = message1.ByteSize();
-    data.resize(size);
-
-    {
-      // Allow the output stream to buffer only one byte at a time.
-      io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
-      io::CodedOutputStream output_stream(&array_stream);
-      message1.SerializeWithCachedSizes(&output_stream);
-      EXPECT_FALSE(output_stream.HadError());
-      EXPECT_EQ(size, output_stream.ByteCount());
-    }
-
-    EXPECT_TRUE(message2.ParseFromString(data));
-    EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::FOO);
-  }
-
-  // Message
-  {
-    unittest::TestOneof2 message1, message2;
-    string data;
-    message1.mutable_foo_message()->set_qux_int(234);
-    int size = message1.ByteSize();
-    data.resize(size);
-
-    {
-      // Allow the output stream to buffer only one byte at a time.
-      io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
-      io::CodedOutputStream output_stream(&array_stream);
-      message1.SerializeWithCachedSizes(&output_stream);
-      EXPECT_FALSE(output_stream.HadError());
-      EXPECT_EQ(size, output_stream.ByteCount());
-    }
-
-    EXPECT_TRUE(message2.ParseFromString(data));
-    EXPECT_EQ(message2.foo_message().qux_int(), 234);
-  }
-
-  // Group
-  {
-    unittest::TestOneof2 message1, message2;
-    string data;
-    message1.mutable_foogroup()->set_a(345);
-    int size = message1.ByteSize();
-    data.resize(size);
-
-    {
-      // Allow the output stream to buffer only one byte at a time.
-      io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
-      io::CodedOutputStream output_stream(&array_stream);
-      message1.SerializeWithCachedSizes(&output_stream);
-      EXPECT_FALSE(output_stream.HadError());
-      EXPECT_EQ(size, output_stream.ByteCount());
-    }
-
-    EXPECT_TRUE(message2.ParseFromString(data));
-    EXPECT_EQ(message2.foogroup().a(), 345);
-  }
-
-}
-
-TEST_F(OneofTest, MergeFrom) {
-  unittest::TestOneof2 message1, message2;
-
-  message1.set_foo_int(123);
-  message2.MergeFrom(message1);
-  TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
-  EXPECT_TRUE(message2.has_foo_int());
-  EXPECT_EQ(message2.foo_int(), 123);
-
-  message1.set_foo_string("foo");
-  message2.MergeFrom(message1);
-  TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
-  EXPECT_TRUE(message2.has_foo_string());
-  EXPECT_EQ(message2.foo_string(), "foo");
-
-
-  message1.set_foo_bytes("qux");
-  message2.MergeFrom(message1);
-  TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
-  EXPECT_TRUE(message2.has_foo_bytes());
-  EXPECT_EQ(message2.foo_bytes(), "qux");
-
-  message1.set_foo_enum(unittest::TestOneof2::FOO);
-  message2.MergeFrom(message1);
-  TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
-  EXPECT_TRUE(message2.has_foo_enum());
-  EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::FOO);
-
-  message1.mutable_foo_message()->set_qux_int(234);
-  message2.MergeFrom(message1);
-  TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
-  EXPECT_TRUE(message2.has_foo_message());
-  EXPECT_EQ(message2.foo_message().qux_int(), 234);
-
-  message1.mutable_foogroup()->set_a(345);
-  message2.MergeFrom(message1);
-  TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
-  EXPECT_TRUE(message2.has_foogroup());
-  EXPECT_EQ(message2.foogroup().a(), 345);
-
-}
-
 }  // namespace cpp_unittest
 }  // namespace cpp
 }  // namespace compiler
-
-namespace no_generic_services_test {
-  // Verify that no class called "TestService" was defined in
-  // unittest_no_generic_services.pb.h by defining a different type by the same
-  // name.  If such a service was generated, this will not compile.
-  struct TestService {
-    int i;
-  };
-}
-
-namespace compiler {
-namespace cpp {
-namespace cpp_unittest {
-
-TEST_F(GeneratedServiceTest, NoGenericServices) {
-  // Verify that non-services in unittest_no_generic_services.proto were
-  // generated.
-  no_generic_services_test::TestMessage message;
-  message.set_a(1);
-  message.SetExtension(no_generic_services_test::test_extension, 123);
-  no_generic_services_test::TestEnum e = no_generic_services_test::FOO;
-  EXPECT_EQ(e, 1);
-
-  // Verify that a ServiceDescriptor is generated for the service even if the
-  // class itself is not.
-  const FileDescriptor* file =
-      no_generic_services_test::TestMessage::descriptor()->file();
-
-  ASSERT_EQ(1, file->service_count());
-  EXPECT_EQ("TestService", file->service(0)->name());
-  ASSERT_EQ(1, file->service(0)->method_count());
-  EXPECT_EQ("Foo", file->service(0)->method(0)->name());
-}
-
-#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
-
-// ===================================================================
-
-// This test must run last.  It verifies that descriptors were or were not
-// initialized depending on whether PROTOBUF_TEST_NO_DESCRIPTORS was defined.
-// When this is defined, we skip all tests which are expected to trigger
-// descriptor initialization.  This verifies that everything else still works
-// if descriptors are not initialized.
-TEST(DescriptorInitializationTest, Initialized) {
-#ifdef PROTOBUF_TEST_NO_DESCRIPTORS
-  bool should_have_descriptors = false;
-#else
-  bool should_have_descriptors = true;
-#endif
-
-  EXPECT_EQ(should_have_descriptors,
-    DescriptorPool::generated_pool()->InternalIsFileLoaded(
-      "google/protobuf/unittest.proto"));
-}
-
-}  // namespace cpp_unittest
-
-}  // namespace cpp
-}  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.inc b/src/google/protobuf/compiler/cpp/cpp_unittest.inc
new file mode 100644
index 0000000..ff6354f
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.inc
@@ -0,0 +1,2281 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// To test the code generator, we actually use it to generate code for
+// google/protobuf/unittest.proto, then test that.  This means that we
+// are actually testing the parser and other parts of the system at the same
+// time, and that problems in the generator may show up as compile-time errors
+// rather than unittest failures, which may be surprising.  However, testing
+// the output of the C++ generator directly would be very hard.  We can't very
+// well just check it against golden files since those files would have to be
+// updated for any small change; such a test would be very brittle and probably
+// not very helpful.  What we really want to test is that the code compiles
+// correctly and produces the interfaces we expect, which is why this test
+// is written this way.
+
+#include <google/protobuf/compiler/cpp/cpp_unittest.h>
+
+#include <memory>
+#include <vector>
+
+#include <google/protobuf/unittest_no_arena.pb.h>
+#if !defined(GOOGLE_PROTOBUF_CMAKE_BUILD) && !defined(_MSC_VER)
+// We exclude this large proto from cmake build because it's too large for
+// visual studio to compile (report internal errors).
+#include <google/protobuf/unittest_enormous_descriptor.pb.h>
+#endif
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h>
+#include <google/protobuf/compiler/importer.h>
+#include <google/protobuf/unittest_no_generic_services.pb.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/dynamic_message.h>
+
+#include <google/protobuf/stubs/callback.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/stubs/stl_util.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
+namespace cpp_unittest {
+
+
+class MockErrorCollector : public MultiFileErrorCollector {
+ public:
+  MockErrorCollector() {}
+  ~MockErrorCollector() {}
+
+  string text_;
+
+  // implements ErrorCollector ---------------------------------------
+  void AddError(const string& filename, int line, int column,
+                const string& message) {
+    strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n",
+                                 filename, line, column, message);
+  }
+};
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
+// Test that generated code has proper descriptors:
+// Parse a descriptor directly (using google::protobuf::compiler::Importer) and
+// compare it to the one that was produced by generated code.
+TEST(GENERATED_DESCRIPTOR_TEST_NAME, IdenticalDescriptors) {
+  const FileDescriptor* generated_descriptor =
+    UNITTEST::TestAllTypes::descriptor()->file();
+
+  // Set up the Importer.
+  MockErrorCollector error_collector;
+  DiskSourceTree source_tree;
+  source_tree.MapPath("", TestSourceDir());
+  Importer importer(&source_tree, &error_collector);
+
+  // Import (parse) unittest.proto.
+  const FileDescriptor* parsed_descriptor =
+    importer.Import(UNITTEST_PROTO_PATH);
+  EXPECT_EQ("", error_collector.text_);
+  ASSERT_TRUE(parsed_descriptor != NULL);
+
+  // Test that descriptors are generated correctly by converting them to
+  // FileDescriptorProtos and comparing.
+  FileDescriptorProto generated_descriptor_proto, parsed_descriptor_proto;
+  generated_descriptor->CopyTo(&generated_descriptor_proto);
+  parsed_descriptor->CopyTo(&parsed_descriptor_proto);
+
+  EXPECT_EQ(parsed_descriptor_proto.DebugString(),
+            generated_descriptor_proto.DebugString());
+}
+
+#if !defined(GOOGLE_PROTOBUF_CMAKE_BUILD) && !defined(_MSC_VER)
+// Test that generated code has proper descriptors:
+// Touch a descriptor generated from an enormous message to validate special
+// handling for descriptors exceeding the C++ standard's recommended minimum
+// limit for string literal size
+TEST(GENERATED_DESCRIPTOR_TEST_NAME, EnormousDescriptor) {
+  const Descriptor* generated_descriptor =
+    TestEnormousDescriptor::descriptor();
+
+  EXPECT_TRUE(generated_descriptor != NULL);
+}
+#endif
+
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
+
+// ===================================================================
+
+TEST(GENERATED_MESSAGE_TEST_NAME, Defaults) {
+  // Check that all default values are set correctly in the initial message.
+  UNITTEST::TestAllTypes message;
+
+  TestUtil::ExpectClear(message);
+
+  // Messages should return pointers to default instances until first use.
+  // (This is not checked by ExpectClear() since it is not actually true after
+  // the fields have been set and then cleared.)
+  EXPECT_EQ(&UNITTEST::TestAllTypes::OptionalGroup::default_instance(),
+            &message.optionalgroup());
+  EXPECT_EQ(&UNITTEST::TestAllTypes::NestedMessage::default_instance(),
+            &message.optional_nested_message());
+  EXPECT_EQ(&UNITTEST::ForeignMessage::default_instance(),
+            &message.optional_foreign_message());
+  EXPECT_EQ(&UNITTEST_IMPORT::ImportMessage::default_instance(),
+            &message.optional_import_message());
+}
+
+#ifndef PROTOBUF_USE_DLLS
+TEST(GENERATED_MESSAGE_TEST_NAME, Int32StringConversion) {
+  EXPECT_EQ("971", Int32ToString(971));
+  EXPECT_EQ("(~0x7fffffff)", Int32ToString(kint32min));
+  EXPECT_EQ("2147483647", Int32ToString(kint32max));
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, Int64StringConversion) {
+  EXPECT_EQ("GOOGLE_LONGLONG(971)", Int64ToString(971));
+  EXPECT_EQ("GOOGLE_LONGLONG(-2147483648)", Int64ToString(kint32min));
+  EXPECT_EQ("GOOGLE_LONGLONG(~0x7fffffffffffffff)", Int64ToString(kint64min));
+  EXPECT_EQ("GOOGLE_LONGLONG(9223372036854775807)", Int64ToString(kint64max));
+}
+#endif  // !PROTOBUF_USE_DLLS
+
+TEST(GENERATED_MESSAGE_TEST_NAME, FloatingPointDefaults) {
+  const UNITTEST::TestExtremeDefaultValues& extreme_default =
+      UNITTEST::TestExtremeDefaultValues::default_instance();
+
+  EXPECT_EQ(0.0f, extreme_default.zero_float());
+  EXPECT_EQ(1.0f, extreme_default.one_float());
+  EXPECT_EQ(1.5f, extreme_default.small_float());
+  EXPECT_EQ(-1.0f, extreme_default.negative_one_float());
+  EXPECT_EQ(-1.5f, extreme_default.negative_float());
+  EXPECT_EQ(2.0e8f, extreme_default.large_float());
+  EXPECT_EQ(-8e-28f, extreme_default.small_negative_float());
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            extreme_default.inf_double());
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(),
+            extreme_default.neg_inf_double());
+  EXPECT_TRUE(extreme_default.nan_double() != extreme_default.nan_double());
+  EXPECT_EQ(std::numeric_limits<float>::infinity(),
+            extreme_default.inf_float());
+  EXPECT_EQ(-std::numeric_limits<float>::infinity(),
+            extreme_default.neg_inf_float());
+  EXPECT_TRUE(extreme_default.nan_float() != extreme_default.nan_float());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, Trigraph) {
+  const UNITTEST::TestExtremeDefaultValues& extreme_default =
+      UNITTEST::TestExtremeDefaultValues::default_instance();
+
+  EXPECT_EQ("? ? ?? ?? ??? ?\?/ ?\?-", extreme_default.cpp_trigraph());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ExtremeSmallIntegerDefault) {
+  const UNITTEST::TestExtremeDefaultValues& extreme_default =
+      UNITTEST::TestExtremeDefaultValues::default_instance();
+  EXPECT_EQ(~0x7fffffff, kint32min);
+  EXPECT_EQ(GOOGLE_LONGLONG(~0x7fffffffffffffff), kint64min);
+  EXPECT_EQ(kint32min, extreme_default.really_small_int32());
+  EXPECT_EQ(kint64min, extreme_default.really_small_int64());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, Accessors) {
+  // Set every field to a unique value then go back and check all those
+  // values.
+  UNITTEST::TestAllTypes message;
+
+  TestUtil::SetAllFields(&message);
+  TestUtil::ExpectAllFieldsSet(message);
+
+  TestUtil::ModifyRepeatedFields(&message);
+  TestUtil::ExpectRepeatedFieldsModified(message);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, MutableStringDefault) {
+  // mutable_foo() for a string should return a string initialized to its
+  // default value.
+  UNITTEST::TestAllTypes message;
+
+  EXPECT_EQ("hello", *message.mutable_default_string());
+
+  // Note that the first time we call mutable_foo(), we get a newly-allocated
+  // string, but if we clear it and call it again, we get the same object again.
+  // We should verify that it has its default value in both cases.
+  message.set_default_string("blah");
+  message.Clear();
+
+  EXPECT_EQ("hello", *message.mutable_default_string());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, StringDefaults) {
+  UNITTEST::TestExtremeDefaultValues message;
+  // Check if '\000' can be used in default string value.
+  EXPECT_EQ(string("hel\000lo", 6), message.string_with_zero());
+  EXPECT_EQ(string("wor\000ld", 6), message.bytes_with_zero());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, 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());
+  std::unique_ptr<string> str(message.release_default_string());
+  EXPECT_FALSE(message.has_default_string());
+  ASSERT_TRUE(str != NULL);
+  EXPECT_EQ("blah", *str);
+
+  EXPECT_EQ(NULL, message.release_default_string());
+  EXPECT_FALSE(message.has_default_string());
+  EXPECT_EQ("hello", message.default_string());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, 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);
+  std::unique_ptr<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());
+
+  EXPECT_EQ(NULL, message.release_optional_nested_message());
+  EXPECT_FALSE(message.has_optional_nested_message());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, SetAllocatedString) {
+  // Check that set_allocated_foo() works for strings.
+  UNITTEST::TestAllTypes message;
+
+  EXPECT_FALSE(message.has_optional_string());
+  const string kHello("hello");
+  message.set_optional_string(kHello);
+  EXPECT_TRUE(message.has_optional_string());
+
+  message.set_allocated_optional_string(NULL);
+  EXPECT_FALSE(message.has_optional_string());
+  EXPECT_EQ("", message.optional_string());
+
+  message.set_allocated_optional_string(new string(kHello));
+  EXPECT_TRUE(message.has_optional_string());
+  EXPECT_EQ(kHello, message.optional_string());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, SetAllocatedMessage) {
+  // Check that set_allocated_foo() can be called in all cases.
+  UNITTEST::TestAllTypes message;
+
+  EXPECT_FALSE(message.has_optional_nested_message());
+
+  message.mutable_optional_nested_message()->set_bb(1);
+  EXPECT_TRUE(message.has_optional_nested_message());
+
+  message.set_allocated_optional_nested_message(NULL);
+  EXPECT_FALSE(message.has_optional_nested_message());
+  EXPECT_EQ(&UNITTEST::TestAllTypes::NestedMessage::default_instance(),
+            &message.optional_nested_message());
+
+  message.mutable_optional_nested_message()->set_bb(1);
+  UNITTEST::TestAllTypes::NestedMessage* nest =
+      message.release_optional_nested_message();
+  ASSERT_TRUE(nest != NULL);
+  EXPECT_FALSE(message.has_optional_nested_message());
+
+  message.set_allocated_optional_nested_message(nest);
+  EXPECT_TRUE(message.has_optional_nested_message());
+  EXPECT_EQ(1, message.optional_nested_message().bb());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, Clear) {
+  // Set every field to a unique value, clear the message, then check that
+  // it is cleared.
+  UNITTEST::TestAllTypes message;
+
+  TestUtil::SetAllFields(&message);
+  message.Clear();
+  TestUtil::ExpectClear(message);
+
+  // Unlike with the defaults test, we do NOT expect that requesting embedded
+  // messages will return a pointer to the default instance.  Instead, they
+  // should return the objects that were created when mutable_blah() was
+  // called.
+  EXPECT_NE(&UNITTEST::TestAllTypes::OptionalGroup::default_instance(),
+            &message.optionalgroup());
+  EXPECT_NE(&UNITTEST::TestAllTypes::NestedMessage::default_instance(),
+            &message.optional_nested_message());
+  EXPECT_NE(&UNITTEST::ForeignMessage::default_instance(),
+            &message.optional_foreign_message());
+  EXPECT_NE(&UNITTEST_IMPORT::ImportMessage::default_instance(),
+            &message.optional_import_message());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, EmbeddedNullsInBytesCharStar) {
+  UNITTEST::TestAllTypes message;
+
+  const char* value = "\0lalala\0\0";
+  message.set_optional_bytes(value, 9);
+  ASSERT_EQ(9, message.optional_bytes().size());
+  EXPECT_EQ(0, memcmp(value, message.optional_bytes().data(), 9));
+
+  message.add_repeated_bytes(value, 9);
+  ASSERT_EQ(9, message.repeated_bytes(0).size());
+  EXPECT_EQ(0, memcmp(value, message.repeated_bytes(0).data(), 9));
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ClearOneField) {
+  // Set every field to a unique value, then clear one value and insure that
+  // only that one value is cleared.
+  UNITTEST::TestAllTypes message;
+
+  TestUtil::SetAllFields(&message);
+  int64 original_value = message.optional_int64();
+
+  // Clear the field and make sure it shows up as cleared.
+  message.clear_optional_int64();
+  EXPECT_FALSE(message.has_optional_int64());
+  EXPECT_EQ(0, message.optional_int64());
+
+  // Other adjacent fields should not be cleared.
+  EXPECT_TRUE(message.has_optional_int32());
+  EXPECT_TRUE(message.has_optional_uint32());
+
+  // Make sure if we set it again, then all fields are set.
+  message.set_optional_int64(original_value);
+  TestUtil::ExpectAllFieldsSet(message);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, StringCharStarLength) {
+  // Verify that we can use a char*,length to set one of the string fields.
+  UNITTEST::TestAllTypes message;
+  message.set_optional_string("abcdef", 3);
+  EXPECT_EQ("abc", message.optional_string());
+
+  // Verify that we can use a char*,length to add to a repeated string field.
+  message.add_repeated_string("abcdef", 3);
+  EXPECT_EQ(1, message.repeated_string_size());
+  EXPECT_EQ("abc", message.repeated_string(0));
+
+  // Verify that we can use a char*,length to set a repeated string field.
+  message.set_repeated_string(0, "wxyz", 2);
+  EXPECT_EQ("wx", message.repeated_string(0));
+}
+
+#if LANG_CXX11
+TEST(GENERATED_MESSAGE_TEST_NAME, StringMove) {
+  // Verify that we trigger the move behavior on a scalar setter.
+  protobuf_unittest_no_arena::TestAllTypes message;
+  {
+    string tmp(32, 'a');
+
+    const char* old_data = tmp.data();
+    message.set_optional_string(std::move(tmp));
+    const char* new_data = message.optional_string().data();
+
+    EXPECT_EQ(old_data, new_data);
+    EXPECT_EQ(string(32, 'a'), message.optional_string());
+
+    string tmp2(32, 'b');
+    old_data = tmp2.data();
+    message.set_optional_string(std::move(tmp2));
+    new_data = message.optional_string().data();
+
+    EXPECT_EQ(old_data, new_data);
+    EXPECT_EQ(string(32, 'b'), message.optional_string());
+  }
+
+  // Verify that we trigger the move behavior on a oneof setter.
+  {
+    string tmp(32, 'a');
+
+    const char* old_data = tmp.data();
+    message.set_oneof_string(std::move(tmp));
+    const char* new_data = message.oneof_string().data();
+
+    EXPECT_EQ(old_data, new_data);
+    EXPECT_EQ(string(32, 'a'), message.oneof_string());
+
+    string tmp2(32, 'b');
+    old_data = tmp2.data();
+    message.set_oneof_string(std::move(tmp2));
+    new_data = message.oneof_string().data();
+
+    EXPECT_EQ(old_data, new_data);
+    EXPECT_EQ(string(32, 'b'), message.oneof_string());
+  }
+
+  // Verify that we trigger the move behavior on a repeated setter.
+  {
+    string tmp(32, 'a');
+
+    const char* old_data = tmp.data();
+    message.add_repeated_string(std::move(tmp));
+    const char* new_data = message.repeated_string(0).data();
+
+    EXPECT_EQ(old_data, new_data);
+    EXPECT_EQ(string(32, 'a'), message.repeated_string(0));
+
+    string tmp2(32, 'b');
+    old_data = tmp2.data();
+    message.set_repeated_string(0, std::move(tmp2));
+    new_data = message.repeated_string(0).data();
+
+    EXPECT_EQ(old_data, new_data);
+    EXPECT_EQ(string(32, 'b'), message.repeated_string(0));
+  }
+}
+#endif
+
+
+TEST(GENERATED_MESSAGE_TEST_NAME, CopyFrom) {
+  UNITTEST::TestAllTypes message1, message2;
+
+  TestUtil::SetAllFields(&message1);
+  message2.CopyFrom(message1);
+  TestUtil::ExpectAllFieldsSet(message2);
+
+  // Copying from self should be a no-op.
+  message2.CopyFrom(message2);
+  TestUtil::ExpectAllFieldsSet(message2);
+}
+
+
+TEST(GENERATED_MESSAGE_TEST_NAME, SwapWithEmpty) {
+  UNITTEST::TestAllTypes message1, message2;
+  TestUtil::SetAllFields(&message1);
+
+  TestUtil::ExpectAllFieldsSet(message1);
+  TestUtil::ExpectClear(message2);
+  message1.Swap(&message2);
+  TestUtil::ExpectAllFieldsSet(message2);
+  TestUtil::ExpectClear(message1);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, SwapWithSelf) {
+  UNITTEST::TestAllTypes message;
+  TestUtil::SetAllFields(&message);
+  TestUtil::ExpectAllFieldsSet(message);
+  message.Swap(&message);
+  TestUtil::ExpectAllFieldsSet(message);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, SwapWithOther) {
+  UNITTEST::TestAllTypes message1, message2;
+
+  message1.set_optional_int32(123);
+  message1.set_optional_string("abc");
+  message1.mutable_optional_nested_message()->set_bb(1);
+  message1.set_optional_nested_enum(UNITTEST::TestAllTypes::FOO);
+  message1.add_repeated_int32(1);
+  message1.add_repeated_int32(2);
+  message1.add_repeated_string("a");
+  message1.add_repeated_string("b");
+  message1.add_repeated_nested_message()->set_bb(7);
+  message1.add_repeated_nested_message()->set_bb(8);
+  message1.add_repeated_nested_enum(UNITTEST::TestAllTypes::FOO);
+  message1.add_repeated_nested_enum(UNITTEST::TestAllTypes::BAR);
+
+  message2.set_optional_int32(456);
+  message2.set_optional_string("def");
+  message2.mutable_optional_nested_message()->set_bb(2);
+  message2.set_optional_nested_enum(UNITTEST::TestAllTypes::BAR);
+  message2.add_repeated_int32(3);
+  message2.add_repeated_string("c");
+  message2.add_repeated_nested_message()->set_bb(9);
+  message2.add_repeated_nested_enum(UNITTEST::TestAllTypes::BAZ);
+
+  message1.Swap(&message2);
+
+  EXPECT_EQ(456, message1.optional_int32());
+  EXPECT_EQ("def", message1.optional_string());
+  EXPECT_EQ(2, message1.optional_nested_message().bb());
+  EXPECT_EQ(UNITTEST::TestAllTypes::BAR, message1.optional_nested_enum());
+  ASSERT_EQ(1, message1.repeated_int32_size());
+  EXPECT_EQ(3, message1.repeated_int32(0));
+  ASSERT_EQ(1, message1.repeated_string_size());
+  EXPECT_EQ("c", message1.repeated_string(0));
+  ASSERT_EQ(1, message1.repeated_nested_message_size());
+  EXPECT_EQ(9, message1.repeated_nested_message(0).bb());
+  ASSERT_EQ(1, message1.repeated_nested_enum_size());
+  EXPECT_EQ(UNITTEST::TestAllTypes::BAZ, message1.repeated_nested_enum(0));
+
+  EXPECT_EQ(123, message2.optional_int32());
+  EXPECT_EQ("abc", message2.optional_string());
+  EXPECT_EQ(1, message2.optional_nested_message().bb());
+  EXPECT_EQ(UNITTEST::TestAllTypes::FOO, message2.optional_nested_enum());
+  ASSERT_EQ(2, message2.repeated_int32_size());
+  EXPECT_EQ(1, message2.repeated_int32(0));
+  EXPECT_EQ(2, message2.repeated_int32(1));
+  ASSERT_EQ(2, message2.repeated_string_size());
+  EXPECT_EQ("a", message2.repeated_string(0));
+  EXPECT_EQ("b", message2.repeated_string(1));
+  ASSERT_EQ(2, message2.repeated_nested_message_size());
+  EXPECT_EQ(7, message2.repeated_nested_message(0).bb());
+  EXPECT_EQ(8, message2.repeated_nested_message(1).bb());
+  ASSERT_EQ(2, message2.repeated_nested_enum_size());
+  EXPECT_EQ(UNITTEST::TestAllTypes::FOO, message2.repeated_nested_enum(0));
+  EXPECT_EQ(UNITTEST::TestAllTypes::BAR, message2.repeated_nested_enum(1));
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ADLSwap) {
+  UNITTEST::TestAllTypes message1, message2;
+  TestUtil::SetAllFields(&message1);
+
+  // Note the address of one of the repeated fields, to verify it was swapped
+  // rather than copied.
+  const int32* addr = &message1.repeated_int32().Get(0);
+
+  using std::swap;
+  swap(message1, message2);
+
+  TestUtil::ExpectAllFieldsSet(message2);
+  TestUtil::ExpectClear(message1);
+
+  EXPECT_EQ(addr, &message2.repeated_int32().Get(0));
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, CopyConstructor) {
+  // All set.
+  {
+    UNITTEST::TestAllTypes message1;
+    TestUtil::SetAllFields(&message1);
+
+    UNITTEST::TestAllTypes message2(message1);
+    TestUtil::ExpectAllFieldsSet(message2);
+  }
+
+  // None set.
+  {
+    UNITTEST::TestAllTypes message1;
+    UNITTEST::TestAllTypes message2(message1);
+
+    EXPECT_FALSE(message1.has_optional_string());
+    EXPECT_FALSE(message2.has_optional_string());
+    EXPECT_EQ(message1.optional_string(), message2.optional_string());
+
+    EXPECT_FALSE(message1.has_optional_bytes());
+    EXPECT_FALSE(message2.has_optional_bytes());
+    EXPECT_EQ(message1.optional_bytes(), message2.optional_bytes());
+
+    EXPECT_FALSE(message1.has_optional_nested_message());
+    EXPECT_FALSE(message2.has_optional_nested_message());
+    EXPECT_EQ(&message1.optional_nested_message(),
+              &message2.optional_nested_message());
+
+    EXPECT_FALSE(message1.has_optional_foreign_message());
+    EXPECT_FALSE(message2.has_optional_foreign_message());
+    EXPECT_EQ(&message1.optional_foreign_message(),
+              &message2.optional_foreign_message());
+
+    EXPECT_FALSE(message1.has_optional_import_message());
+    EXPECT_FALSE(message2.has_optional_import_message());
+    EXPECT_EQ(&message1.optional_import_message(),
+              &message2.optional_import_message());
+
+    EXPECT_FALSE(message1.has_optional_public_import_message());
+    EXPECT_FALSE(message2.has_optional_public_import_message());
+    EXPECT_EQ(&message1.optional_public_import_message(),
+              &message2.optional_public_import_message());
+
+    EXPECT_FALSE(message1.has_optional_lazy_message());
+    EXPECT_FALSE(message2.has_optional_lazy_message());
+    EXPECT_EQ(&message1.optional_lazy_message(),
+              &message2.optional_lazy_message());
+  }
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, CopyConstructorWithArenas) {
+  Arena arena;
+  UNITTEST::TestAllTypes* message1 =
+      Arena::CreateMessage<UNITTEST::TestAllTypes>(&arena);
+  TestUtil::SetAllFields(message1);
+
+  UNITTEST::TestAllTypes message2_stack(*message1);
+  TestUtil::ExpectAllFieldsSet(message2_stack);
+
+  std::unique_ptr<UNITTEST::TestAllTypes> message2_heap(
+      new UNITTEST::TestAllTypes(*message1));
+  TestUtil::ExpectAllFieldsSet(*message2_heap);
+
+  arena.Reset();
+
+  // Verify that the copies are still intact.
+  TestUtil::ExpectAllFieldsSet(message2_stack);
+  TestUtil::ExpectAllFieldsSet(*message2_heap);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, CopyAssignmentOperator) {
+  UNITTEST::TestAllTypes message1;
+  TestUtil::SetAllFields(&message1);
+
+  UNITTEST::TestAllTypes message2;
+  message2 = message1;
+  TestUtil::ExpectAllFieldsSet(message2);
+
+  // Make sure that self-assignment does something sane.
+  message2.operator=(message2);
+  TestUtil::ExpectAllFieldsSet(message2);
+}
+
+#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \
+    !defined(GOOGLE_PROTOBUF_NO_RTTI)
+TEST(GENERATED_MESSAGE_TEST_NAME, UpcastCopyFrom) {
+  // Test the CopyFrom method that takes in the generic const Message&
+  // parameter.
+  UNITTEST::TestAllTypes message1, message2;
+
+  TestUtil::SetAllFields(&message1);
+
+  const Message* source = implicit_cast<const Message*>(&message1);
+  message2.CopyFrom(*source);
+
+  TestUtil::ExpectAllFieldsSet(message2);
+}
+#endif
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
+TEST(GENERATED_MESSAGE_TEST_NAME, DynamicMessageCopyFrom) {
+  // Test copying from a DynamicMessage, which must fall back to using
+  // reflection.
+  UNITTEST::TestAllTypes message2;
+
+  // Construct a new version of the dynamic message via the factory.
+  DynamicMessageFactory factory;
+  std::unique_ptr<Message> message1;
+  message1.reset(factory.GetPrototype(
+                     UNITTEST::TestAllTypes::descriptor())->New());
+
+  TestUtil::ReflectionTester reflection_tester(
+    UNITTEST::TestAllTypes::descriptor());
+  reflection_tester.SetAllFieldsViaReflection(message1.get());
+
+  message2.CopyFrom(*message1);
+
+  TestUtil::ExpectAllFieldsSet(message2);
+}
+
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
+
+TEST(GENERATED_MESSAGE_TEST_NAME, NonEmptyMergeFrom) {
+  // Test merging with a non-empty message. Code is a modified form
+  // of that found in google/protobuf/reflection_ops_unittest.cc.
+  UNITTEST::TestAllTypes message1, message2;
+
+  TestUtil::SetAllFields(&message1);
+
+  // This field will test merging into an empty spot.
+  message2.set_optional_int32(message1.optional_int32());
+  message1.clear_optional_int32();
+
+  // This tests overwriting.
+  message2.set_optional_string(message1.optional_string());
+  message1.set_optional_string("something else");
+
+  // This tests concatenating.
+  message2.add_repeated_int32(message1.repeated_int32(1));
+  int32 i = message1.repeated_int32(0);
+  message1.clear_repeated_int32();
+  message1.add_repeated_int32(i);
+
+  message1.MergeFrom(message2);
+
+  TestUtil::ExpectAllFieldsSet(message1);
+}
+
+
+// Test the generated SerializeWithCachedSizesToArray(),
+TEST(GENERATED_MESSAGE_TEST_NAME, SerializationToArray) {
+  UNITTEST::TestAllTypes message1, message2;
+  string data;
+  TestUtil::SetAllFields(&message1);
+  int size = message1.ByteSizeLong();
+  data.resize(size);
+  uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
+  uint8* end = message1.SerializeWithCachedSizesToArray(start);
+  EXPECT_EQ(size, end - start);
+  EXPECT_TRUE(message2.ParseFromString(data));
+  TestUtil::ExpectAllFieldsSet(message2);
+
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, PackedFieldsSerializationToArray) {
+  UNITTEST::TestPackedTypes packed_message1, packed_message2;
+  string packed_data;
+  TestUtil::SetPackedFields(&packed_message1);
+  int packed_size = packed_message1.ByteSizeLong();
+  packed_data.resize(packed_size);
+  uint8* start = reinterpret_cast<uint8*>(string_as_array(&packed_data));
+  uint8* end = packed_message1.SerializeWithCachedSizesToArray(start);
+  EXPECT_EQ(packed_size, end - start);
+  EXPECT_TRUE(packed_message2.ParseFromString(packed_data));
+  TestUtil::ExpectPackedFieldsSet(packed_message2);
+}
+
+// Test the generated SerializeWithCachedSizes() by forcing the buffer to write
+// one byte at a time.
+TEST(GENERATED_MESSAGE_TEST_NAME, SerializationToStream) {
+  UNITTEST::TestAllTypes message1, message2;
+  TestUtil::SetAllFields(&message1);
+  int size = message1.ByteSizeLong();
+  string data;
+  data.resize(size);
+  {
+    // Allow the output stream to buffer only one byte at a time.
+    io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+    io::CodedOutputStream output_stream(&array_stream);
+    message1.SerializeWithCachedSizes(&output_stream);
+    EXPECT_FALSE(output_stream.HadError());
+    EXPECT_EQ(size, output_stream.ByteCount());
+  }
+  EXPECT_TRUE(message2.ParseFromString(data));
+  TestUtil::ExpectAllFieldsSet(message2);
+
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, PackedFieldsSerializationToStream) {
+  UNITTEST::TestPackedTypes message1, message2;
+  TestUtil::SetPackedFields(&message1);
+  int size = message1.ByteSizeLong();
+  string data;
+  data.resize(size);
+  {
+    // Allow the output stream to buffer only one byte at a time.
+    io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+    io::CodedOutputStream output_stream(&array_stream);
+    message1.SerializeWithCachedSizes(&output_stream);
+    EXPECT_FALSE(output_stream.HadError());
+    EXPECT_EQ(size, output_stream.ByteCount());
+  }
+  EXPECT_TRUE(message2.ParseFromString(data));
+  TestUtil::ExpectPackedFieldsSet(message2);
+}
+
+
+TEST(GENERATED_MESSAGE_TEST_NAME, Required) {
+  // Test that IsInitialized() returns false if required fields are missing.
+  UNITTEST::TestRequired message;
+
+  EXPECT_FALSE(message.IsInitialized());
+  message.set_a(1);
+  EXPECT_FALSE(message.IsInitialized());
+  message.set_b(2);
+  EXPECT_FALSE(message.IsInitialized());
+  message.set_c(3);
+  EXPECT_TRUE(message.IsInitialized());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, RequiredForeign) {
+  // Test that IsInitialized() returns false if required fields in nested
+  // messages are missing.
+  UNITTEST::TestRequiredForeign message;
+
+  EXPECT_TRUE(message.IsInitialized());
+
+  message.mutable_optional_message();
+  EXPECT_FALSE(message.IsInitialized());
+
+  message.mutable_optional_message()->set_a(1);
+  message.mutable_optional_message()->set_b(2);
+  message.mutable_optional_message()->set_c(3);
+  EXPECT_TRUE(message.IsInitialized());
+
+  message.add_repeated_message();
+  EXPECT_FALSE(message.IsInitialized());
+
+  message.mutable_repeated_message(0)->set_a(1);
+  message.mutable_repeated_message(0)->set_b(2);
+  message.mutable_repeated_message(0)->set_c(3);
+  EXPECT_TRUE(message.IsInitialized());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ForeignNested) {
+  // Test that TestAllTypes::NestedMessage can be embedded directly into
+  // another message.
+  UNITTEST::TestForeignNested message;
+
+  // If this compiles and runs without crashing, it must work.  We have
+  // nothing more to test.
+  UNITTEST::TestAllTypes::NestedMessage* nested =
+    message.mutable_foreign_nested();
+  nested->set_bb(1);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ReallyLargeTagNumber) {
+  // Test that really large tag numbers don't break anything.
+  UNITTEST::TestReallyLargeTagNumber message1, message2;
+  string data;
+
+  // For the most part, if this compiles and runs then we're probably good.
+  // (The most likely cause for failure would be if something were attempting
+  // to allocate a lookup table of some sort using tag numbers as the index.)
+  // We'll try serializing just for fun.
+  message1.set_a(1234);
+  message1.set_bb(5678);
+  message1.SerializeToString(&data);
+  EXPECT_TRUE(message2.ParseFromString(data));
+  EXPECT_EQ(1234, message2.a());
+  EXPECT_EQ(5678, message2.bb());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, MutualRecursion) {
+  // Test that mutually-recursive message types work.
+  UNITTEST::TestMutualRecursionA message;
+  UNITTEST::TestMutualRecursionA* nested = message.mutable_bb()->mutable_a();
+  UNITTEST::TestMutualRecursionA* nested2 = nested->mutable_bb()->mutable_a();
+
+  // Again, if the above compiles and runs, that's all we really have to
+  // test, but just for run we'll check that the system didn't somehow come
+  // up with a pointer loop...
+  EXPECT_NE(&message, nested);
+  EXPECT_NE(&message, nested2);
+  EXPECT_NE(nested, nested2);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, CamelCaseFieldNames) {
+  // This test is mainly checking that the following compiles, which verifies
+  // that the field names were coerced to lower-case.
+  //
+  // Protocol buffers standard style is to use lowercase-with-underscores for
+  // field names.  Some old proto1 .protos unfortunately used camel-case field
+  // names.  In proto1, these names were forced to lower-case.  So, we do the
+  // same thing in proto2.
+
+  UNITTEST::TestCamelCaseFieldNames message;
+
+  message.set_primitivefield(2);
+  message.set_stringfield("foo");
+  message.set_enumfield(UNITTEST::FOREIGN_FOO);
+  message.mutable_messagefield()->set_c(6);
+
+  message.add_repeatedprimitivefield(8);
+  message.add_repeatedstringfield("qux");
+  message.add_repeatedenumfield(UNITTEST::FOREIGN_BAR);
+  message.add_repeatedmessagefield()->set_c(15);
+
+  EXPECT_EQ(2, message.primitivefield());
+  EXPECT_EQ("foo", message.stringfield());
+  EXPECT_EQ(UNITTEST::FOREIGN_FOO, message.enumfield());
+  EXPECT_EQ(6, message.messagefield().c());
+
+  EXPECT_EQ(8, message.repeatedprimitivefield(0));
+  EXPECT_EQ("qux", message.repeatedstringfield(0));
+  EXPECT_EQ(UNITTEST::FOREIGN_BAR, message.repeatedenumfield(0));
+  EXPECT_EQ(15, message.repeatedmessagefield(0).c());
+}
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
+TEST(GENERATED_MESSAGE_TEST_NAME, TestOptimizedForSize) {
+  // We rely on the tests in reflection_ops_unittest and wire_format_unittest
+  // to really test that reflection-based methods work.  Here we are mostly
+  // just making sure that TestOptimizedForSize actually builds and seems to
+  // function.
+
+  UNITTEST::TestOptimizedForSize message, message2;
+  message.set_i(1);
+  message.mutable_msg()->set_c(2);
+  message2.CopyFrom(message);
+  EXPECT_EQ(1, message2.i());
+  EXPECT_EQ(2, message2.msg().c());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, TestEmbedOptimizedForSize) {
+  // Verifies that something optimized for speed can contain something optimized
+  // for size.
+
+  UNITTEST::TestEmbedOptimizedForSize message, message2;
+  message.mutable_optional_message()->set_i(1);
+  message.add_repeated_message()->mutable_msg()->set_c(2);
+  string data;
+  message.SerializeToString(&data);
+  ASSERT_TRUE(message2.ParseFromString(data));
+  EXPECT_EQ(1, message2.optional_message().i());
+  EXPECT_EQ(2, message2.repeated_message(0).msg().c());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, TestSpaceUsed) {
+  UNITTEST::TestAllTypes message1;
+  // sizeof provides a lower bound on SpaceUsedLong().
+  EXPECT_LE(sizeof(UNITTEST::TestAllTypes), message1.SpaceUsedLong());
+  const size_t empty_message_size = message1.SpaceUsedLong();
+
+  // Setting primitive types shouldn't affect the space used.
+  message1.set_optional_int32(123);
+  message1.set_optional_int64(12345);
+  message1.set_optional_uint32(123);
+  message1.set_optional_uint64(12345);
+  EXPECT_EQ(empty_message_size, message1.SpaceUsedLong());
+
+  // On some STL implementations, setting the string to a small value should
+  // only increase SpaceUsedLong() by the size of a string object, though this
+  // is not true everywhere.
+  message1.set_optional_string("abc");
+  EXPECT_LE(empty_message_size + message1.optional_string().size(),
+            message1.SpaceUsedLong());
+
+  // Setting a string to a value larger than the string object itself should
+  // increase SpaceUsedLong(), because it cannot store the value internally.
+  message1.set_optional_string(string(sizeof(string) + 1, 'x'));
+  int min_expected_increase = message1.optional_string().capacity();
+  EXPECT_LE(empty_message_size + min_expected_increase,
+            message1.SpaceUsedLong());
+
+  size_t previous_size = message1.SpaceUsedLong();
+  // Adding an optional message should increase the size by the size of the
+  // nested message type. NestedMessage is simple enough (1 int field) that it
+  // is equal to sizeof(NestedMessage)
+  message1.mutable_optional_nested_message();
+  ASSERT_EQ(sizeof(UNITTEST::TestAllTypes::NestedMessage),
+            message1.optional_nested_message().SpaceUsedLong());
+  EXPECT_EQ(previous_size +
+            sizeof(UNITTEST::TestAllTypes::NestedMessage),
+            message1.SpaceUsedLong());
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, TestOneofSpaceUsed) {
+  UNITTEST::TestOneof2 message1;
+  EXPECT_LE(sizeof(UNITTEST::TestOneof2), message1.SpaceUsedLong());
+
+  const size_t empty_message_size = message1.SpaceUsedLong();
+  // Setting primitive types shouldn't affect the space used.
+  message1.set_foo_int(123);
+  message1.set_bar_int(12345);
+  EXPECT_EQ(empty_message_size, message1.SpaceUsedLong());
+
+  // Setting a string in oneof to a small value should only increase
+  // SpaceUsedLong() by the size of a string object.
+  message1.set_foo_string("abc");
+  EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsedLong());
+
+  // Setting a string in oneof to a value larger than the string object itself
+  // should increase SpaceUsedLong(), because it cannot store the value
+  // internally.
+  message1.set_foo_string(string(sizeof(string) + 1, 'x'));
+  int min_expected_increase = message1.foo_string().capacity() +
+      sizeof(string);
+  EXPECT_LE(empty_message_size + min_expected_increase,
+            message1.SpaceUsedLong());
+
+  // Setting a message in oneof should delete the other fields and increase the
+  // size by the size of the nested message type. NestedMessage is simple enough
+  // that it is equal to sizeof(NestedMessage)
+  message1.mutable_foo_message();
+  ASSERT_EQ(sizeof(UNITTEST::TestOneof2::NestedMessage),
+            message1.foo_message().SpaceUsedLong());
+  EXPECT_EQ(empty_message_size +
+            sizeof(UNITTEST::TestOneof2::NestedMessage),
+            message1.SpaceUsedLong());
+}
+
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
+
+
+TEST(GENERATED_MESSAGE_TEST_NAME, FieldConstantValues) {
+  UNITTEST::TestRequired message;
+  EXPECT_EQ(UNITTEST::TestAllTypes_NestedMessage::kBbFieldNumber, 1);
+  EXPECT_EQ(UNITTEST::TestAllTypes::kOptionalInt32FieldNumber, 1);
+  EXPECT_EQ(UNITTEST::TestAllTypes::kOptionalgroupFieldNumber, 16);
+  EXPECT_EQ(UNITTEST::TestAllTypes::kOptionalNestedMessageFieldNumber, 18);
+  EXPECT_EQ(UNITTEST::TestAllTypes::kOptionalNestedEnumFieldNumber, 21);
+  EXPECT_EQ(UNITTEST::TestAllTypes::kRepeatedInt32FieldNumber, 31);
+  EXPECT_EQ(UNITTEST::TestAllTypes::kRepeatedgroupFieldNumber, 46);
+  EXPECT_EQ(UNITTEST::TestAllTypes::kRepeatedNestedMessageFieldNumber, 48);
+  EXPECT_EQ(UNITTEST::TestAllTypes::kRepeatedNestedEnumFieldNumber, 51);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ExtensionConstantValues) {
+  EXPECT_EQ(UNITTEST::TestRequired::kSingleFieldNumber, 1000);
+  EXPECT_EQ(UNITTEST::TestRequired::kMultiFieldNumber, 1001);
+  EXPECT_EQ(UNITTEST::kOptionalInt32ExtensionFieldNumber, 1);
+  EXPECT_EQ(UNITTEST::kOptionalgroupExtensionFieldNumber, 16);
+  EXPECT_EQ(UNITTEST::kOptionalNestedMessageExtensionFieldNumber, 18);
+  EXPECT_EQ(UNITTEST::kOptionalNestedEnumExtensionFieldNumber, 21);
+  EXPECT_EQ(UNITTEST::kRepeatedInt32ExtensionFieldNumber, 31);
+  EXPECT_EQ(UNITTEST::kRepeatedgroupExtensionFieldNumber, 46);
+  EXPECT_EQ(UNITTEST::kRepeatedNestedMessageExtensionFieldNumber, 48);
+  EXPECT_EQ(UNITTEST::kRepeatedNestedEnumExtensionFieldNumber, 51);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ParseFromTruncated) {
+  const string long_string = string(128, 'q');
+  FileDescriptorProto p;
+  p.add_extension()->set_name(long_string);
+  const string msg = p.SerializeAsString();
+  int successful_count = 0;
+  for (int i = 0; i <= msg.size(); i++) {
+    if (p.ParseFromArray(msg.c_str(), i)) {
+      ++successful_count;
+    }
+  }
+  // We don't really care about how often we succeeded.
+  // As long as we didn't crash, we're happy.
+  EXPECT_GE(successful_count, 1);
+}
+
+// ===================================================================
+
+TEST(GENERATED_ENUM_TEST_NAME, EnumValuesAsSwitchCases) {
+  // Test that our nested enum values can be used as switch cases.  This test
+  // doesn't actually do anything, the proof that it works is that it
+  // compiles.
+  int i =0;
+  UNITTEST::TestAllTypes::NestedEnum a = UNITTEST::TestAllTypes::BAR;
+  switch (a) {
+    case UNITTEST::TestAllTypes::FOO:
+      i = 1;
+      break;
+    case UNITTEST::TestAllTypes::BAR:
+      i = 2;
+      break;
+    case UNITTEST::TestAllTypes::BAZ:
+      i = 3;
+      break;
+    case UNITTEST::TestAllTypes::NEG:
+      i = -1;
+      break;
+    // no default case:  We want to make sure the compiler recognizes that
+    //   all cases are covered.  (GCC warns if you do not cover all cases of
+    //   an enum in a switch.)
+  }
+
+  // Token check just for fun.
+  EXPECT_EQ(2, i);
+}
+
+TEST(GENERATED_ENUM_TEST_NAME, IsValidValue) {
+  // Test enum IsValidValue.
+  EXPECT_TRUE(UNITTEST::TestAllTypes::NestedEnum_IsValid(1));
+  EXPECT_TRUE(UNITTEST::TestAllTypes::NestedEnum_IsValid(2));
+  EXPECT_TRUE(UNITTEST::TestAllTypes::NestedEnum_IsValid(3));
+
+  EXPECT_FALSE(UNITTEST::TestAllTypes::NestedEnum_IsValid(0));
+  EXPECT_FALSE(UNITTEST::TestAllTypes::NestedEnum_IsValid(4));
+
+  // Make sure it also works when there are dups.
+  EXPECT_TRUE(UNITTEST::TestEnumWithDupValue_IsValid(1));
+  EXPECT_TRUE(UNITTEST::TestEnumWithDupValue_IsValid(2));
+  EXPECT_TRUE(UNITTEST::TestEnumWithDupValue_IsValid(3));
+
+  EXPECT_FALSE(UNITTEST::TestEnumWithDupValue_IsValid(0));
+  EXPECT_FALSE(UNITTEST::TestEnumWithDupValue_IsValid(4));
+}
+
+TEST(GENERATED_ENUM_TEST_NAME, MinAndMax) {
+  EXPECT_EQ(UNITTEST::TestAllTypes::NEG,
+            UNITTEST::TestAllTypes::NestedEnum_MIN);
+  EXPECT_EQ(UNITTEST::TestAllTypes::BAZ,
+            UNITTEST::TestAllTypes::NestedEnum_MAX);
+  EXPECT_EQ(4, UNITTEST::TestAllTypes::NestedEnum_ARRAYSIZE);
+
+  EXPECT_EQ(UNITTEST::FOREIGN_FOO, UNITTEST::ForeignEnum_MIN);
+  EXPECT_EQ(UNITTEST::FOREIGN_BAZ, UNITTEST::ForeignEnum_MAX);
+  EXPECT_EQ(7, UNITTEST::ForeignEnum_ARRAYSIZE);
+
+  EXPECT_EQ(1, UNITTEST::TestEnumWithDupValue_MIN);
+  EXPECT_EQ(3, UNITTEST::TestEnumWithDupValue_MAX);
+  EXPECT_EQ(4, UNITTEST::TestEnumWithDupValue_ARRAYSIZE);
+
+  EXPECT_EQ(UNITTEST::SPARSE_E, UNITTEST::TestSparseEnum_MIN);
+  EXPECT_EQ(UNITTEST::SPARSE_C, UNITTEST::TestSparseEnum_MAX);
+  EXPECT_EQ(12589235, UNITTEST::TestSparseEnum_ARRAYSIZE);
+
+  // Make sure we can take the address of _MIN, _MAX and _ARRAYSIZE.
+  void* null_pointer = 0;  // NULL may be integer-type, not pointer-type.
+  EXPECT_NE(null_pointer, &UNITTEST::TestAllTypes::NestedEnum_MIN);
+  EXPECT_NE(null_pointer, &UNITTEST::TestAllTypes::NestedEnum_MAX);
+  EXPECT_NE(null_pointer, &UNITTEST::TestAllTypes::NestedEnum_ARRAYSIZE);
+
+  EXPECT_NE(null_pointer, &UNITTEST::ForeignEnum_MIN);
+  EXPECT_NE(null_pointer, &UNITTEST::ForeignEnum_MAX);
+  EXPECT_NE(null_pointer, &UNITTEST::ForeignEnum_ARRAYSIZE);
+
+  // Make sure we can use _MIN and _MAX as switch cases.
+  switch (UNITTEST::SPARSE_A) {
+    case UNITTEST::TestSparseEnum_MIN:
+    case UNITTEST::TestSparseEnum_MAX:
+      break;
+    default:
+      break;
+  }
+}
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
+TEST(GENERATED_ENUM_TEST_NAME, Name) {
+  // "Names" in the presence of dup values are a bit arbitrary.
+  EXPECT_EQ("FOO1", UNITTEST::TestEnumWithDupValue_Name(UNITTEST::FOO1));
+  EXPECT_EQ("FOO1", UNITTEST::TestEnumWithDupValue_Name(UNITTEST::FOO2));
+
+  EXPECT_EQ("SPARSE_A", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_A));
+  EXPECT_EQ("SPARSE_B", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_B));
+  EXPECT_EQ("SPARSE_C", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_C));
+  EXPECT_EQ("SPARSE_D", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_D));
+  EXPECT_EQ("SPARSE_E", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_E));
+  EXPECT_EQ("SPARSE_F", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_F));
+  EXPECT_EQ("SPARSE_G", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_G));
+}
+
+TEST(GENERATED_ENUM_TEST_NAME, Parse) {
+  UNITTEST::TestEnumWithDupValue dup_value = UNITTEST::FOO1;
+  EXPECT_TRUE(UNITTEST::TestEnumWithDupValue_Parse("FOO1", &dup_value));
+  EXPECT_EQ(UNITTEST::FOO1, dup_value);
+  EXPECT_TRUE(UNITTEST::TestEnumWithDupValue_Parse("FOO2", &dup_value));
+  EXPECT_EQ(UNITTEST::FOO2, dup_value);
+  EXPECT_FALSE(UNITTEST::TestEnumWithDupValue_Parse("FOO", &dup_value));
+}
+
+TEST(GENERATED_ENUM_TEST_NAME, GetEnumDescriptor) {
+  EXPECT_EQ(UNITTEST::TestAllTypes::NestedEnum_descriptor(),
+            GetEnumDescriptor<UNITTEST::TestAllTypes::NestedEnum>());
+  EXPECT_EQ(UNITTEST::ForeignEnum_descriptor(),
+            GetEnumDescriptor<UNITTEST::ForeignEnum>());
+  EXPECT_EQ(UNITTEST::TestEnumWithDupValue_descriptor(),
+            GetEnumDescriptor<UNITTEST::TestEnumWithDupValue>());
+  EXPECT_EQ(UNITTEST::TestSparseEnum_descriptor(),
+            GetEnumDescriptor<UNITTEST::TestSparseEnum>());
+}
+
+enum NonProtoEnum {
+  kFoo = 1,
+};
+
+TEST(GENERATED_ENUM_TEST_NAME, IsProtoEnumTypeTrait) {
+  EXPECT_TRUE(is_proto_enum<UNITTEST::TestAllTypes::NestedEnum>::value);
+  EXPECT_TRUE(is_proto_enum<UNITTEST::ForeignEnum>::value);
+  EXPECT_TRUE(is_proto_enum<UNITTEST::TestEnumWithDupValue>::value);
+  EXPECT_TRUE(is_proto_enum<UNITTEST::TestSparseEnum>::value);
+
+  EXPECT_FALSE(is_proto_enum<int>::value);
+  EXPECT_FALSE(is_proto_enum<NonProtoEnum>::value);
+}
+
+#endif  // PROTOBUF_TEST_NO_DESCRIPTORS
+
+// ===================================================================
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
+// Support code for testing services.
+class GENERATED_SERVICE_TEST_NAME : public testing::Test {
+ protected:
+  class MockTestService : public UNITTEST::TestService {
+   public:
+    MockTestService()
+      : called_(false),
+        method_(""),
+        controller_(NULL),
+        request_(NULL),
+        response_(NULL),
+        done_(NULL) {}
+
+    ~MockTestService() {}
+
+    void Reset() { called_ = false; }
+
+    // implements TestService ----------------------------------------
+
+    void Foo(RpcController* controller,
+             const UNITTEST::FooRequest* request,
+             UNITTEST::FooResponse* response,
+             Closure* done) {
+      ASSERT_FALSE(called_);
+      called_ = true;
+      method_ = "Foo";
+      controller_ = controller;
+      request_ = request;
+      response_ = response;
+      done_ = done;
+    }
+
+    void Bar(RpcController* controller,
+             const UNITTEST::BarRequest* request,
+             UNITTEST::BarResponse* response,
+             Closure* done) {
+      ASSERT_FALSE(called_);
+      called_ = true;
+      method_ = "Bar";
+      controller_ = controller;
+      request_ = request;
+      response_ = response;
+      done_ = done;
+    }
+
+    // ---------------------------------------------------------------
+
+    bool called_;
+    string method_;
+    RpcController* controller_;
+    const Message* request_;
+    Message* response_;
+    Closure* done_;
+  };
+
+  class MockRpcChannel : public RpcChannel {
+   public:
+    MockRpcChannel()
+      : called_(false),
+        method_(NULL),
+        controller_(NULL),
+        request_(NULL),
+        response_(NULL),
+        done_(NULL),
+        destroyed_(NULL) {}
+
+    ~MockRpcChannel() {
+      if (destroyed_ != NULL) *destroyed_ = true;
+    }
+
+    void Reset() { called_ = false; }
+
+    // implements TestService ----------------------------------------
+
+    void CallMethod(const MethodDescriptor* method,
+                    RpcController* controller,
+                    const Message* request,
+                    Message* response,
+                    Closure* done) {
+      ASSERT_FALSE(called_);
+      called_ = true;
+      method_ = method;
+      controller_ = controller;
+      request_ = request;
+      response_ = response;
+      done_ = done;
+    }
+
+    // ---------------------------------------------------------------
+
+    bool called_;
+    const MethodDescriptor* method_;
+    RpcController* controller_;
+    const Message* request_;
+    Message* response_;
+    Closure* done_;
+    bool* destroyed_;
+  };
+
+  class MockController : public RpcController {
+   public:
+    void Reset() {
+      ADD_FAILURE() << "Reset() not expected during this test.";
+    }
+    bool Failed() const {
+      ADD_FAILURE() << "Failed() not expected during this test.";
+      return false;
+    }
+    string ErrorText() const {
+      ADD_FAILURE() << "ErrorText() not expected during this test.";
+      return "";
+    }
+    void StartCancel() {
+      ADD_FAILURE() << "StartCancel() not expected during this test.";
+    }
+    void SetFailed(const string& reason) {
+      ADD_FAILURE() << "SetFailed() not expected during this test.";
+    }
+    bool IsCanceled() const {
+      ADD_FAILURE() << "IsCanceled() not expected during this test.";
+      return false;
+    }
+    void NotifyOnCancel(Closure* callback) {
+      ADD_FAILURE() << "NotifyOnCancel() not expected during this test.";
+    }
+  };
+
+  GENERATED_SERVICE_TEST_NAME()
+    : descriptor_(UNITTEST::TestService::descriptor()),
+      foo_(descriptor_->FindMethodByName("Foo")),
+      bar_(descriptor_->FindMethodByName("Bar")),
+      stub_(&mock_channel_),
+      done_(::google::protobuf::NewPermanentCallback(&DoNothing)) {}
+
+  virtual void SetUp() {
+    ASSERT_TRUE(foo_ != NULL);
+    ASSERT_TRUE(bar_ != NULL);
+  }
+
+  const ServiceDescriptor* descriptor_;
+  const MethodDescriptor* foo_;
+  const MethodDescriptor* bar_;
+
+  MockTestService mock_service_;
+  MockController mock_controller_;
+
+  MockRpcChannel mock_channel_;
+  UNITTEST::TestService::Stub stub_;
+
+  // Just so we don't have to re-define these with every test.
+  UNITTEST::FooRequest foo_request_;
+  UNITTEST::FooResponse foo_response_;
+  UNITTEST::BarRequest bar_request_;
+  UNITTEST::BarResponse bar_response_;
+  std::unique_ptr<Closure> done_;
+};
+
+TEST_F(GENERATED_SERVICE_TEST_NAME, GetDescriptor) {
+  // Test that GetDescriptor() works.
+
+  EXPECT_EQ(descriptor_, mock_service_.GetDescriptor());
+}
+
+TEST_F(GENERATED_SERVICE_TEST_NAME, GetChannel) {
+  EXPECT_EQ(&mock_channel_, stub_.channel());
+}
+
+TEST_F(GENERATED_SERVICE_TEST_NAME, OwnsChannel) {
+  MockRpcChannel* channel = new MockRpcChannel;
+  bool destroyed = false;
+  channel->destroyed_ = &destroyed;
+
+  {
+    UNITTEST::TestService::Stub owning_stub(channel,
+                                            Service::STUB_OWNS_CHANNEL);
+    EXPECT_FALSE(destroyed);
+  }
+
+  EXPECT_TRUE(destroyed);
+}
+
+TEST_F(GENERATED_SERVICE_TEST_NAME, CallMethod) {
+  // Test that CallMethod() works.
+
+  // Call Foo() via CallMethod().
+  mock_service_.CallMethod(foo_, &mock_controller_,
+                           &foo_request_, &foo_response_, done_.get());
+
+  ASSERT_TRUE(mock_service_.called_);
+
+  EXPECT_EQ("Foo"            , mock_service_.method_    );
+  EXPECT_EQ(&mock_controller_, mock_service_.controller_);
+  EXPECT_EQ(&foo_request_    , mock_service_.request_   );
+  EXPECT_EQ(&foo_response_   , mock_service_.response_  );
+  EXPECT_EQ(done_.get()      , mock_service_.done_      );
+
+  // Try again, but call Bar() instead.
+  mock_service_.Reset();
+  mock_service_.CallMethod(bar_, &mock_controller_,
+                           &bar_request_, &bar_response_, done_.get());
+
+  ASSERT_TRUE(mock_service_.called_);
+  EXPECT_EQ("Bar", mock_service_.method_);
+}
+
+TEST_F(GENERATED_SERVICE_TEST_NAME, CallMethodTypeFailure) {
+  // Verify death if we call Foo() with Bar's message types.
+
+#ifdef PROTOBUF_HAS_DEATH_TEST  // death tests do not work on Windows yet
+  EXPECT_DEBUG_DEATH(
+    mock_service_.CallMethod(foo_, &mock_controller_,
+                             &foo_request_, &bar_response_, done_.get()),
+    "dynamic_cast");
+
+  mock_service_.Reset();
+  EXPECT_DEBUG_DEATH(
+    mock_service_.CallMethod(foo_, &mock_controller_,
+                             &bar_request_, &foo_response_, done_.get()),
+    "dynamic_cast");
+#endif  // PROTOBUF_HAS_DEATH_TEST
+}
+
+TEST_F(GENERATED_SERVICE_TEST_NAME, GetPrototypes) {
+  // Test Get{Request,Response}Prototype() methods.
+
+  EXPECT_EQ(&UNITTEST::FooRequest::default_instance(),
+            &mock_service_.GetRequestPrototype(foo_));
+  EXPECT_EQ(&UNITTEST::BarRequest::default_instance(),
+            &mock_service_.GetRequestPrototype(bar_));
+
+  EXPECT_EQ(&UNITTEST::FooResponse::default_instance(),
+            &mock_service_.GetResponsePrototype(foo_));
+  EXPECT_EQ(&UNITTEST::BarResponse::default_instance(),
+            &mock_service_.GetResponsePrototype(bar_));
+}
+
+TEST_F(GENERATED_SERVICE_TEST_NAME, Stub) {
+  // Test that the stub class works.
+
+  // Call Foo() via the stub.
+  stub_.Foo(&mock_controller_, &foo_request_, &foo_response_, done_.get());
+
+  ASSERT_TRUE(mock_channel_.called_);
+
+  EXPECT_EQ(foo_             , mock_channel_.method_    );
+  EXPECT_EQ(&mock_controller_, mock_channel_.controller_);
+  EXPECT_EQ(&foo_request_    , mock_channel_.request_   );
+  EXPECT_EQ(&foo_response_   , mock_channel_.response_  );
+  EXPECT_EQ(done_.get()      , mock_channel_.done_      );
+
+  // Call Bar() via the stub.
+  mock_channel_.Reset();
+  stub_.Bar(&mock_controller_, &bar_request_, &bar_response_, done_.get());
+
+  ASSERT_TRUE(mock_channel_.called_);
+  EXPECT_EQ(bar_, mock_channel_.method_);
+}
+
+TEST_F(GENERATED_SERVICE_TEST_NAME, NotImplemented) {
+  // Test that failing to implement a method of a service causes it to fail
+  // with a "not implemented" error message.
+
+  // A service which doesn't implement any methods.
+  class UnimplementedService : public UNITTEST::TestService {
+   public:
+    UnimplementedService() {}
+  };
+
+  UnimplementedService unimplemented_service;
+
+  // And a controller which expects to get a "not implemented" error.
+  class ExpectUnimplementedController : public MockController {
+   public:
+    ExpectUnimplementedController() : called_(false) {}
+
+    void SetFailed(const string& reason) {
+      EXPECT_FALSE(called_);
+      called_ = true;
+      EXPECT_EQ("Method Foo() not implemented.", reason);
+    }
+
+    bool called_;
+  };
+
+  ExpectUnimplementedController controller;
+
+  // Call Foo.
+  unimplemented_service.Foo(&controller, &foo_request_, &foo_response_,
+                            done_.get());
+
+  EXPECT_TRUE(controller.called_);
+}
+
+// ===================================================================
+
+class OneofTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+  }
+
+  void ExpectEnumCasesWork(const UNITTEST::TestOneof2 &message) {
+    switch (message.foo_case()) {
+      case UNITTEST::TestOneof2::kFooInt:
+        EXPECT_TRUE(message.has_foo_int());
+        break;
+      case UNITTEST::TestOneof2::kFooString:
+        EXPECT_TRUE(message.has_foo_string());
+        break;
+      case UNITTEST::TestOneof2::kFooCord:
+        EXPECT_TRUE(message.has_foo_cord());
+        break;
+      case UNITTEST::TestOneof2::kFooStringPiece:
+        EXPECT_TRUE(message.has_foo_string_piece());
+        break;
+      case UNITTEST::TestOneof2::kFooBytes:
+        EXPECT_TRUE(message.has_foo_bytes());
+        break;
+      case UNITTEST::TestOneof2::kFooEnum:
+        EXPECT_TRUE(message.has_foo_enum());
+        break;
+      case UNITTEST::TestOneof2::kFooMessage:
+        EXPECT_TRUE(message.has_foo_message());
+        break;
+      case UNITTEST::TestOneof2::kFoogroup:
+        EXPECT_TRUE(message.has_foogroup());
+        break;
+      case UNITTEST::TestOneof2::kFooLazyMessage:
+        EXPECT_TRUE(message.has_foo_lazy_message());
+        break;
+      case UNITTEST::TestOneof2::FOO_NOT_SET:
+        break;
+    }
+  }
+};
+
+TEST_F(OneofTest, SettingOneFieldClearsOthers) {
+  UNITTEST::TestOneof2 message;
+
+  message.set_foo_int(123);
+  EXPECT_TRUE(message.has_foo_int());
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+
+  message.set_foo_string("foo");
+  EXPECT_TRUE(message.has_foo_string());
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+
+
+  message.set_foo_bytes("qux");
+  EXPECT_TRUE(message.has_foo_bytes());
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+
+  message.set_foo_enum(UNITTEST::TestOneof2::FOO);
+  EXPECT_TRUE(message.has_foo_enum());
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+
+  message.mutable_foo_message()->set_qux_int(234);
+  EXPECT_TRUE(message.has_foo_message());
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+
+  message.mutable_foogroup()->set_a(345);
+  EXPECT_TRUE(message.has_foogroup());
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+
+
+  // we repeat this because we didn't test if this properly clears other fields
+  // at the beginning.
+  message.set_foo_int(123);
+  EXPECT_TRUE(message.has_foo_int());
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message);
+}
+
+TEST_F(OneofTest, EnumCases) {
+  UNITTEST::TestOneof2 message;
+
+  message.set_foo_int(123);
+  ExpectEnumCasesWork(message);
+  message.set_foo_string("foo");
+  ExpectEnumCasesWork(message);
+  message.set_foo_bytes("qux");
+  ExpectEnumCasesWork(message);
+  message.set_foo_enum(UNITTEST::TestOneof2::FOO);
+  ExpectEnumCasesWork(message);
+  message.mutable_foo_message()->set_qux_int(234);
+  ExpectEnumCasesWork(message);
+  message.mutable_foogroup()->set_a(345);
+  ExpectEnumCasesWork(message);
+}
+
+TEST_F(OneofTest, PrimitiveType) {
+  UNITTEST::TestOneof2 message;
+  // Unset field returns default value
+  EXPECT_EQ(message.foo_int(), 0);
+
+  message.set_foo_int(123);
+  EXPECT_TRUE(message.has_foo_int());
+  EXPECT_EQ(message.foo_int(), 123);
+  message.clear_foo_int();
+  EXPECT_FALSE(message.has_foo_int());
+}
+
+TEST_F(OneofTest, EnumType) {
+  UNITTEST::TestOneof2 message;
+  // Unset field returns default value
+  EXPECT_EQ(message.foo_enum(), 1);
+
+  message.set_foo_enum(UNITTEST::TestOneof2::FOO);
+  EXPECT_TRUE(message.has_foo_enum());
+  EXPECT_EQ(message.foo_enum(), UNITTEST::TestOneof2::FOO);
+  message.clear_foo_enum();
+  EXPECT_FALSE(message.has_foo_enum());
+}
+
+TEST_F(OneofTest, SetString) {
+  // Check that setting a string field in various ways works
+  UNITTEST::TestOneof2 message;
+
+  // Unset field returns default value
+  EXPECT_EQ(message.foo_string(), "");
+
+  message.set_foo_string("foo");
+  EXPECT_TRUE(message.has_foo_string());
+  EXPECT_EQ(message.foo_string(), "foo");
+  message.clear_foo_string();
+  EXPECT_FALSE(message.has_foo_string());
+
+  message.set_foo_string(string("bar"));
+  EXPECT_TRUE(message.has_foo_string());
+  EXPECT_EQ(message.foo_string(), "bar");
+  message.clear_foo_string();
+  EXPECT_FALSE(message.has_foo_string());
+
+
+  message.set_foo_string("qux", 3);
+  EXPECT_TRUE(message.has_foo_string());
+  EXPECT_EQ(message.foo_string(), "qux");
+  message.clear_foo_string();
+  EXPECT_FALSE(message.has_foo_string());
+
+  message.mutable_foo_string()->assign("quux");
+  EXPECT_TRUE(message.has_foo_string());
+  EXPECT_EQ(message.foo_string(), "quux");
+  message.clear_foo_string();
+  EXPECT_FALSE(message.has_foo_string());
+
+  message.set_foo_string("corge");
+  EXPECT_TRUE(message.has_foo_string());
+  EXPECT_EQ(message.foo_string(), "corge");
+  message.clear_foo_string();
+  EXPECT_FALSE(message.has_foo_string());
+}
+
+TEST_F(OneofTest, ReleaseString) {
+  // Check that release_foo() starts out NULL, and gives us a value
+  // that we can delete after it's been set.
+  UNITTEST::TestOneof2 message;
+
+  EXPECT_EQ(NULL, message.release_foo_string());
+  EXPECT_FALSE(message.has_foo_string());
+
+  message.set_foo_string("blah");
+  EXPECT_TRUE(message.has_foo_string());
+  std::unique_ptr<string> str(message.release_foo_string());
+  EXPECT_FALSE(message.has_foo_string());
+  ASSERT_TRUE(str != NULL);
+  EXPECT_EQ("blah", *str);
+
+  EXPECT_EQ(NULL, message.release_foo_string());
+  EXPECT_FALSE(message.has_foo_string());
+}
+
+TEST_F(OneofTest, SetAllocatedString) {
+  // Check that set_allocated_foo() works for strings.
+  UNITTEST::TestOneof2 message;
+
+  EXPECT_FALSE(message.has_foo_string());
+  const string kHello("hello");
+  message.set_foo_string(kHello);
+  EXPECT_TRUE(message.has_foo_string());
+
+  message.set_allocated_foo_string(NULL);
+  EXPECT_FALSE(message.has_foo_string());
+  EXPECT_EQ("", message.foo_string());
+
+  message.set_allocated_foo_string(new string(kHello));
+  EXPECT_TRUE(message.has_foo_string());
+  EXPECT_EQ(kHello, message.foo_string());
+}
+
+
+TEST_F(OneofTest, SetMessage) {
+  // Check that setting a message field works
+  UNITTEST::TestOneof2 message;
+
+  // Unset field returns default instance
+  EXPECT_EQ(&message.foo_message(),
+            &UNITTEST::TestOneof2_NestedMessage::default_instance());
+  EXPECT_EQ(message.foo_message().qux_int(), 0);
+
+  message.mutable_foo_message()->set_qux_int(234);
+  EXPECT_TRUE(message.has_foo_message());
+  EXPECT_EQ(message.foo_message().qux_int(), 234);
+  message.clear_foo_message();
+  EXPECT_FALSE(message.has_foo_message());
+}
+
+TEST_F(OneofTest, ReleaseMessage) {
+  // Check that release_foo() starts out NULL, and gives us a value
+  // that we can delete after it's been set.
+  UNITTEST::TestOneof2 message;
+
+  EXPECT_EQ(NULL, message.release_foo_message());
+  EXPECT_FALSE(message.has_foo_message());
+
+  message.mutable_foo_message()->set_qux_int(1);
+  EXPECT_TRUE(message.has_foo_message());
+  std::unique_ptr<UNITTEST::TestOneof2_NestedMessage> mes(
+      message.release_foo_message());
+  EXPECT_FALSE(message.has_foo_message());
+  ASSERT_TRUE(mes != NULL);
+  EXPECT_EQ(1, mes->qux_int());
+
+  EXPECT_EQ(NULL, message.release_foo_message());
+  EXPECT_FALSE(message.has_foo_message());
+}
+
+TEST_F(OneofTest, SetAllocatedMessage) {
+  // Check that set_allocated_foo() works for messages.
+  UNITTEST::TestOneof2 message;
+
+  EXPECT_FALSE(message.has_foo_message());
+
+  message.mutable_foo_message()->set_qux_int(1);
+  EXPECT_TRUE(message.has_foo_message());
+
+  message.set_allocated_foo_message(NULL);
+  EXPECT_FALSE(message.has_foo_message());
+  EXPECT_EQ(&message.foo_message(),
+            &UNITTEST::TestOneof2_NestedMessage::default_instance());
+
+  message.mutable_foo_message()->set_qux_int(1);
+  UNITTEST::TestOneof2_NestedMessage* mes = message.release_foo_message();
+  ASSERT_TRUE(mes != NULL);
+  EXPECT_FALSE(message.has_foo_message());
+
+  message.set_allocated_foo_message(mes);
+  EXPECT_TRUE(message.has_foo_message());
+  EXPECT_EQ(1, message.foo_message().qux_int());
+}
+
+
+TEST_F(OneofTest, Clear) {
+  UNITTEST::TestOneof2 message;
+
+  message.set_foo_int(1);
+  EXPECT_TRUE(message.has_foo_int());
+  message.clear_foo_int();
+  EXPECT_FALSE(message.has_foo_int());
+}
+
+TEST_F(OneofTest, Defaults) {
+  UNITTEST::TestOneof2 message;
+
+  EXPECT_FALSE(message.has_foo_int());
+  EXPECT_EQ(message.foo_int(), 0);
+
+  EXPECT_FALSE(message.has_foo_string());
+  EXPECT_EQ(message.foo_string(), "");
+
+
+  EXPECT_FALSE(message.has_foo_bytes());
+  EXPECT_EQ(message.foo_bytes(), "");
+
+  EXPECT_FALSE(message.has_foo_enum());
+  EXPECT_EQ(message.foo_enum(), 1);
+
+  EXPECT_FALSE(message.has_foo_message());
+  EXPECT_EQ(message.foo_message().qux_int(), 0);
+
+  EXPECT_FALSE(message.has_foogroup());
+  EXPECT_EQ(message.foogroup().a(), 0);
+
+
+  EXPECT_FALSE(message.has_bar_int());
+  EXPECT_EQ(message.bar_int(), 5);
+
+  EXPECT_FALSE(message.has_bar_string());
+  EXPECT_EQ(message.bar_string(), "STRING");
+
+
+  EXPECT_FALSE(message.has_bar_bytes());
+  EXPECT_EQ(message.bar_bytes(), "BYTES");
+
+  EXPECT_FALSE(message.has_bar_enum());
+  EXPECT_EQ(message.bar_enum(), 2);
+}
+
+TEST_F(OneofTest, SwapWithEmpty) {
+  UNITTEST::TestOneof2 message1, message2;
+  message1.set_foo_string("FOO");
+  EXPECT_TRUE(message1.has_foo_string());
+  message1.Swap(&message2);
+  EXPECT_FALSE(message1.has_foo_string());
+  EXPECT_TRUE(message2.has_foo_string());
+  EXPECT_EQ(message2.foo_string(), "FOO");
+}
+
+TEST_F(OneofTest, SwapWithSelf) {
+  UNITTEST::TestOneof2 message;
+  message.set_foo_string("FOO");
+  EXPECT_TRUE(message.has_foo_string());
+  message.Swap(&message);
+  EXPECT_TRUE(message.has_foo_string());
+  EXPECT_EQ(message.foo_string(), "FOO");
+}
+
+TEST_F(OneofTest, SwapBothHasFields) {
+  UNITTEST::TestOneof2 message1, message2;
+
+  message1.set_foo_string("FOO");
+  EXPECT_TRUE(message1.has_foo_string());
+  message2.mutable_foo_message()->set_qux_int(1);
+  EXPECT_TRUE(message2.has_foo_message());
+
+  message1.Swap(&message2);
+  EXPECT_FALSE(message1.has_foo_string());
+  EXPECT_FALSE(message2.has_foo_message());
+  EXPECT_TRUE(message1.has_foo_message());
+  EXPECT_EQ(message1.foo_message().qux_int(), 1);
+  EXPECT_TRUE(message2.has_foo_string());
+  EXPECT_EQ(message2.foo_string(), "FOO");
+}
+
+TEST_F(OneofTest, CopyConstructor) {
+  UNITTEST::TestOneof2 message1;
+  message1.set_foo_bytes("FOO");
+
+  UNITTEST::TestOneof2 message2(message1);
+  EXPECT_TRUE(message2.has_foo_bytes());
+  EXPECT_EQ(message2.foo_bytes(), "FOO");
+}
+
+TEST_F(OneofTest, CopyFrom) {
+  UNITTEST::TestOneof2 message1, message2;
+  message1.set_foo_enum(UNITTEST::TestOneof2::BAR);
+  EXPECT_TRUE(message1.has_foo_enum());
+
+  message2.CopyFrom(message1);
+  EXPECT_TRUE(message2.has_foo_enum());
+  EXPECT_EQ(message2.foo_enum(), UNITTEST::TestOneof2::BAR);
+
+  // Copying from self should be a no-op.
+  message2.CopyFrom(message2);
+  EXPECT_TRUE(message2.has_foo_enum());
+  EXPECT_EQ(message2.foo_enum(), UNITTEST::TestOneof2::BAR);
+}
+
+TEST_F(OneofTest, CopyAssignmentOperator) {
+  UNITTEST::TestOneof2 message1;
+  message1.mutable_foo_message()->set_qux_int(123);
+  EXPECT_TRUE(message1.has_foo_message());
+
+  UNITTEST::TestOneof2 message2;
+  message2 = message1;
+  EXPECT_EQ(message2.foo_message().qux_int(), 123);
+
+  // Make sure that self-assignment does something sane.
+  message2 = message2;
+  EXPECT_EQ(message2.foo_message().qux_int(), 123);
+}
+
+TEST_F(OneofTest, UpcastCopyFrom) {
+  // Test the CopyFrom method that takes in the generic const Message&
+  // parameter.
+  UNITTEST::TestOneof2 message1, message2;
+  message1.mutable_foogroup()->set_a(123);
+  EXPECT_TRUE(message1.has_foogroup());
+
+  const Message* source = implicit_cast<const Message*>(&message1);
+  message2.CopyFrom(*source);
+
+  EXPECT_TRUE(message2.has_foogroup());
+  EXPECT_EQ(message2.foogroup().a(), 123);
+}
+
+// Test the generated SerializeWithCachedSizesToArray(),
+// This indirectly tests MergePartialFromCodedStream()
+// We have to test each field type separately because we cannot set them at the
+// same time
+TEST_F(OneofTest, SerializationToArray) {
+  // Primitive type
+  {
+    UNITTEST::TestOneof2 message1, message2;
+    string data;
+    message1.set_foo_int(123);
+    int size = message1.ByteSizeLong();
+    data.resize(size);
+    uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
+    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    EXPECT_EQ(size, end - start);
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_int(), 123);
+  }
+
+  // String
+  {
+    UNITTEST::TestOneof2 message1, message2;
+    string data;
+    message1.set_foo_string("foo");
+    int size = message1.ByteSizeLong();
+    data.resize(size);
+    uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
+    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    EXPECT_EQ(size, end - start);
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_string(), "foo");
+  }
+
+
+  // Bytes
+  {
+    UNITTEST::TestOneof2 message1, message2;
+    string data;
+    message1.set_foo_bytes("qux");
+    int size = message1.ByteSizeLong();
+    data.resize(size);
+    uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
+    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    EXPECT_EQ(size, end - start);
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_bytes(), "qux");
+  }
+
+  // Enum
+  {
+    UNITTEST::TestOneof2 message1, message2;
+    string data;
+    message1.set_foo_enum(UNITTEST::TestOneof2::FOO);
+    int size = message1.ByteSizeLong();
+    data.resize(size);
+    uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
+    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    EXPECT_EQ(size, end - start);
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_enum(), UNITTEST::TestOneof2::FOO);
+  }
+
+  // Message
+  {
+    UNITTEST::TestOneof2 message1, message2;
+    string data;
+    message1.mutable_foo_message()->set_qux_int(234);
+    int size = message1.ByteSizeLong();
+    data.resize(size);
+    uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
+    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    EXPECT_EQ(size, end - start);
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_message().qux_int(), 234);
+  }
+
+  // Group
+  {
+    UNITTEST::TestOneof2 message1, message2;
+    string data;
+    message1.mutable_foogroup()->set_a(345);
+    int size = message1.ByteSizeLong();
+    data.resize(size);
+    uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
+    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    EXPECT_EQ(size, end - start);
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foogroup().a(), 345);
+  }
+
+}
+
+// Test the generated SerializeWithCachedSizes() by forcing the buffer to write
+// one byte at a time.
+// This indirectly tests MergePartialFromCodedStream()
+// We have to test each field type separately because we cannot set them at the
+// same time
+TEST_F(OneofTest, SerializationToStream) {
+  // Primitive type
+  {
+    UNITTEST::TestOneof2 message1, message2;
+    string data;
+    message1.set_foo_int(123);
+    int size = message1.ByteSizeLong();
+    data.resize(size);
+
+    {
+      // Allow the output stream to buffer only one byte at a time.
+      io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+      io::CodedOutputStream output_stream(&array_stream);
+      message1.SerializeWithCachedSizes(&output_stream);
+      EXPECT_FALSE(output_stream.HadError());
+      EXPECT_EQ(size, output_stream.ByteCount());
+    }
+
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_int(), 123);
+  }
+
+  // String
+  {
+    UNITTEST::TestOneof2 message1, message2;
+    string data;
+    message1.set_foo_string("foo");
+    int size = message1.ByteSizeLong();
+    data.resize(size);
+
+    {
+      // Allow the output stream to buffer only one byte at a time.
+      io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+      io::CodedOutputStream output_stream(&array_stream);
+      message1.SerializeWithCachedSizes(&output_stream);
+      EXPECT_FALSE(output_stream.HadError());
+      EXPECT_EQ(size, output_stream.ByteCount());
+    }
+
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_string(), "foo");
+  }
+
+
+  // Bytes
+  {
+    UNITTEST::TestOneof2 message1, message2;
+    string data;
+    message1.set_foo_bytes("qux");
+    int size = message1.ByteSizeLong();
+    data.resize(size);
+
+    {
+      // Allow the output stream to buffer only one byte at a time.
+      io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+      io::CodedOutputStream output_stream(&array_stream);
+      message1.SerializeWithCachedSizes(&output_stream);
+      EXPECT_FALSE(output_stream.HadError());
+      EXPECT_EQ(size, output_stream.ByteCount());
+    }
+
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_bytes(), "qux");
+  }
+
+  // Enum
+  {
+    UNITTEST::TestOneof2 message1, message2;
+    string data;
+    message1.set_foo_enum(UNITTEST::TestOneof2::FOO);
+    int size = message1.ByteSizeLong();
+    data.resize(size);
+
+    {
+      // Allow the output stream to buffer only one byte at a time.
+      io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+      io::CodedOutputStream output_stream(&array_stream);
+      message1.SerializeWithCachedSizes(&output_stream);
+      EXPECT_FALSE(output_stream.HadError());
+      EXPECT_EQ(size, output_stream.ByteCount());
+    }
+
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_enum(), UNITTEST::TestOneof2::FOO);
+  }
+
+  // Message
+  {
+    UNITTEST::TestOneof2 message1, message2;
+    string data;
+    message1.mutable_foo_message()->set_qux_int(234);
+    int size = message1.ByteSizeLong();
+    data.resize(size);
+
+    {
+      // Allow the output stream to buffer only one byte at a time.
+      io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+      io::CodedOutputStream output_stream(&array_stream);
+      message1.SerializeWithCachedSizes(&output_stream);
+      EXPECT_FALSE(output_stream.HadError());
+      EXPECT_EQ(size, output_stream.ByteCount());
+    }
+
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foo_message().qux_int(), 234);
+  }
+
+  // Group
+  {
+    UNITTEST::TestOneof2 message1, message2;
+    string data;
+    message1.mutable_foogroup()->set_a(345);
+    int size = message1.ByteSizeLong();
+    data.resize(size);
+
+    {
+      // Allow the output stream to buffer only one byte at a time.
+      io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+      io::CodedOutputStream output_stream(&array_stream);
+      message1.SerializeWithCachedSizes(&output_stream);
+      EXPECT_FALSE(output_stream.HadError());
+      EXPECT_EQ(size, output_stream.ByteCount());
+    }
+
+    EXPECT_TRUE(message2.ParseFromString(data));
+    EXPECT_EQ(message2.foogroup().a(), 345);
+  }
+
+}
+
+TEST_F(OneofTest, MergeFrom) {
+  UNITTEST::TestOneof2 message1, message2;
+
+  message1.set_foo_int(123);
+  message2.MergeFrom(message1);
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
+  EXPECT_TRUE(message2.has_foo_int());
+  EXPECT_EQ(message2.foo_int(), 123);
+
+  message1.set_foo_string("foo");
+  message2.MergeFrom(message1);
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
+  EXPECT_TRUE(message2.has_foo_string());
+  EXPECT_EQ(message2.foo_string(), "foo");
+
+
+  message1.set_foo_bytes("qux");
+  message2.MergeFrom(message1);
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
+  EXPECT_TRUE(message2.has_foo_bytes());
+  EXPECT_EQ(message2.foo_bytes(), "qux");
+
+  message1.set_foo_enum(UNITTEST::TestOneof2::FOO);
+  message2.MergeFrom(message1);
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
+  EXPECT_TRUE(message2.has_foo_enum());
+  EXPECT_EQ(message2.foo_enum(), UNITTEST::TestOneof2::FOO);
+
+  message1.mutable_foo_message()->set_qux_int(234);
+  message2.MergeFrom(message1);
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
+  EXPECT_TRUE(message2.has_foo_message());
+  EXPECT_EQ(message2.foo_message().qux_int(), 234);
+
+  message1.mutable_foogroup()->set_a(345);
+  message2.MergeFrom(message1);
+  TestUtil::ExpectAtMostOneFieldSetInOneof(message2);
+  EXPECT_TRUE(message2.has_foogroup());
+  EXPECT_EQ(message2.foogroup().a(), 345);
+
+}
+
+TEST(HELPERS_TEST_NAME, TestSCC) {
+  UNITTEST::TestMutualRecursionA a;
+  SCCAnalyzer scc_analyzer((Options()));
+  const SCC* scc = scc_analyzer.GetSCC(a.GetDescriptor());
+  std::vector<string> names;
+  for (int i = 0; i < scc->descriptors.size(); i++) {
+    names.push_back(scc->descriptors[i]->full_name());
+  }
+  string package = a.GetDescriptor()->file()->package();
+  ASSERT_EQ(names.size(), 4);
+  std::sort(names.begin(), names.end());
+  EXPECT_EQ(names[0], package + ".TestMutualRecursionA");
+  EXPECT_EQ(names[1], package + ".TestMutualRecursionA.SubGroup");
+  EXPECT_EQ(names[2], package + ".TestMutualRecursionA.SubMessage");
+  EXPECT_EQ(names[3], package + ".TestMutualRecursionB");
+
+  MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc);
+  EXPECT_EQ(result.is_recursive, true);
+  EXPECT_EQ(result.contains_required, false);
+  EXPECT_EQ(result.contains_cord, true);  // TestAllTypes
+  EXPECT_EQ(result.contains_extension, false);  // TestAllTypes
+}
+
+TEST(HELPERS_TEST_NAME, TestSCCAnalysis) {
+  {
+    UNITTEST::TestRecursiveMessage msg;
+    SCCAnalyzer scc_analyzer((Options()));
+    const SCC* scc = scc_analyzer.GetSCC(msg.GetDescriptor());
+    MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc);
+    EXPECT_EQ(result.is_recursive, true);
+    EXPECT_EQ(result.contains_required, false);
+    EXPECT_EQ(result.contains_cord, false);
+    EXPECT_EQ(result.contains_extension, false);
+  }
+  {
+    UNITTEST::TestAllExtensions msg;
+    SCCAnalyzer scc_analyzer((Options()));
+    const SCC* scc = scc_analyzer.GetSCC(msg.GetDescriptor());
+    MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc);
+    EXPECT_EQ(result.is_recursive, false);
+    EXPECT_EQ(result.contains_required, false);
+    EXPECT_EQ(result.contains_cord, false);
+    EXPECT_EQ(result.contains_extension, true);
+  }
+  {
+    UNITTEST::TestRequired msg;
+    SCCAnalyzer scc_analyzer((Options()));
+    const SCC* scc = scc_analyzer.GetSCC(msg.GetDescriptor());
+    MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc);
+    EXPECT_EQ(result.is_recursive, false);
+    EXPECT_EQ(result.contains_required, true);
+    EXPECT_EQ(result.contains_cord, false);
+    EXPECT_EQ(result.contains_extension, false);
+  }
+}
+
+}  // namespace cpp_unittest
+}  // namespace cpp
+}  // namespace compiler
+
+namespace no_generic_services_test {
+  // Verify that no class called "TestService" was defined in
+  // unittest_no_generic_services.pb.h by defining a different type by the same
+  // name.  If such a service was generated, this will not compile.
+  struct TestService {
+    int i;
+  };
+}
+
+namespace compiler {
+namespace cpp {
+namespace cpp_unittest {
+
+TEST_F(GENERATED_SERVICE_TEST_NAME, NoGenericServices) {
+  // Verify that non-services in unittest_no_generic_services.proto were
+  // generated.
+  no_generic_services_test::TestMessage message;
+  message.set_a(1);
+  message.SetExtension(no_generic_services_test::test_extension, 123);
+  no_generic_services_test::TestEnum e = no_generic_services_test::FOO;
+  EXPECT_EQ(e, 1);
+
+  // Verify that a ServiceDescriptor is generated for the service even if the
+  // class itself is not.
+  const FileDescriptor* file =
+      no_generic_services_test::TestMessage::descriptor()->file();
+
+  ASSERT_EQ(1, file->service_count());
+  EXPECT_EQ("TestService", file->service(0)->name());
+  ASSERT_EQ(1, file->service(0)->method_count());
+  EXPECT_EQ("Foo", file->service(0)->method(0)->name());
+}
+
+#endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
+
+// ===================================================================
+
+// This test must run last.  It verifies that descriptors were or were not
+// initialized depending on whether PROTOBUF_TEST_NO_DESCRIPTORS was defined.
+// When this is defined, we skip all tests which are expected to trigger
+// descriptor initialization.  This verifies that everything else still works
+// if descriptors are not initialized.
+TEST(DESCRIPTOR_INIT_TEST_NAME, Initialized) {
+#ifdef PROTOBUF_TEST_NO_DESCRIPTORS
+  bool should_have_descriptors = false;
+#else
+  bool should_have_descriptors = true;
+#endif
+
+  EXPECT_EQ(should_have_descriptors,
+    DescriptorPool::generated_pool()->InternalIsFileLoaded(
+      UNITTEST_PROTO_PATH));
+}
+
+}  // namespace cpp_unittest
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/cpp/metadata_test.cc b/src/google/protobuf/compiler/cpp/metadata_test.cc
index 422eb73..2ad4edd 100644
--- a/src/google/protobuf/compiler/cpp/metadata_test.cc
+++ b/src/google/protobuf/compiler/cpp/metadata_test.cc
@@ -29,28 +29,132 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_generator.h>
+#include <google/protobuf/compiler/annotation_test_util.h>
 #include <google/protobuf/compiler/command_line_interface.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-#include <google/protobuf/io/printer.h>
 #include <google/protobuf/descriptor.pb.h>
 
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
-#include <google/protobuf/testing/file.h>
 
 namespace google {
+namespace atu = ::google::protobuf::compiler::annotation_test_util;
+
 namespace protobuf {
 namespace compiler {
 namespace cpp {
 namespace {
 
+class CppMetadataTest : public ::testing::Test {
+ public:
+  // Tries to capture a FileDescriptorProto, GeneratedCodeInfo, and output
+  // code from the previously added file with name `filename`. Returns true on
+  // success. If pb_h is non-null, expects a .pb.h and a .pb.h.meta (copied to
+  // pb_h and pb_h_info respecfively); similarly for proto_h and proto_h_info.
+  bool CaptureMetadata(const string& filename, FileDescriptorProto* file,
+                       string* pb_h, GeneratedCodeInfo* pb_h_info,
+                       string* proto_h, GeneratedCodeInfo* proto_h_info,
+                       string* pb_cc) {
+    google::protobuf::compiler::CommandLineInterface cli;
+    CppGenerator cpp_generator;
+    cli.RegisterGenerator("--cpp_out", &cpp_generator, "");
+    string cpp_out =
+        "--cpp_out=annotate_headers=true,"
+        "annotation_pragma_name=pragma_name,"
+        "annotation_guard_name=guard_name:" +
+        TestTempDir();
+
+    const bool result =
+        atu::RunProtoCompiler(filename, cpp_out, &cli, file);
+
+    if (!result) {
+      return result;
+    }
+
+    string output_base = TestTempDir() + "/" + StripProto(filename);
+
+    if (pb_cc != NULL) {
+      GOOGLE_CHECK_OK(
+          File::GetContents(output_base + ".pb.cc", pb_cc, true));
+    }
+
+    if (pb_h != NULL && pb_h_info != NULL) {
+      GOOGLE_CHECK_OK(
+          File::GetContents(output_base + ".pb.h", pb_h, true));
+      if (!atu::DecodeMetadata(output_base + ".pb.h.meta", pb_h_info)) {
+        return false;
+      }
+    }
+
+    if (proto_h != NULL && proto_h_info != NULL) {
+      GOOGLE_CHECK_OK(File::GetContents(output_base + ".proto.h", proto_h,
+                                 true));
+      if (!atu::DecodeMetadata(output_base + ".proto.h.meta", proto_h_info)) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+};
+
+const char kSmallTestFile[] =
+    "syntax = \"proto2\";\n"
+    "package foo;\n"
+    "enum Enum { VALUE = 0; }\n"
+    "message Message { }\n";
+
+TEST_F(CppMetadataTest, CapturesEnumNames) {
+  FileDescriptorProto file;
+  GeneratedCodeInfo info;
+  string pb_h;
+  atu::AddFile("test.proto", kSmallTestFile);
+  EXPECT_TRUE(
+      CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
+  EXPECT_EQ("Enum", file.enum_type(0).name());
+  std::vector<int> enum_path;
+  enum_path.push_back(FileDescriptorProto::kEnumTypeFieldNumber);
+  enum_path.push_back(0);
+  const GeneratedCodeInfo::Annotation* enum_annotation =
+      atu::FindAnnotationOnPath(info, "test.proto", enum_path);
+  EXPECT_TRUE(NULL != enum_annotation);
+  EXPECT_TRUE(atu::AnnotationMatchesSubstring(pb_h, enum_annotation, "Enum"));
+}
+
+TEST_F(CppMetadataTest, AddsPragma) {
+  FileDescriptorProto file;
+  GeneratedCodeInfo info;
+  string pb_h;
+  atu::AddFile("test.proto", kSmallTestFile);
+  EXPECT_TRUE(
+      CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
+  EXPECT_TRUE(pb_h.find("#ifdef guard_name") != string::npos);
+  EXPECT_TRUE(pb_h.find("#pragma pragma_name \"test.pb.h.meta\"") !=
+              string::npos);
+}
+
+TEST_F(CppMetadataTest, CapturesMessageNames) {
+  FileDescriptorProto file;
+  GeneratedCodeInfo info;
+  string pb_h;
+  atu::AddFile("test.proto", kSmallTestFile);
+  EXPECT_TRUE(
+      CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
+  EXPECT_EQ("Message", file.message_type(0).name());
+  std::vector<int> message_path;
+  message_path.push_back(FileDescriptorProto::kMessageTypeFieldNumber);
+  message_path.push_back(0);
+  const GeneratedCodeInfo::Annotation* message_annotation =
+      atu::FindAnnotationOnPath(info, "test.proto", message_path);
+  EXPECT_TRUE(NULL != message_annotation);
+  EXPECT_TRUE(
+      atu::AnnotationMatchesSubstring(pb_h, message_annotation, "Message"));
+}
+
 }  // namespace
 }  // namespace cpp
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc b/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc
new file mode 100644
index 0000000..8c38e52
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc
@@ -0,0 +1,200 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This test insures that
+// csharp/src/Google.Protobuf/Reflection/Descriptor.cs  match exactly
+// what would be generated by the protocol compiler.  The file is not
+// generated automatically at build time.
+//
+// If this test fails, run the script
+// "generate_descriptor_proto.sh" and add the changed files under
+// csharp/src/ to your changelist.
+
+#include <map>
+
+#include <google/protobuf/compiler/csharp/csharp_generator.h>
+#include <google/protobuf/compiler/importer.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/stl_util.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+namespace {
+
+class MockErrorCollector : public MultiFileErrorCollector {
+ public:
+  MockErrorCollector() {}
+  ~MockErrorCollector() {}
+
+  string text_;
+
+  // implements ErrorCollector ---------------------------------------
+  void AddError(const string& filename, int line, int column,
+                const string& message) {
+    strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n",
+                                 filename, line, column, message);
+  }
+};
+
+class MockGeneratorContext : public GeneratorContext {
+ public:
+  MockGeneratorContext() {}
+  ~MockGeneratorContext() {
+    STLDeleteValues(&files_);
+  }
+
+  void ExpectFileMatches(const string& virtual_filename,
+                         const string& physical_filename) {
+    string* expected_contents = FindPtrOrNull(files_, virtual_filename);
+    ASSERT_TRUE(expected_contents != NULL)
+      << "Generator failed to generate file: " << virtual_filename;
+
+    string actual_contents;
+    GOOGLE_CHECK_OK(
+        File::GetContents(TestSourceDir() + "/" + physical_filename,
+                          &actual_contents, true))
+        << "Unable to get " << physical_filename;
+    EXPECT_TRUE(actual_contents == *expected_contents)
+      << physical_filename << " needs to be regenerated.  Please run "
+         "generate_descriptor_proto.sh. Then add this file "
+         "to your CL.";
+  }
+
+  // implements GeneratorContext --------------------------------------
+
+  virtual io::ZeroCopyOutputStream* Open(const string& filename) {
+    string** map_slot = &files_[filename];
+    delete *map_slot;
+    *map_slot = new string;
+
+    return new io::StringOutputStream(*map_slot);
+  }
+
+ private:
+  std::map<string, string*> files_;
+};
+
+class GenerateAndTest {
+ public:
+  GenerateAndTest() {}
+  void Run(const FileDescriptor* proto_file, string file1, string file2) {
+    ASSERT_TRUE(proto_file != NULL) << TestSourceDir();
+    ASSERT_TRUE(generator_.Generate(proto_file, parameter_,
+                                    &context_, &error_));
+    context_.ExpectFileMatches(file1, file2);
+  }
+  void SetParameter(string parameter) {
+    parameter_ = parameter;
+  }
+
+ private:
+  Generator generator_;
+  MockGeneratorContext context_;
+  string error_;
+  string parameter_;
+};
+
+TEST(CsharpBootstrapTest, GeneratedCsharpDescriptorMatches) {
+  // Skip this whole test if the csharp directory doesn't exist (i.e., a C++11
+  // only distribution).
+  string descriptor_file_name =
+      "../csharp/src/Google.Protobuf/Reflection/Descriptor.cs";
+  if (!File::Exists(TestSourceDir() + "/" + descriptor_file_name)) {
+    return;
+  }
+
+  MockErrorCollector error_collector;
+  DiskSourceTree source_tree;
+  Importer importer(&source_tree, &error_collector);
+  GenerateAndTest generate_test;
+
+  generate_test.SetParameter("base_namespace=Google.Protobuf");
+  source_tree.MapPath("", TestSourceDir());
+  generate_test.Run(importer.Import("google/protobuf/descriptor.proto"),
+                    "Reflection/Descriptor.cs",
+                    "../csharp/src/Google.Protobuf/Reflection/Descriptor.cs");
+  generate_test.Run(importer.Import("google/protobuf/any.proto"),
+                    "WellKnownTypes/Any.cs",
+                    "../csharp/src/Google.Protobuf/WellKnownTypes/Any.cs");
+  generate_test.Run(importer.Import("google/protobuf/api.proto"),
+                    "WellKnownTypes/Api.cs",
+                    "../csharp/src/Google.Protobuf/WellKnownTypes/Api.cs");
+  generate_test.Run(importer.Import("google/protobuf/duration.proto"),
+                    "WellKnownTypes/Duration.cs",
+                    "../csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs");
+  generate_test.Run(importer.Import("google/protobuf/empty.proto"),
+                    "WellKnownTypes/Empty.cs",
+                    "../csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs");
+  generate_test.Run(importer.Import("google/protobuf/field_mask.proto"),
+                    "WellKnownTypes/FieldMask.cs",
+                    "../csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs");
+  generate_test.Run(importer.Import("google/protobuf/source_context.proto"),
+                    "WellKnownTypes/SourceContext.cs",
+                    "../csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs");
+  generate_test.Run(importer.Import("google/protobuf/struct.proto"),
+                    "WellKnownTypes/Struct.cs",
+                    "../csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs");
+  generate_test.Run(importer.Import("google/protobuf/timestamp.proto"),
+                    "WellKnownTypes/Timestamp.cs",
+                    "../csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs");
+  generate_test.Run(importer.Import("google/protobuf/type.proto"),
+                    "WellKnownTypes/Type.cs",
+                    "../csharp/src/Google.Protobuf/WellKnownTypes/Type.cs");
+  generate_test.Run(importer.Import("google/protobuf/wrappers.proto"),
+                    "WellKnownTypes/Wrappers.cs",
+                    "../csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs");
+
+  generate_test.SetParameter("");
+  source_tree.MapPath("", TestSourceDir() + "/../conformance");
+  generate_test.Run(importer.Import("conformance.proto"),
+                    "Conformance.cs",
+                    "../csharp/src/Google.Protobuf.Conformance/Conformance.cs");
+
+  EXPECT_EQ("", error_collector.text_);
+}
+
+}  // namespace
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc b/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
index 587e022..a21dc0a 100644
--- a/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
@@ -56,7 +56,7 @@
     // node of a summary element, not part of an attribute.
     comments = StringReplace(comments, "&", "&amp;", true);
     comments = StringReplace(comments, "<", "&lt;", true);
-    vector<string> lines = Split(comments, "\n", false /* skip_empty */);
+    std::vector<string> lines = Split(comments, "\n", false /* skip_empty */);
     // TODO: We really should work out which part to put in the summary and which to put in the remarks...
     // but that needs to be part of a bigger effort to understand the markdown better anyway.
     printer->Print("/// <summary>\n");
@@ -74,7 +74,7 @@
                 printer->Print("///\n");
             }
             last_was_empty = false;
-            printer->Print("/// $line$\n", "line", *it);
+            printer->Print("///$line$\n", "line", *it);
         }
     }
     printer->Print("/// </summary>\n");
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.cc b/src/google/protobuf/compiler/csharp/csharp_enum.cc
index 5668198..32c7199 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc
@@ -41,16 +41,15 @@
 #include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
 #include <google/protobuf/compiler/csharp/csharp_enum.h>
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
-
-using google::protobuf::internal::scoped_ptr;
+#include <google/protobuf/compiler/csharp/csharp_options.h>
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace csharp {
 
-EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) :
-    SourceGeneratorBase(descriptor->file()),
+EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Options* options) :
+    SourceGeneratorBase(descriptor->file(), options),
     descriptor_(descriptor) {
 }
 
@@ -59,16 +58,35 @@
 
 void EnumGenerator::Generate(io::Printer* printer) {
   WriteEnumDocComment(printer, descriptor_);
-  WriteGeneratedCodeAttributes(printer);
   printer->Print("$access_level$ enum $name$ {\n",
                  "access_level", class_access_level(),
                  "name", descriptor_->name());
   printer->Indent();
+  std::set<string> used_names;
+  std::set<int> used_number;
   for (int i = 0; i < descriptor_->value_count(); i++) {
       WriteEnumValueDocComment(printer, descriptor_->value(i));
-      printer->Print("$name$ = $number$,\n",
-                   "name", descriptor_->value(i)->name(),
-                   "number", SimpleItoa(descriptor_->value(i)->number()));
+      string original_name = descriptor_->value(i)->name();
+      string name = GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name());
+      // Make sure we don't get any duplicate names due to prefix removal.
+      while (!used_names.insert(name).second) {
+        // It's possible we'll end up giving this warning multiple times, but that's better than not at all.
+        GOOGLE_LOG(WARNING) << "Duplicate enum value " << name << " (originally " << original_name
+          << ") in " << descriptor_->name() << "; adding underscore to distinguish";
+        name += "_";
+      }
+      int number = descriptor_->value(i)->number();
+      if (!used_number.insert(number).second) {
+          printer->Print("[pbr::OriginalName(\"$original_name$\", PreferredAlias = false)] $name$ = $number$,\n",
+             "original_name", original_name,
+             "name", name,
+             "number", SimpleItoa(number));
+      } else {
+          printer->Print("[pbr::OriginalName(\"$original_name$\")] $name$ = $number$,\n",
+             "original_name", original_name,
+             "name", name,
+             "number", SimpleItoa(number));
+      }
   }
   printer->Outdent();
   printer->Print("}\n");
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.h b/src/google/protobuf/compiler/csharp/csharp_enum.h
index 2cf2fad..8925cdf 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum.h
+++ b/src/google/protobuf/compiler/csharp/csharp_enum.h
@@ -43,7 +43,7 @@
 
 class EnumGenerator : public SourceGeneratorBase {
  public:
-  EnumGenerator(const EnumDescriptor* descriptor);
+  EnumGenerator(const EnumDescriptor* descriptor, const Options* options);
   ~EnumGenerator();
 
   void Generate(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
index d38fb1e..9ceffa8 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
@@ -38,6 +38,7 @@
 #include <google/protobuf/io/zero_copy_stream.h>
 
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
 #include <google/protobuf/compiler/csharp/csharp_enum_field.h>
 
 namespace google {
@@ -46,8 +47,8 @@
 namespace csharp {
 
 EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
-                                       int fieldOrdinal)
-    : PrimitiveFieldGenerator(descriptor, fieldOrdinal) {
+                                       int fieldOrdinal, const Options *options)
+    : PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) {
 }
 
 EnumFieldGenerator::~EnumFieldGenerator() {
@@ -80,14 +81,18 @@
         "pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x)");
 }
 
-EnumOneofFieldGenerator::EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
-						 int fieldOrdinal)
-  : PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal) {
+EnumOneofFieldGenerator::EnumOneofFieldGenerator(
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+  : PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options) {
 }
 
 EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {
 }
 
+void EnumOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+  printer->Print(variables_, "$property_name$ = other.$property_name$;\n");
+}
+
 void EnumOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
   // TODO(jonskeet): What about if we read the default value?
   printer->Print(
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_enum_field.h
index 0836415..631632b 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.h
@@ -43,7 +43,9 @@
 
 class EnumFieldGenerator : public PrimitiveFieldGenerator {
  public:
-  EnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  EnumFieldGenerator(const FieldDescriptor* descriptor,
+                     int fieldOrdinal,
+                     const Options *options);
   ~EnumFieldGenerator();
 
   virtual void GenerateCodecCode(io::Printer* printer);
@@ -57,9 +59,12 @@
 
 class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator {
  public:
-  EnumOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
+                          int fieldOrdinal,
+                          const Options *options);
   ~EnumOneofFieldGenerator();
 
+  virtual void GenerateMergingCode(io::Printer* printer);
   virtual void GenerateParsingCode(io::Printer* printer);
   virtual void GenerateSerializationCode(io::Printer* printer);
   virtual void GenerateSerializedSizeCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
index 5df43d3..7e737e4 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
@@ -46,15 +46,13 @@
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
 #include <google/protobuf/compiler/csharp/csharp_names.h>
 
-using google::protobuf::internal::scoped_ptr;
-
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace csharp {
 
 void FieldGeneratorBase::SetCommonFieldVariables(
-    map<string, string>* variables) {
+    std::map<string, string>* variables) {
   // Note: this will be valid even though the tag emitted for packed and unpacked versions of
   // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which
   // never effects the tag size.
@@ -92,16 +90,17 @@
 }
 
 void FieldGeneratorBase::SetCommonOneofFieldVariables(
-    map<string, string>* variables) {
+    std::map<string, string>* variables) {
   (*variables)["oneof_name"] = oneof_name();
-  (*variables)["has_property_check"] = oneof_name() + "Case_ == " + oneof_property_name() +
+  (*variables)["has_property_check"] =
+    oneof_name() + "Case_ == " + oneof_property_name() +
     "OneofCase." + property_name();
   (*variables)["oneof_property_name"] = oneof_property_name();
 }
 
 FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor,
-                                       int fieldOrdinal)
-    : SourceGeneratorBase(descriptor->file()),
+                                       int fieldOrdinal, const Options* options)
+    : SourceGeneratorBase(descriptor->file(), options),
       descriptor_(descriptor),
       fieldOrdinal_(fieldOrdinal) {
   SetCommonFieldVariables(&variables_);
@@ -121,14 +120,17 @@
 }
 
 void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) {
-  if (descriptor_->options().deprecated())
-  {
-    printer->Print("[global::System.ObsoleteAttribute()]\n");
+  if (descriptor_->options().deprecated()) {
+    printer->Print("[global::System.ObsoleteAttribute]\n");
+  } else if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE &&
+           descriptor_->message_type()->options().deprecated()) {
+    printer->Print("[global::System.ObsoleteAttribute]\n");
   }
 }
 
 void FieldGeneratorBase::AddPublicMemberAttributes(io::Printer* printer) {
   AddDeprecatedFlag(printer);
+  WriteGeneratedCodeAttributes(printer);
 }
 
 std::string FieldGeneratorBase::oneof_property_name() {
@@ -158,10 +160,11 @@
     case FieldDescriptor::TYPE_MESSAGE:
     case FieldDescriptor::TYPE_GROUP:
       if (IsWrapperType(descriptor)) {
-        const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
+        const FieldDescriptor* wrapped_field =
+            descriptor->message_type()->field(0);
         string wrapped_field_type_name = type_name(wrapped_field);
-        // String and ByteString go to the same type; other wrapped types go to the
-        // nullable equivalent.
+        // String and ByteString go to the same type; other wrapped types
+        // go to the nullable equivalent.
         if (wrapped_field->type() == FieldDescriptor::TYPE_STRING ||
             wrapped_field->type() == FieldDescriptor::TYPE_BYTES) {
           return wrapped_field_type_name;
@@ -304,7 +307,9 @@
 std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) {
   switch (descriptor->type()) {
     case FieldDescriptor::TYPE_ENUM:
-      return type_name() + "." + descriptor->default_value_enum()->name();
+      // All proto3 enums have a default value of 0, and there's an implicit conversion from the constant 0 to
+      // any C# enum. This means we don't need to work out what we actually mapped the enum value name to.
+     return "0";
     case FieldDescriptor::TYPE_MESSAGE:
     case FieldDescriptor::TYPE_GROUP:
       if (IsWrapperType(descriptor)) {
@@ -315,9 +320,9 @@
       }
     case FieldDescriptor::TYPE_DOUBLE: {
       double value = descriptor->default_value_double();
-      if (value == numeric_limits<double>::infinity()) {
+      if (value == std::numeric_limits<double>::infinity()) {
         return "double.PositiveInfinity";
-      } else if (value == -numeric_limits<double>::infinity()) {
+      } else if (value == -std::numeric_limits<double>::infinity()) {
         return "double.NegativeInfinity";
       } else if (MathLimits<double>::IsNaN(value)) {
         return "double.NaN";
@@ -326,9 +331,9 @@
     }
     case FieldDescriptor::TYPE_FLOAT: {
       float value = descriptor->default_value_float();
-      if (value == numeric_limits<float>::infinity()) {
+      if (value == std::numeric_limits<float>::infinity()) {
         return "float.PositiveInfinity";
-      } else if (value == -numeric_limits<float>::infinity()) {
+      } else if (value == -std::numeric_limits<float>::infinity()) {
         return "float.NegativeInfinity";
       } else if (MathLimits<float>::IsNaN(value)) {
         return "float.NaN";
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h
index d83543b..df26853 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.h
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h
@@ -44,7 +44,9 @@
 
 class FieldGeneratorBase : public SourceGeneratorBase {
  public:
-  FieldGeneratorBase(const FieldDescriptor* descriptor, int fieldOrdinal);
+  FieldGeneratorBase(const FieldDescriptor* descriptor,
+                     int fieldOrdinal,
+                     const Options* options);
   ~FieldGeneratorBase();
 
   virtual void GenerateCloningCode(io::Printer* printer) = 0;
@@ -64,14 +66,14 @@
  protected:
   const FieldDescriptor* descriptor_;
   const int fieldOrdinal_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
   void AddDeprecatedFlag(io::Printer* printer);
   void AddNullCheck(io::Printer* printer);
   void AddNullCheck(io::Printer* printer, const std::string& name);
 
   void AddPublicMemberAttributes(io::Printer* printer);
-  void SetCommonOneofFieldVariables(map<string, string>* variables);
+  void SetCommonOneofFieldVariables(std::map<string, string>* variables);
 
   std::string oneof_property_name();
   std::string oneof_name();
@@ -87,7 +89,7 @@
   std::string capitalized_type_name();
 
  private:
-  void SetCommonFieldVariables(map<string, string>* variables);
+  void SetCommonFieldVariables(std::map<string, string>* variables);
   std::string GetStringDefaultValueInternal();
   std::string GetBytesDefaultValueInternal();
 
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc
index 825de54..0c93fc2 100644
--- a/src/google/protobuf/compiler/csharp/csharp_generator.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc
@@ -41,18 +41,18 @@
 #include <google/protobuf/compiler/csharp/csharp_generator.h>
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
 #include <google/protobuf/compiler/csharp/csharp_names.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
 #include <google/protobuf/compiler/csharp/csharp_reflection_class.h>
 
-using google::protobuf::internal::scoped_ptr;
-
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace csharp {
 
 void GenerateFile(const google::protobuf::FileDescriptor* file,
-                  io::Printer* printer) {
-  ReflectionClassGenerator reflectionClassGenerator(file);
+                  io::Printer* printer,
+                  const Options* options) {
+  ReflectionClassGenerator reflectionClassGenerator(file, options);
   reflectionClassGenerator.Generate(printer);
 }
 
@@ -62,7 +62,7 @@
     GeneratorContext* generator_context,
     string* error) const {
 
-  vector<pair<string, string> > options;
+  std::vector<std::pair<string, string> > options;
   ParseGeneratorParameter(parameter, &options);
 
   // We only support proto3 - but we make an exception for descriptor.proto.
@@ -71,15 +71,16 @@
     return false;
   }
 
-  std::string file_extension = ".cs";
-  std::string base_namespace = "";
-  bool generate_directories = false;
+  struct Options cli_options;
+
   for (int i = 0; i < options.size(); i++) {
     if (options[i].first == "file_extension") {
-      file_extension = options[i].second;
+      cli_options.file_extension = options[i].second;
     } else if (options[i].first == "base_namespace") {
-      base_namespace = options[i].second;
-      generate_directories = true;
+      cli_options.base_namespace = options[i].second;
+      cli_options.base_namespace_specified = true;
+    } else if (options[i].first == "internal_access") {
+      cli_options.internal_access = true;
     } else {
       *error = "Unknown generator option: " + options[i].first;
       return false;
@@ -87,16 +88,21 @@
   }
 
   string filename_error = "";
-  std::string filename = GetOutputFile(file, file_extension, generate_directories, base_namespace, &filename_error);
+  std::string filename = GetOutputFile(file,
+      cli_options.file_extension,
+      cli_options.base_namespace_specified,
+      cli_options.base_namespace,
+      &filename_error);
+
   if (filename.empty()) {
     *error = filename_error;
     return false;
   }
-  scoped_ptr<io::ZeroCopyOutputStream> output(
+  std::unique_ptr<io::ZeroCopyOutputStream> output(
       generator_context->Open(filename));
   io::Printer printer(output.get(), '$');
 
-  GenerateFile(file, &printer);
+  GenerateFile(file, &printer, &cli_options);
 
   return true;
 }
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.h b/src/google/protobuf/compiler/csharp/csharp_generator.h
index 9b54e91..c8b1952 100644
--- a/src/google/protobuf/compiler/csharp/csharp_generator.h
+++ b/src/google/protobuf/compiler/csharp/csharp_generator.h
@@ -28,6 +28,8 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+// Generates C# code for a given .proto file.
+
 #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
 #define GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
 
@@ -40,8 +42,13 @@
 namespace compiler {
 namespace csharp {
 
+// CodeGenerator implementation which generates a C# source file and
+// header.  If you create your own protocol compiler binary and you want
+// it to support C# output, you can do so by registering an instance of this
+// CodeGenerator with the CommandLineInterface in your main() function.
 class LIBPROTOC_EXPORT Generator
     : public google::protobuf::compiler::CodeGenerator {
+public:
   virtual bool Generate(
       const FileDescriptor* file,
       const string& parameter,
@@ -55,4 +62,3 @@
 }  // namespace google
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
-
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc b/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
index 7ef7df4..5755fee 100644
--- a/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
@@ -30,8 +30,8 @@
 
 #include <memory>
 
-#include <google/protobuf/compiler/ruby/ruby_generator.h>
 #include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/io/printer.h>
 
@@ -45,7 +45,23 @@
 namespace csharp {
 namespace {
 
-// TODO(jtattermusch): add some tests.
+TEST(CSharpEnumValue, PascalCasedPrefixStripping) {
+  EXPECT_EQ("Bar", GetEnumValueName("Foo", "BAR"));
+  EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "BAR_BAZ"));
+  EXPECT_EQ("Bar", GetEnumValueName("Foo", "FOO_BAR"));
+  EXPECT_EQ("Bar", GetEnumValueName("Foo", "FOO__BAR"));
+  EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "FOO_BAR_BAZ"));
+  EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "Foo_BarBaz"));
+  EXPECT_EQ("Bar", GetEnumValueName("FO_O", "FOO_BAR"));
+  EXPECT_EQ("Bar", GetEnumValueName("FOO", "F_O_O_BAR"));
+  EXPECT_EQ("Bar", GetEnumValueName("Foo", "BAR"));
+  EXPECT_EQ("BarBaz", GetEnumValueName("Foo", "BAR_BAZ"));
+  EXPECT_EQ("Foo", GetEnumValueName("Foo", "FOO"));
+  EXPECT_EQ("Foo", GetEnumValueName("Foo", "FOO___"));
+  // Identifiers can't start with digits
+  EXPECT_EQ("_2Bar", GetEnumValueName("Foo", "FOO_2_BAR"));
+  EXPECT_EQ("_2", GetEnumValueName("Foo", "FOO___2"));
+}
 
 }  // namespace
 }  // namespace csharp
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
index c51fe44..5bca1ff 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
@@ -38,6 +38,7 @@
 #include <vector>
 
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_names.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/wire_format.h>
@@ -48,6 +49,7 @@
 #include <google/protobuf/compiler/csharp/csharp_enum_field.h>
 #include <google/protobuf/compiler/csharp/csharp_map_field.h>
 #include <google/protobuf/compiler/csharp/csharp_message_field.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
 #include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
 #include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h>
 #include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h>
@@ -127,7 +129,8 @@
 }
 
 std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor) {
-  // TODO: Detect collisions with existing messages, and append an underscore if necessary.
+  // TODO: Detect collisions with existing messages,
+  // and append an underscore if necessary.
   return GetFileNameBase(descriptor) + "Reflection";
 }
 
@@ -176,6 +179,104 @@
   return UnderscoresToCamelCase(input, true);
 }
 
+// Convert a string which is expected to be SHOUTY_CASE (but may not be *precisely* shouty)
+// into a PascalCase string. Precise rules implemented:
+
+// Previous input character      Current character         Case
+// Any                           Non-alphanumeric          Skipped
+// None - first char of input    Alphanumeric              Upper
+// Non-letter (e.g. _ or 1)      Alphanumeric              Upper
+// Numeric                       Alphanumeric              Upper
+// Lower letter                  Alphanumeric              Same as current
+// Upper letter                  Alphanumeric              Lower
+std::string ShoutyToPascalCase(const std::string& input) {
+  string result;
+  // Simple way of implementing "always start with upper"
+  char previous = '_';
+  for (int i = 0; i < input.size(); i++) {
+    char current = input[i];
+    if (!ascii_isalnum(current)) {
+      previous = current;
+      continue;      
+    }
+    if (!ascii_isalnum(previous)) {
+      result += ascii_toupper(current);
+    } else if (ascii_isdigit(previous)) {
+      result += ascii_toupper(current);
+    } else if (ascii_islower(previous)) {
+      result += current;
+    } else {
+      result += ascii_tolower(current);
+    }
+    previous = current;
+  }
+  return result;
+}
+
+// Attempt to remove a prefix from a value, ignoring casing and skipping underscores.
+// (foo, foo_bar) => bar - underscore after prefix is skipped
+// (FOO, foo_bar) => bar - casing is ignored
+// (foo_bar, foobarbaz) => baz - underscore in prefix is ignored
+// (foobar, foo_barbaz) => baz - underscore in value is ignored
+// (foo, bar) => bar - prefix isn't matched; return original value
+std::string TryRemovePrefix(const std::string& prefix, const std::string& value) {
+  // First normalize to a lower-case no-underscores prefix to match against
+  std::string prefix_to_match = "";
+  for (size_t i = 0; i < prefix.size(); i++) {
+    if (prefix[i] != '_') {
+      prefix_to_match += ascii_tolower(prefix[i]);
+    }
+  }
+  
+  // This keeps track of how much of value we've consumed
+  size_t prefix_index, value_index;
+  for (prefix_index = 0, value_index = 0;
+      prefix_index < prefix_to_match.size() && value_index < value.size();
+      value_index++) {
+    // Skip over underscores in the value
+    if (value[value_index] == '_') {
+      continue;
+    }
+    if (ascii_tolower(value[value_index]) != prefix_to_match[prefix_index++]) {
+      // Failed to match the prefix - bail out early.
+      return value;
+    }
+  }
+
+  // If we didn't finish looking through the prefix, we can't strip it.
+  if (prefix_index < prefix_to_match.size()) {
+    return value;
+  }
+
+  // Step over any underscores after the prefix
+  while (value_index < value.size() && value[value_index] == '_') {
+    value_index++;
+  }
+
+  // If there's nothing left (e.g. it was a prefix with only underscores afterwards), don't strip.
+  if (value_index == value.size()) {
+    return value;
+  }
+
+  return value.substr(value_index);
+}
+
+// Format the enum value name in a pleasant way for C#:
+// - Strip the enum name as a prefix if possible
+// - Convert to PascalCase.
+// For example, an enum called Color with a value of COLOR_BLUE should
+// result in an enum value in C# called just Blue
+std::string GetEnumValueName(const std::string& enum_name, const std::string& enum_value_name) {
+  std::string stripped = TryRemovePrefix(enum_name, enum_value_name);
+  std::string result = ShoutyToPascalCase(stripped);
+  // Just in case we have an enum name of FOO and a value of FOO_2... make sure the returned
+  // string is a valid identifier.
+  if (ascii_isdigit(result[0])) {
+    result = "_" + result;
+  }
+  return result;
+}
+
 std::string ToCSharpName(const std::string& name, const FileDescriptor* file) {
   std::string result = GetFileNamespace(file);
   if (result != "") {
@@ -351,49 +452,50 @@
 }
 
 FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
-                                         int fieldOrdinal) {
+                                         int fieldOrdinal,
+                                         const Options* options) {
   switch (descriptor->type()) {
     case FieldDescriptor::TYPE_GROUP:
     case FieldDescriptor::TYPE_MESSAGE:
       if (descriptor->is_repeated()) {
         if (descriptor->is_map()) {
-          return new MapFieldGenerator(descriptor, fieldOrdinal);
+          return new MapFieldGenerator(descriptor, fieldOrdinal, options);
         } else {
-          return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal);
+          return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal, options);
         }
       } else {
         if (IsWrapperType(descriptor)) {
           if (descriptor->containing_oneof()) {
-            return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal);
+            return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal, options);
           } else {
-            return new WrapperFieldGenerator(descriptor, fieldOrdinal);
+            return new WrapperFieldGenerator(descriptor, fieldOrdinal, options);
           }
         } else {
           if (descriptor->containing_oneof()) {
-            return new MessageOneofFieldGenerator(descriptor, fieldOrdinal);
+            return new MessageOneofFieldGenerator(descriptor, fieldOrdinal, options);
           } else {
-            return new MessageFieldGenerator(descriptor, fieldOrdinal);
+            return new MessageFieldGenerator(descriptor, fieldOrdinal, options);
           }
         }
       }
     case FieldDescriptor::TYPE_ENUM:
       if (descriptor->is_repeated()) {
-        return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal);
+        return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal, options);
       } else {
         if (descriptor->containing_oneof()) {
-          return new EnumOneofFieldGenerator(descriptor, fieldOrdinal);
+          return new EnumOneofFieldGenerator(descriptor, fieldOrdinal, options);
         } else {
-          return new EnumFieldGenerator(descriptor, fieldOrdinal);
+          return new EnumFieldGenerator(descriptor, fieldOrdinal, options);
         }
       }
     default:
       if (descriptor->is_repeated()) {
-        return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal);
+        return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal, options);
       } else {
         if (descriptor->containing_oneof()) {
-          return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal);
+          return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options);
         } else {
-          return new PrimitiveFieldGenerator(descriptor, fieldOrdinal);
+          return new PrimitiveFieldGenerator(descriptor, fieldOrdinal, options);
         }
       }
   }
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h
index e96e793..c317ad0 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.h
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h
@@ -36,6 +36,7 @@
 #define GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
 
 #include <string>
+#include <google/protobuf/stubs/port.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/compiler/code_generator.h>
@@ -46,6 +47,7 @@
 namespace compiler {
 namespace csharp {
 
+struct Options;
 class FieldGeneratorBase;
 
 // TODO: start using this enum.
@@ -82,7 +84,9 @@
 
 int GetFixedSize(FieldDescriptor::Type type);
 
-std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter, bool preserve_period);
+std::string UnderscoresToCamelCase(const std::string& input,
+                                   bool cap_next_letter,
+                                   bool preserve_period);
 
 inline std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter) {
   return UnderscoresToCamelCase(input, cap_next_letter, false);
@@ -90,26 +94,48 @@
 
 std::string UnderscoresToPascalCase(const std::string& input);
 
+// Note that we wouldn't normally want to export this (we're not expecting
+// it to be used outside libprotoc itself) but this exposes it for testing.
+std::string LIBPROTOBUF_EXPORT GetEnumValueName(const std::string& enum_name, const std::string& enum_value_name);
+
 // TODO(jtattermusch): perhaps we could move this to strutil
 std::string StringToBase64(const std::string& input);
 
 std::string FileDescriptorToBase64(const FileDescriptor* descriptor);
 
-FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
+                                         int fieldOrdinal,
+                                         const Options* options);
 
-// Determines whether the given message is a map entry message, i.e. one implicitly created
-// by protoc due to a map<key, value> field.
+// Determines whether the given message is a map entry message,
+// i.e. one implicitly created by protoc due to a map<key, value> field.
 inline bool IsMapEntryMessage(const Descriptor* descriptor) {
   return descriptor->options().map_entry();
 }
 
-// Determines whether we're generating code for the proto representation of descriptors etc,
-// for use in the runtime. This is the only type which is allowed to use proto2 syntax,
-// and it generates internal classes.
+// Determines whether we're generating code for the proto representation of
+// descriptors etc, for use in the runtime. This is the only type which is
+// allowed to use proto2 syntax, and it generates internal classes.
 inline bool IsDescriptorProto(const FileDescriptor* descriptor) {
   return descriptor->name() == "google/protobuf/descriptor.proto";
 }
 
+// Determines whether the given message is an options message within descriptor.proto.
+inline bool IsDescriptorOptionMessage(const Descriptor* descriptor) {
+  if (!IsDescriptorProto(descriptor->file())) {
+    return false;
+  }
+  const string name = descriptor->full_name();
+  return name == "google.protobuf.FileOptions" ||
+      name == "google.protobuf.MessageOptions" ||
+      name == "google.protobuf.FieldOptions" ||
+      name == "google.protobuf.OneofOptions" ||
+      name == "google.protobuf.EnumOptions" ||
+      name == "google.protobuf.EnumValueOptions" ||
+      name == "google.protobuf.ServiceOptions" ||
+      name == "google.protobuf.MethodOptions";
+}
+
 inline bool IsWrapperType(const FieldDescriptor* descriptor) {
   return descriptor->type() == FieldDescriptor::TYPE_MESSAGE &&
       descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto";
diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
index 15c68b3..d58514c 100644
--- a/src/google/protobuf/compiler/csharp/csharp_map_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
@@ -48,8 +48,9 @@
 namespace csharp {
 
 MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
-                                             int fieldOrdinal)
-    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+                                     int fieldOrdinal,
+                                     const Options* options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
 }
 
 MapFieldGenerator::~MapFieldGenerator() {
@@ -62,8 +63,10 @@
       descriptor_->message_type()->FindFieldByName("value");
   variables_["key_type_name"] = type_name(key_descriptor);
   variables_["value_type_name"] = type_name(value_descriptor);
-  scoped_ptr<FieldGeneratorBase> key_generator(CreateFieldGenerator(key_descriptor, 1));  
-  scoped_ptr<FieldGeneratorBase> value_generator(CreateFieldGenerator(value_descriptor, 2));
+  std::unique_ptr<FieldGeneratorBase> key_generator(
+      CreateFieldGenerator(key_descriptor, 1, this->options()));
+  std::unique_ptr<FieldGeneratorBase> value_generator(
+      CreateFieldGenerator(value_descriptor, 2, this->options()));
 
   printer->Print(
     variables_,
@@ -77,7 +80,7 @@
     ", $tag$);\n"
     "private readonly pbc::MapField<$key_type_name$, $value_type_name$> $name$_ = new pbc::MapField<$key_type_name$, $value_type_name$>();\n");
   WritePropertyDocComment(printer, descriptor_);
-  AddDeprecatedFlag(printer);
+  AddPublicMemberAttributes(printer);
   printer->Print(
     variables_,
     "$access_level$ pbc::MapField<$key_type_name$, $value_type_name$> $property_name$ {\n"
diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.h b/src/google/protobuf/compiler/csharp/csharp_map_field.h
index f33fe1c..84a33a0 100644
--- a/src/google/protobuf/compiler/csharp/csharp_map_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.h
@@ -43,7 +43,9 @@
 
 class MapFieldGenerator : public FieldGeneratorBase {
  public:
-  MapFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  MapFieldGenerator(const FieldDescriptor* descriptor,
+                    int fieldOrdinal,
+                    const Options* options);
   ~MapFieldGenerator();
 
   virtual void GenerateCloningCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc
index e0230a2..8a4307f 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message.cc
@@ -49,8 +49,6 @@
 #include <google/protobuf/compiler/csharp/csharp_message.h>
 #include <google/protobuf/compiler/csharp/csharp_names.h>
 
-using google::protobuf::internal::scoped_ptr;
-
 namespace google {
 namespace protobuf {
 namespace compiler {
@@ -60,8 +58,9 @@
   return d1->number() < d2->number();
 }
 
-MessageGenerator::MessageGenerator(const Descriptor* descriptor)
-    : SourceGeneratorBase(descriptor->file()),
+MessageGenerator::MessageGenerator(const Descriptor* descriptor,
+                                   const Options* options)
+    : SourceGeneratorBase(descriptor->file(), options),
       descriptor_(descriptor) {
 
   // sorted field names
@@ -97,15 +96,20 @@
   return fields_by_number_;
 }
 
+void MessageGenerator::AddDeprecatedFlag(io::Printer* printer) {
+  if (descriptor_->options().deprecated()) {
+    printer->Print("[global::System.ObsoleteAttribute]\n");
+  }
+}
+
 void MessageGenerator::Generate(io::Printer* printer) {
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["class_name"] = class_name();
   vars["access_level"] = class_access_level();
 
   WriteMessageDocComment(printer, descriptor_);
-  printer->Print(
-    "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
-  WriteGeneratedCodeAttributes(printer);
+  AddDeprecatedFlag(printer);
+
   printer->Print(
     vars,
     "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$> {\n");
@@ -114,7 +118,15 @@
   // All static fields and properties
   printer->Print(
       vars,
-      "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n"
+      "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n");
+
+  printer->Print(
+      "private pb::UnknownFieldSet _unknownFields;\n");
+
+  WriteGeneratedCodeAttributes(printer);
+
+  printer->Print(
+      vars,
       "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n");
 
   // Access the message descriptor via the relevant file descriptor or containing message descriptor.
@@ -126,18 +138,29 @@
         + ".Descriptor.NestedTypes[" + SimpleItoa(descriptor_->index()) + "]";
   }
 
+  WriteGeneratedCodeAttributes(printer);
   printer->Print(
     vars,
     "public static pbr::MessageDescriptor Descriptor {\n"
     "  get { return $descriptor_accessor$; }\n"
     "}\n"
-    "\n"
+    "\n");
+  WriteGeneratedCodeAttributes(printer);
+  printer->Print(
+    vars,
     "pbr::MessageDescriptor pb::IMessage.Descriptor {\n"
     "  get { return Descriptor; }\n"
     "}\n"
     "\n");
+  // CustomOptions property, only for options messages
+  if (IsDescriptorOptionMessage(descriptor_)) {
+    printer->Print(
+      "internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty;\n"
+       "\n");
+  }
 
   // Parameterless constructor and partial OnConstruction method.
+  WriteGeneratedCodeAttributes(printer);
   printer->Print(
     vars,
     "public $class_name$() {\n"
@@ -159,7 +182,7 @@
       "field_name", fieldDescriptor->name(),
       "field_constant_name", GetFieldConstantName(fieldDescriptor),
       "index", SimpleItoa(fieldDescriptor->number()));
-    scoped_ptr<FieldGeneratorBase> generator(
+    std::unique_ptr<FieldGeneratorBase> generator(
         CreateFieldGeneratorInternal(fieldDescriptor));
     generator->GenerateMembers(printer);
     printer->Print("\n");
@@ -185,13 +208,20 @@
     }
     printer->Outdent();
     printer->Print("}\n");
-    // TODO: Should we put the oneof .proto comments here? It's unclear exactly where they should go.
+    // TODO: Should we put the oneof .proto comments here?
+    // It's unclear exactly where they should go.
     printer->Print(
       vars,
-      "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n"
+      "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n");
+    WriteGeneratedCodeAttributes(printer);
+    printer->Print(
+      vars,
       "public $property_name$OneofCase $property_name$Case {\n"
       "  get { return $name$Case_; }\n"
-      "}\n\n"
+      "}\n\n");
+    WriteGeneratedCodeAttributes(printer);
+    printer->Print(
+      vars,
       "public void Clear$property_name$() {\n"
       "  $name$Case_ = $property_name$OneofCase.None;\n"
       "  $name$_ = null;\n"
@@ -208,19 +238,19 @@
     printer->Print(
       vars,
       "#region Nested types\n"
-      "/// <summary>Container for nested types declared in the $class_name$ message type.</summary>\n"
-      "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
+      "/// <summary>Container for nested types declared in the $class_name$ message type.</summary>\n");
     WriteGeneratedCodeAttributes(printer);
     printer->Print("public static partial class Types {\n");
     printer->Indent();
     for (int i = 0; i < descriptor_->enum_type_count(); i++) {
-      EnumGenerator enumGenerator(descriptor_->enum_type(i));
+      EnumGenerator enumGenerator(descriptor_->enum_type(i), this->options());
       enumGenerator.Generate(printer);
     }
     for (int i = 0; i < descriptor_->nested_type_count(); i++) {
       // Don't generate nested types for maps...
       if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
-        MessageGenerator messageGenerator(descriptor_->nested_type(i));
+        MessageGenerator messageGenerator(
+            descriptor_->nested_type(i), this->options());
         messageGenerator.Generate(printer);
       }
     }
@@ -251,7 +281,8 @@
 }
 
 void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
-  map<string, string> vars;
+  std::map<string, string> vars;
+  WriteGeneratedCodeAttributes(printer);
   vars["class_name"] = class_name();
     printer->Print(
     vars,
@@ -260,7 +291,7 @@
   // Clone non-oneof fields first
   for (int i = 0; i < descriptor_->field_count(); i++) {
     if (!descriptor_->field(i)->containing_oneof()) {
-      scoped_ptr<FieldGeneratorBase> generator(
+      std::unique_ptr<FieldGeneratorBase> generator(
         CreateFieldGeneratorInternal(descriptor_->field(i)));
       generator->GenerateCloningCode(printer);
     }
@@ -268,12 +299,13 @@
   // Clone just the right field for each oneof
   for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
     vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
-    vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
+    vars["property_name"] = UnderscoresToCamelCase(
+        descriptor_->oneof_decl(i)->name(), true);
     printer->Print(vars, "switch (other.$property_name$Case) {\n");
     printer->Indent();
     for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
       const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
-      scoped_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
+      std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
       vars["field_property_name"] = GetPropertyName(field);
       printer->Print(
           vars,
@@ -286,10 +318,14 @@
     printer->Outdent();
     printer->Print("}\n\n");
   }
+  // Clone unknown fields
+  printer->Print(
+      "_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);\n");
 
   printer->Outdent();
   printer->Print("}\n\n");
 
+  WriteGeneratedCodeAttributes(printer);
   printer->Print(
     vars,
     "public $class_name$ Clone() {\n"
@@ -301,15 +337,19 @@
 }
 
 void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
-    map<string, string> vars;
+    std::map<string, string> vars;
     vars["class_name"] = class_name();
 
     // Equality
+    WriteGeneratedCodeAttributes(printer);
     printer->Print(
         vars,
         "public override bool Equals(object other) {\n"
         "  return Equals(other as $class_name$);\n"
-        "}\n\n"
+        "}\n\n");
+    WriteGeneratedCodeAttributes(printer);
+    printer->Print(
+        vars,
         "public bool Equals($class_name$ other) {\n"
         "  if (ReferenceEquals(other, null)) {\n"
         "    return false;\n"
@@ -319,7 +359,7 @@
         "  }\n");
     printer->Indent();
     for (int i = 0; i < descriptor_->field_count(); i++) {
-        scoped_ptr<FieldGeneratorBase> generator(
+      std::unique_ptr<FieldGeneratorBase> generator(
             CreateFieldGeneratorInternal(descriptor_->field(i)));
         generator->WriteEquals(printer);
     }
@@ -329,17 +369,18 @@
     }
     printer->Outdent();
     printer->Print(
-        "  return true;\n"
+        "  return Equals(_unknownFields, other._unknownFields);\n"
         "}\n\n");
 
     // GetHashCode
     // Start with a non-zero value to easily distinguish between null and "empty" messages.
+    WriteGeneratedCodeAttributes(printer);
     printer->Print(
         "public override int GetHashCode() {\n"
         "  int hash = 1;\n");
     printer->Indent();
     for (int i = 0; i < descriptor_->field_count(); i++) {
-        scoped_ptr<FieldGeneratorBase> generator(
+      std::unique_ptr<FieldGeneratorBase> generator(
             CreateFieldGeneratorInternal(descriptor_->field(i)));
         generator->WriteHash(printer);
     }
@@ -347,10 +388,15 @@
         printer->Print("hash ^= (int) $name$Case_;\n",
             "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false));
     }
-    printer->Print("return hash;\n");
+    printer->Print(
+        "if (_unknownFields != null) {\n"
+        "  hash ^= _unknownFields.GetHashCode();\n"
+        "}\n"
+        "return hash;\n");
     printer->Outdent();
     printer->Print("}\n\n");
 
+    WriteGeneratedCodeAttributes(printer);
     printer->Print(
         "public override string ToString() {\n"
         "  return pb::JsonFormatter.ToDiagnosticString(this);\n"
@@ -358,30 +404,45 @@
 }
 
 void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) {
+  WriteGeneratedCodeAttributes(printer);
   printer->Print(
       "public void WriteTo(pb::CodedOutputStream output) {\n");
   printer->Indent();
 
   // Serialize all the fields
   for (int i = 0; i < fields_by_number().size(); i++) {
-    scoped_ptr<FieldGeneratorBase> generator(
+    std::unique_ptr<FieldGeneratorBase> generator(
       CreateFieldGeneratorInternal(fields_by_number()[i]));
     generator->GenerateSerializationCode(printer);
   }
 
+  // Serialize unknown fields
+  printer->Print(
+    "if (_unknownFields != null) {\n"
+    "  _unknownFields.WriteTo(output);\n"
+    "}\n");
+
   // TODO(jonskeet): Memoize size of frozen messages?
   printer->Outdent();
   printer->Print(
     "}\n"
-    "\n"
+    "\n");
+  WriteGeneratedCodeAttributes(printer);
+  printer->Print(
     "public int CalculateSize() {\n");
   printer->Indent();
   printer->Print("int size = 0;\n");
   for (int i = 0; i < descriptor_->field_count(); i++) {
-    scoped_ptr<FieldGeneratorBase> generator(
+    std::unique_ptr<FieldGeneratorBase> generator(
         CreateFieldGeneratorInternal(descriptor_->field(i)));
     generator->GenerateSerializedSizeCode(printer);
   }
+
+  printer->Print(
+    "if (_unknownFields != null) {\n"
+    "  size += _unknownFields.CalculateSize();\n"
+    "}\n");
+
   printer->Print("return size;\n");
   printer->Outdent();
   printer->Print("}\n\n");
@@ -391,9 +452,10 @@
   // Note:  These are separate from GenerateMessageSerializationMethods()
   //   because they need to be generated even for messages that are optimized
   //   for code size.
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["class_name"] = class_name();
 
+  WriteGeneratedCodeAttributes(printer);
   printer->Print(
     vars,
     "public void MergeFrom($class_name$ other) {\n");
@@ -405,7 +467,7 @@
   // Merge non-oneof fields
   for (int i = 0; i < descriptor_->field_count(); i++) {
     if (!descriptor_->field(i)->containing_oneof()) {      
-      scoped_ptr<FieldGeneratorBase> generator(
+      std::unique_ptr<FieldGeneratorBase> generator(
           CreateFieldGeneratorInternal(descriptor_->field(i)));
       generator->GenerateMergingCode(printer);
     }
@@ -421,15 +483,25 @@
       vars["field_property_name"] = GetPropertyName(field);
       printer->Print(
         vars,
-        "case $property_name$OneofCase.$field_property_name$:\n"
-        "  $field_property_name$ = other.$field_property_name$;\n"
-        "  break;\n");
+        "case $property_name$OneofCase.$field_property_name$:\n");
+      printer->Indent();
+      std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
+      generator->GenerateMergingCode(printer);
+      printer->Print("break;\n");
+      printer->Outdent();
     }
     printer->Outdent();
     printer->Print("}\n\n");
   }
+  // Merge unknown fields.
+  printer->Print(
+      "_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);\n");
+
   printer->Outdent();
   printer->Print("}\n\n");
+
+
+  WriteGeneratedCodeAttributes(printer);
   printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n");
   printer->Indent();
   printer->Print(
@@ -438,10 +510,18 @@
     "  switch(tag) {\n");
   printer->Indent();
   printer->Indent();
-  printer->Print(
-    "default:\n"
-    "  input.SkipLastField();\n" // We're not storing the data, but we still need to consume it.
-    "  break;\n");
+  // Option messages need to store unknown fields so that options can be parsed later.
+  if (IsDescriptorOptionMessage(descriptor_)) {
+    printer->Print(
+      "default:\n"
+      "  CustomOptions = CustomOptions.ReadOrSkipUnknownField(input);\n"
+      "  break;\n");
+  } else {
+    printer->Print(
+      "default:\n"
+      "  _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);\n"
+      "  break;\n");
+  }
   for (int i = 0; i < fields_by_number().size(); i++) {
     const FieldDescriptor* field = fields_by_number()[i];
     internal::WireFormatLite::WireType wt =
@@ -449,7 +529,8 @@
     uint32 tag = internal::WireFormatLite::MakeTag(field->number(), wt);
     // Handle both packed and unpacked repeated fields with the same Read*Array call;
     // the two generated cases are the packed and unpacked tags.
-    // TODO(jonskeet): Check that is_packable is equivalent to is_repeated && wt in { VARINT, FIXED32, FIXED64 }.
+    // TODO(jonskeet): Check that is_packable is equivalent to
+    // is_repeated && wt in { VARINT, FIXED32, FIXED64 }.
     // It looks like it is...
     if (field->is_packable()) {
       printer->Print(
@@ -463,7 +544,7 @@
 
     printer->Print("case $tag$: {\n", "tag", SimpleItoa(tag));
     printer->Indent();
-    scoped_ptr<FieldGeneratorBase> generator(
+    std::unique_ptr<FieldGeneratorBase> generator(
         CreateFieldGeneratorInternal(field));
     generator->GenerateParsingCode(printer);
     printer->Print("break;\n");
@@ -490,7 +571,7 @@
 
 FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal(
     const FieldDescriptor* descriptor) {
-  return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor));
+  return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor), this->options());
 }
 
 }  // namespace csharp
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h
index f0c49ac..e7f3b4d 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.h
+++ b/src/google/protobuf/compiler/csharp/csharp_message.h
@@ -47,7 +47,7 @@
 
 class MessageGenerator : public SourceGeneratorBase {
  public:
-  MessageGenerator(const Descriptor* descriptor);
+  MessageGenerator(const Descriptor* descriptor, const Options* options);
   ~MessageGenerator();
 
   void GenerateCloningCode(io::Printer* printer);
@@ -69,6 +69,8 @@
 
   bool HasNestedGeneratedTypes();
 
+  void AddDeprecatedFlag(io::Printer* printer);
+  
   std::string class_name();
   std::string full_class_name();
 
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
index f81f769..cf1b4db 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
@@ -41,6 +41,7 @@
 #include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
 #include <google/protobuf/compiler/csharp/csharp_message_field.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
 
 namespace google {
 namespace protobuf {
@@ -48,8 +49,9 @@
 namespace csharp {
 
 MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
-                                             int fieldOrdinal)
-    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+                                             int fieldOrdinal,
+                                             const Options *options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
   variables_["has_property_check"] = name() + "_ != null";
   variables_["has_not_property_check"] = name() + "_ == null";
 }
@@ -63,7 +65,7 @@
     variables_,
     "private $type_name$ $name$_;\n");
   WritePropertyDocComment(printer, descriptor_);
-  AddDeprecatedFlag(printer);
+  AddPublicMemberAttributes(printer);
   printer->Print(
     variables_,
     "$access_level$ $type_name$ $property_name$ {\n"
@@ -131,7 +133,7 @@
 
 void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
   printer->Print(variables_,
-    "$property_name$ = other.$has_property_check$ ? other.$property_name$.Clone() : null;\n");
+    "$name$_ = other.$has_property_check$ ? other.$name$_.Clone() : null;\n");
 }
 
 void MessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
@@ -143,9 +145,11 @@
     "pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)");
 }
 
-MessageOneofFieldGenerator::MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
-						       int fieldOrdinal)
-    : MessageFieldGenerator(descriptor, fieldOrdinal) {
+MessageOneofFieldGenerator::MessageOneofFieldGenerator(
+    const FieldDescriptor* descriptor,
+	  int fieldOrdinal,
+    const Options *options)
+    : MessageFieldGenerator(descriptor, fieldOrdinal, options) {
   SetCommonOneofFieldVariables(&variables_);
 }
 
@@ -155,7 +159,7 @@
 
 void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
   WritePropertyDocComment(printer, descriptor_);
-  AddDeprecatedFlag(printer);
+  AddPublicMemberAttributes(printer);
   printer->Print(
     variables_,
     "$access_level$ $type_name$ $property_name$ {\n"
@@ -167,6 +171,14 @@
     "}\n");
 }
 
+void MessageOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+  printer->Print(variables_, 
+    "if ($property_name$ == null) {\n"
+    "  $property_name$ = new $type_name$();\n"
+    "}\n"
+    "$property_name$.MergeFrom(other.$property_name$);\n");
+}
+
 void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
   // TODO(jonskeet): We may be able to do better than this
   printer->Print(
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h
index dc6e4dc..c41ee88 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.h
@@ -43,7 +43,9 @@
 
 class MessageFieldGenerator : public FieldGeneratorBase {
  public:
-  MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  MessageFieldGenerator(const FieldDescriptor* descriptor,
+                        int fieldOrdinal,
+                        const Options *options);
   ~MessageFieldGenerator();
 
   virtual void GenerateCodecCode(io::Printer* printer);
@@ -65,11 +67,14 @@
 
 class MessageOneofFieldGenerator : public MessageFieldGenerator {
  public:
-  MessageOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
+                             int fieldOrdinal,
+                             const Options *options);
   ~MessageOneofFieldGenerator();
 
   virtual void GenerateCloningCode(io::Printer* printer);
   virtual void GenerateMembers(io::Printer* printer);
+  virtual void GenerateMergingCode(io::Printer* printer);
   virtual void WriteToString(io::Printer* printer);
   virtual void GenerateParsingCode(io::Printer* printer);
 
diff --git a/src/google/protobuf/compiler/csharp/csharp_names.h b/src/google/protobuf/compiler/csharp/csharp_names.h
index 3080518..21758f2 100644
--- a/src/google/protobuf/compiler/csharp/csharp_names.h
+++ b/src/google/protobuf/compiler/csharp/csharp_names.h
@@ -39,6 +39,7 @@
 #define GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__
 
 #include <string>
+#include <google/protobuf/stubs/port.h>
 
 namespace google {
 namespace protobuf {
@@ -56,14 +57,14 @@
 //
 // Returns:
 //   The namespace to use for given file descriptor.
-string GetFileNamespace(const FileDescriptor* descriptor);
+string LIBPROTOC_EXPORT GetFileNamespace(const FileDescriptor* descriptor);
 
 // Requires:
 //   descriptor != NULL
 //
 // Returns:
 //   The fully-qualified C# class name.
-string GetClassName(const Descriptor* descriptor);
+string LIBPROTOC_EXPORT GetClassName(const Descriptor* descriptor);
 
 // Requires:
 //   descriptor != NULL
@@ -72,7 +73,7 @@
 //   The fully-qualified name of the C# class that provides
 //   access to the file descriptor. Proto compiler generates
 //   such class for each .proto file processed.
-string GetReflectionClassName(const FileDescriptor* descriptor);
+string LIBPROTOC_EXPORT GetReflectionClassName(const FileDescriptor* descriptor);
 
 // Generates output file name for given file descriptor. If generate_directories
 // is true, the output file will be put under directory corresponding to file's
@@ -88,7 +89,7 @@
 //    The file name to use as output file for given file descriptor. In case
 //    of failure, this function will return empty string and error parameter
 //    will contain the error message.
-string GetOutputFile(
+string LIBPROTOC_EXPORT GetOutputFile(
     const google::protobuf::FileDescriptor* descriptor,
     const string file_extension,
     const bool generate_directories,
diff --git a/src/google/protobuf/compiler/csharp/csharp_options.h b/src/google/protobuf/compiler/csharp/csharp_options.h
new file mode 100644
index 0000000..426fb3b
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_options.h
@@ -0,0 +1,79 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+// Generator options (used by csharp_generator.cc):
+struct Options {
+  Options() :
+      file_extension(".cs"),
+      base_namespace(""),
+      base_namespace_specified(false),
+      internal_access(false) {
+  }
+  // Extension of the generated file. Defaults to ".cs"
+  string file_extension;
+  // Base namespace to use to create directory hierarchy. Defaults to "".
+  // This option allows the simple creation of a conventional C# file layout,
+  // where directories are created relative to a project-specific base
+  // namespace. For example, in a project with a base namespace of PetShop, a
+  // proto of user.proto with a C# namespace of PetShop.Model.Shared would
+  // generate Model/Shared/User.cs underneath the specified --csharp_out
+  // directory.
+  //
+  // If no base namespace is specified, all files are generated in the
+  // --csharp_out directory, with no subdirectories created automatically.
+  string base_namespace;
+  // Whether the base namespace has been explicitly specified by the user.
+  // This is required as the base namespace can be explicitly set to the empty
+  // string, meaning "create a full directory hierarchy, starting from the first
+  // segment of the namespace."
+  bool base_namespace_specified;
+  // Whether the generated classes should have accessibility level of "internal".
+  // Defaults to false that generates "public" classes.
+  bool internal_access;
+};
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
index 60afd89..c3003e3 100644
--- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
@@ -40,6 +40,7 @@
 
 #include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
 #include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
 
 namespace google {
@@ -48,8 +49,8 @@
 namespace csharp {
 
 PrimitiveFieldGenerator::PrimitiveFieldGenerator(
-    const FieldDescriptor* descriptor, int fieldOrdinal)
-    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
   // TODO(jonskeet): Make this cleaner...
   is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING
       && descriptor->type() != FieldDescriptor::TYPE_BYTES;
@@ -70,7 +71,7 @@
     variables_,
     "private $type_name$ $name_def_message$;\n");
   WritePropertyDocComment(printer, descriptor_);
-  AddDeprecatedFlag(printer);
+  AddPublicMemberAttributes(printer);
   printer->Print(
     variables_,
     "$access_level$ $type_name$ $property_name$ {\n"
@@ -136,14 +137,22 @@
 }
 
 void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) {
-  printer->Print(
-    variables_,
-    "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n");
+  const char *text = "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n";
+  if (descriptor_->type() == FieldDescriptor::TYPE_FLOAT) {
+    text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode($property_name$);\n";
+  } else if (descriptor_->type() == FieldDescriptor::TYPE_DOUBLE) {
+    text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode($property_name$);\n";
+  }
+	printer->Print(variables_, text);
 }
 void PrimitiveFieldGenerator::WriteEquals(io::Printer* printer) {
-  printer->Print(
-    variables_,
-    "if ($property_name$ != other.$property_name$) return false;\n");
+  const char *text = "if ($property_name$ != other.$property_name$) return false;\n";
+  if (descriptor_->type() == FieldDescriptor::TYPE_FLOAT) {
+    text = "if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n";
+  } else if (descriptor_->type() == FieldDescriptor::TYPE_DOUBLE) {
+    text = "if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n";
+  }
+  printer->Print(variables_, text);
 }
 void PrimitiveFieldGenerator::WriteToString(io::Printer* printer) {
   printer->Print(
@@ -163,8 +172,8 @@
 }
 
 PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
-    const FieldDescriptor* descriptor, int fieldOrdinal)
-    : PrimitiveFieldGenerator(descriptor, fieldOrdinal) {
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+    : PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) {
   SetCommonOneofFieldVariables(&variables_);
 }
 
@@ -173,7 +182,7 @@
 
 void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
   WritePropertyDocComment(printer, descriptor_);
-  AddDeprecatedFlag(printer);
+  AddPublicMemberAttributes(printer);
   printer->Print(
     variables_,
     "$access_level$ $type_name$ $property_name$ {\n"
@@ -195,6 +204,10 @@
       "}\n");
 }
 
+void PrimitiveOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+  printer->Print(variables_, "$property_name$ = other.$property_name$;\n");
+}
+
 void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) {
   printer->Print(variables_,
     "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n");
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
index 8b87ebc..ca7b8b3 100644
--- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
@@ -41,9 +41,13 @@
 namespace compiler {
 namespace csharp {
 
+struct Options;
+
 class PrimitiveFieldGenerator : public FieldGeneratorBase {
  public:
-  PrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                          int fieldOrdinal,
+                          const Options *options);
   ~PrimitiveFieldGenerator();
 
   virtual void GenerateCodecCode(io::Printer* printer);
@@ -67,11 +71,14 @@
 
 class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
  public:
-  PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
+                               int fieldOrdinal,
+                               const Options *options);
   ~PrimitiveOneofFieldGenerator();
 
   virtual void GenerateCloningCode(io::Printer* printer);
   virtual void GenerateMembers(io::Printer* printer);
+  virtual void GenerateMergingCode(io::Printer* printer);
   virtual void WriteToString(io::Printer* printer);
   virtual void GenerateParsingCode(io::Printer* printer);
 
diff --git a/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc b/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
index 22dae43..5ddd616 100644
--- a/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
@@ -43,6 +43,7 @@
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
 #include <google/protobuf/compiler/csharp/csharp_message.h>
 #include <google/protobuf/compiler/csharp/csharp_names.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
 #include <google/protobuf/compiler/csharp/csharp_reflection_class.h>
 
 namespace google {
@@ -50,8 +51,9 @@
 namespace compiler {
 namespace csharp {
 
-ReflectionClassGenerator::ReflectionClassGenerator(const FileDescriptor* file)
-    : SourceGeneratorBase(file),
+ReflectionClassGenerator::ReflectionClassGenerator(const FileDescriptor* file,
+                                                   const Options* options)
+    : SourceGeneratorBase(file, options),
       file_(file) {
   namespace_ = GetFileNamespace(file);
   reflectionClassname_ = GetReflectionClassUnqualifiedName(file);
@@ -72,7 +74,7 @@
   if (file_->enum_type_count() > 0) {
     printer->Print("#region Enums\n");
     for (int i = 0; i < file_->enum_type_count(); i++) {
-      EnumGenerator enumGenerator(file_->enum_type(i));
+      EnumGenerator enumGenerator(file_->enum_type(i), this->options());
       enumGenerator.Generate(printer);
     }
     printer->Print("#endregion\n");
@@ -83,7 +85,7 @@
   if (file_->message_type_count() > 0) {
     printer->Print("#region Messages\n");
     for (int i = 0; i < file_->message_type_count(); i++) {
-      MessageGenerator messageGenerator(file_->message_type(i));
+      MessageGenerator messageGenerator(file_->message_type(i), this->options());
       messageGenerator.Generate(printer);
     }
     printer->Print("#endregion\n");
@@ -102,8 +104,10 @@
 
 void ReflectionClassGenerator::WriteIntroduction(io::Printer* printer) {
   printer->Print(
-    "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
-    "// source: $file_name$\n"
+    "// <auto-generated>\n"
+    "//     Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+    "//     source: $file_name$\n"
+    "// </auto-generated>\n"
     "#pragma warning disable 1591, 0612, 3021\n"
     "#region Designer generated code\n"
     "\n"
@@ -121,12 +125,9 @@
 
   printer->Print(
     "/// <summary>Holder for reflection information generated from $file_name$</summary>\n"
-    "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n",
-    "file_name", file_->name());
-  WriteGeneratedCodeAttributes(printer);
-  printer->Print(
     "$access_level$ static partial class $reflection_class_name$ {\n"
     "\n",
+    "file_name", file_->name(),
     "access_level", class_access_level(),
     "reflection_class_name", reflectionClassname_);
   printer->Indent();
diff --git a/src/google/protobuf/compiler/csharp/csharp_reflection_class.h b/src/google/protobuf/compiler/csharp/csharp_reflection_class.h
index 0a5b8ed..e0c69f3 100644
--- a/src/google/protobuf/compiler/csharp/csharp_reflection_class.h
+++ b/src/google/protobuf/compiler/csharp/csharp_reflection_class.h
@@ -43,7 +43,7 @@
 
 class ReflectionClassGenerator : public SourceGeneratorBase {
  public:
-  ReflectionClassGenerator(const FileDescriptor* file);
+  ReflectionClassGenerator(const FileDescriptor* file, const Options* options);
   ~ReflectionClassGenerator();
 
   void Generate(io::Printer* printer);
@@ -56,7 +56,9 @@
 
   void WriteIntroduction(io::Printer* printer);
   void WriteDescriptor(io::Printer* printer);
-  void WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last);
+  void WriteGeneratedCodeInfo(const Descriptor* descriptor,
+                              io::Printer* printer,
+                              bool last);
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReflectionClassGenerator);
 };
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
index 3a11b75..683c4b0 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
@@ -48,8 +48,8 @@
 namespace csharp {
 
 RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
-    const FieldDescriptor* descriptor, int fieldOrdinal)
-    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
 }
 
 RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {
@@ -64,7 +64,7 @@
   printer->Print(variables_,
     "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
   WritePropertyDocComment(printer, descriptor_);
-  AddDeprecatedFlag(printer);
+  AddPublicMemberAttributes(printer);
   printer->Print(
     variables_,
     "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
index ee50eef..819b583 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
@@ -45,7 +45,9 @@
 // should probably have a RepeatedFieldGeneratorBase.
 class RepeatedEnumFieldGenerator : public FieldGeneratorBase {
  public:
-  RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+                             int fieldOrdinal,
+                             const Options *options);
   ~RepeatedEnumFieldGenerator();
 
   virtual void GenerateCloningCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
index fc12fae..90af569 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
@@ -49,8 +49,8 @@
 namespace csharp {
 
 RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
-    const FieldDescriptor* descriptor, int fieldOrdinal)
-    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
 }
 
 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {
@@ -66,10 +66,12 @@
   // "create single field generator for this repeated field"
   // function, but it doesn't seem worth it for just this.
   if (IsWrapperType(descriptor_)) {
-    scoped_ptr<FieldGeneratorBase> single_generator(new WrapperFieldGenerator(descriptor_, fieldOrdinal_));
+    std::unique_ptr<FieldGeneratorBase> single_generator(
+      new WrapperFieldGenerator(descriptor_, fieldOrdinal_, this->options()));
     single_generator->GenerateCodecCode(printer);
   } else {
-    scoped_ptr<FieldGeneratorBase> single_generator(new MessageFieldGenerator(descriptor_, fieldOrdinal_));
+    std::unique_ptr<FieldGeneratorBase> single_generator(
+      new MessageFieldGenerator(descriptor_, fieldOrdinal_, this->options()));
     single_generator->GenerateCodecCode(printer);
   }
   printer->Print(";\n");
@@ -77,7 +79,7 @@
     variables_,
     "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
   WritePropertyDocComment(printer, descriptor_);
-  AddDeprecatedFlag(printer);
+  AddPublicMemberAttributes(printer);
   printer->Print(
     variables_,
     "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
index cf601c7..6e33648 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
@@ -41,9 +41,13 @@
 namespace compiler {
 namespace csharp {
 
+struct Options;
+
 class RepeatedMessageFieldGenerator : public FieldGeneratorBase {
  public:
-  RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+                                int fieldOrdinal,
+                                const Options *options);
   ~RepeatedMessageFieldGenerator();
 
   virtual void GenerateCloningCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
index 5fe0b20..cd91506 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
@@ -48,8 +48,8 @@
 namespace csharp {
 
 RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
-    const FieldDescriptor* descriptor, int fieldOrdinal)
-    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
 }
 
 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {
@@ -64,7 +64,7 @@
   printer->Print(variables_,
     "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
   WritePropertyDocComment(printer, descriptor_);
-  AddDeprecatedFlag(printer);
+  AddPublicMemberAttributes(printer);
   printer->Print(
     variables_,
     "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
index f1ceeb5..a59348a 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
@@ -43,7 +43,7 @@
 
 class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase {
  public:
-  RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options);
   ~RepeatedPrimitiveFieldGenerator();
 
   virtual void GenerateCloningCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
index 735d164..1fda7dd 100644
--- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
@@ -39,25 +39,32 @@
 
 #include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_names.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace csharp {
 
-SourceGeneratorBase::SourceGeneratorBase(const FileDescriptor* descriptor)
-    : descriptor_(descriptor) {
+SourceGeneratorBase::SourceGeneratorBase(const FileDescriptor* descriptor,
+                                         const Options *options)
+    : descriptor_(descriptor), options_(options) {
 }
 
 SourceGeneratorBase::~SourceGeneratorBase() {
 }
 
 void SourceGeneratorBase::WriteGeneratedCodeAttributes(io::Printer* printer) {
-  // This hook can be used to reintroduce generated code attributes in the future.
+  printer->Print("[global::System.Diagnostics.DebuggerNonUserCodeAttribute]\n");
 }
 
 std::string SourceGeneratorBase::class_access_level() {
-  return IsDescriptorProto(descriptor_) ? "internal" : "public";  // public_classes is always on.
+  return (IsDescriptorProto(descriptor_) || this->options()->internal_access) ? "internal" : "public";
+}
+
+const Options* SourceGeneratorBase::options() {
+  return this->options_;
 }
 
 }  // namespace csharp
diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h
index 6caef17..c741080 100644
--- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h
+++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h
@@ -40,17 +40,23 @@
 namespace compiler {
 namespace csharp {
 
+struct Options;
+
 class SourceGeneratorBase {
  protected:
-  SourceGeneratorBase(const FileDescriptor* descriptor);
+  SourceGeneratorBase(const FileDescriptor* descriptor, const Options* options);
   virtual ~SourceGeneratorBase();
 
   std::string class_access_level();
+  const Options* options();
 
+  // Write any attributes used to decorate generated function members (methods and properties).
+  // Should not be used to decorate types.
   void WriteGeneratedCodeAttributes(io::Printer* printer);
 
  private:
   const FileDescriptor* descriptor_;
+  const Options *options_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceGeneratorBase);
 };
diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
index 6a3750e..047edf7 100644
--- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
@@ -39,6 +39,7 @@
 
 #include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_options.h>
 #include <google/protobuf/compiler/csharp/csharp_wrapper_field.h>
 
 namespace google {
@@ -47,8 +48,8 @@
 namespace csharp {
 
 WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor,
-                                       int fieldOrdinal)
-    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+                                       int fieldOrdinal, const Options *options)
+    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
   variables_["has_property_check"] = name() + "_ != null";
   variables_["has_not_property_check"] = name() + "_ == null";
   const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
@@ -72,7 +73,7 @@
     ";\n"
     "private $type_name$ $name$_;\n");
   WritePropertyDocComment(printer, descriptor_);
-  AddDeprecatedFlag(printer);
+  AddPublicMemberAttributes(printer);
   printer->Print(
     variables_,
     "$access_level$ $type_name$ $property_name$ {\n"
@@ -119,15 +120,25 @@
 }
 
 void WrapperFieldGenerator::WriteHash(io::Printer* printer) {
-  printer->Print(
-    variables_,
-    "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n");
+  const char *text = "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n";
+  if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_FLOAT) {
+    text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.GetHashCode($property_name$);\n";
+  }
+  else if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_DOUBLE) {
+    text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode($property_name$);\n";
+  }
+  printer->Print(variables_, text);
 }
 
 void WrapperFieldGenerator::WriteEquals(io::Printer* printer) {
-  printer->Print(
-    variables_,
-    "if ($property_name$ != other.$property_name$) return false;\n");
+  const char *text = "if ($property_name$ != other.$property_name$) return false;\n";
+  if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_FLOAT) {
+    text = "if (!pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n";
+  }
+  else if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_DOUBLE) {
+    text = "if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n";
+  }
+  printer->Print(variables_, text);
 }
 
 void WrapperFieldGenerator::WriteToString(io::Printer* printer) {
@@ -151,9 +162,9 @@
   }
 }
 
-WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(const FieldDescriptor* descriptor,
-    int fieldOrdinal)
-    : WrapperFieldGenerator(descriptor, fieldOrdinal) {
+WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(
+    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
+    : WrapperFieldGenerator(descriptor, fieldOrdinal, options) {
     SetCommonOneofFieldVariables(&variables_);
 }
 
@@ -168,7 +179,7 @@
   GenerateCodecCode(printer);
   printer->Print(";\n");
   WritePropertyDocComment(printer, descriptor_);
-  AddDeprecatedFlag(printer);
+  AddPublicMemberAttributes(printer);
   printer->Print(
     variables_,
     "$access_level$ $type_name$ $property_name$ {\n"
@@ -180,6 +191,10 @@
     "}\n");
 }
 
+void WrapperOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+  printer->Print(variables_, "$property_name$ = other.$property_name$;\n");
+}
+
 void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
   printer->Print(
     variables_,
diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
index 6e2414a..452531f 100644
--- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
@@ -41,9 +41,13 @@
 namespace compiler {
 namespace csharp {
 
+struct Options;
+
 class WrapperFieldGenerator : public FieldGeneratorBase {
  public:
-  WrapperFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  WrapperFieldGenerator(const FieldDescriptor* descriptor,
+                        int fieldOrdinal,
+                        const Options *options);
   ~WrapperFieldGenerator();
 
   virtual void GenerateCodecCode(io::Printer* printer);
@@ -65,10 +69,13 @@
 
 class WrapperOneofFieldGenerator : public WrapperFieldGenerator {
  public:
-  WrapperOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  WrapperOneofFieldGenerator(const FieldDescriptor* descriptor,
+                             int fieldOrdinal,
+                             const Options *options);
   ~WrapperOneofFieldGenerator();
 
   virtual void GenerateMembers(io::Printer* printer);
+  virtual void GenerateMergingCode(io::Printer* printer);
   virtual void GenerateParsingCode(io::Printer* printer);
   virtual void GenerateSerializationCode(io::Printer* printer);
   virtual void GenerateSerializedSizeCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/importer.cc b/src/google/protobuf/compiler/importer.cc
index 0d9093c..c3831e7 100644
--- a/src/google/protobuf/compiler/importer.cc
+++ b/src/google/protobuf/compiler/importer.cc
@@ -33,7 +33,7 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
 #ifdef _MSC_VER
-#include <io.h>
+#include <direct.h>
 #else
 #include <unistd.h>
 #endif
@@ -44,9 +44,6 @@
 
 #include <algorithm>
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 
 #include <google/protobuf/compiler/importer.h>
 
@@ -55,15 +52,22 @@
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/stubs/strutil.h>
 
+
+#include <google/protobuf/stubs/io_win32.h>
+
+#ifdef _WIN32
+#include <ctype.h>
+#endif
+
 namespace google {
 namespace protobuf {
 namespace compiler {
 
 #ifdef _WIN32
-#ifndef F_OK
-#define F_OK 00  // not defined by MSVC for whatever reason
-#endif
-#include <ctype.h>
+// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
+// them like we do below.
+using google::protobuf::internal::win32::access;
+using google::protobuf::internal::win32::open;
 #endif
 
 // Returns true if the text looks like a Windows-style absolute path, starting
@@ -125,7 +129,7 @@
 
 bool SourceTreeDescriptorDatabase::FindFileByName(
     const string& filename, FileDescriptorProto* output) {
-  google::protobuf::scoped_ptr<io::ZeroCopyInputStream> input(source_tree_->Open(filename));
+  std::unique_ptr<io::ZeroCopyInputStream> input(source_tree_->Open(filename));
   if (input == NULL) {
     if (error_collector_ != NULL) {
       error_collector_->AddError(filename, -1, 0,
@@ -222,6 +226,7 @@
   pool_.ClearUnusedImportTrackFiles();
 }
 
+
 // ===================================================================
 
 SourceTree::~SourceTree() {}
@@ -270,8 +275,8 @@
   }
 #endif
 
-  vector<string> canonical_parts;
-  vector<string> parts = Split(
+  std::vector<string> canonical_parts;
+  std::vector<string> parts = Split(
       path, "/", true);  // Note:  Removes empty parts.
   for (int i = 0; i < parts.size(); i++) {
     if (parts[i] == ".") {
@@ -294,10 +299,8 @@
 }
 
 static inline bool ContainsParentReference(const string& path) {
-  return path == ".." ||
-         HasPrefixString(path, "../") ||
-         HasSuffixString(path, "/..") ||
-         path.find("/../") != string::npos;
+  return path == ".." || HasPrefixString(path, "../") ||
+         HasSuffixString(path, "/..") || path.find("/../") != string::npos;
 }
 
 // Maps a file from an old location to a new one.  Typically, old_prefix is
@@ -327,8 +330,7 @@
       // We do not allow the file name to use "..".
       return false;
     }
-    if (HasPrefixString(filename, "/") ||
-        IsWindowsAbsolutePath(filename)) {
+    if (HasPrefixString(filename, "/") || IsWindowsAbsolutePath(filename)) {
       // This is an absolute path, so it isn't matched by the empty string.
       return false;
     }
@@ -416,7 +418,7 @@
   // Verify that we can open the file.  Note that this also has the side-effect
   // of verifying that we are not canonicalizing away any non-existent
   // directories.
-  google::protobuf::scoped_ptr<io::ZeroCopyInputStream> stream(OpenDiskFile(disk_file));
+  std::unique_ptr<io::ZeroCopyInputStream> stream(OpenDiskFile(disk_file));
   if (stream == NULL) {
     return CANNOT_OPEN;
   }
@@ -426,7 +428,7 @@
 
 bool DiskSourceTree::VirtualFileToDiskFile(const string& virtual_file,
                                            string* disk_file) {
-  google::protobuf::scoped_ptr<io::ZeroCopyInputStream> stream(
+  std::unique_ptr<io::ZeroCopyInputStream> stream(
       OpenVirtualFile(virtual_file, disk_file));
   return stream != NULL;
 }
diff --git a/src/google/protobuf/compiler/importer.h b/src/google/protobuf/compiler/importer.h
index cc8fcc3..a4ffcf8 100644
--- a/src/google/protobuf/compiler/importer.h
+++ b/src/google/protobuf/compiler/importer.h
@@ -175,6 +175,7 @@
   void AddUnusedImportTrackFile(const string& file_name);
   void ClearUnusedImportTrackFiles();
 
+
  private:
   SourceTreeDescriptorDatabase database_;
   DescriptorPool pool_;
@@ -305,7 +306,7 @@
                    const string& disk_path_param)
       : virtual_path(virtual_path_param), disk_path(disk_path_param) {}
   };
-  vector<Mapping> mappings_;
+  std::vector<Mapping> mappings_;
   string last_error_message_;
 
   // Like Open(), but returns the on-disk path in disk_file if disk_file is
diff --git a/src/google/protobuf/compiler/importer_unittest.cc b/src/google/protobuf/compiler/importer_unittest.cc
index be19aa2..73bef3f 100644
--- a/src/google/protobuf/compiler/importer_unittest.cc
+++ b/src/google/protobuf/compiler/importer_unittest.cc
@@ -32,25 +32,23 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/importer.h>
+
 #include <google/protobuf/stubs/hash.h>
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 
-#include <google/protobuf/compiler/importer.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-
-#include <google/protobuf/stubs/map_util.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/testing/file.h>
-#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.h>
 #include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/strutil.h>
 
 namespace google {
 namespace protobuf {
@@ -267,7 +265,7 @@
 
   void ExpectFileContents(const string& filename,
                           const char* expected_contents) {
-    google::protobuf::scoped_ptr<io::ZeroCopyInputStream> input(source_tree_.Open(filename));
+    std::unique_ptr<io::ZeroCopyInputStream> input(source_tree_.Open(filename));
 
     ASSERT_FALSE(input == NULL);
 
@@ -284,7 +282,7 @@
 
   void ExpectCannotOpenFile(const string& filename,
                             const string& error_message) {
-    google::protobuf::scoped_ptr<io::ZeroCopyInputStream> input(source_tree_.Open(filename));
+    std::unique_ptr<io::ZeroCopyInputStream> input(source_tree_.Open(filename));
     EXPECT_TRUE(input == NULL);
     EXPECT_EQ(error_message, source_tree_.GetLastErrorMessage());
   }
@@ -292,7 +290,7 @@
   DiskSourceTree source_tree_;
 
   // Paths of two on-disk directories to use during the test.
-  vector<string> dirnames_;
+  std::vector<string> dirnames_;
 };
 
 TEST_F(DiskSourceTreeTest, MapRoot) {
diff --git a/src/google/protobuf/compiler/java/java_context.cc b/src/google/protobuf/compiler/java/java_context.cc
index 7d21fe6..2528c2d 100644
--- a/src/google/protobuf/compiler/java/java_context.cc
+++ b/src/google/protobuf/compiler/java/java_context.cc
@@ -42,15 +42,15 @@
 namespace compiler {
 namespace java {
 
-Context::Context(const FileDescriptor* file)
-    : name_resolver_(new ClassNameResolver) {
+Context::Context(const FileDescriptor* file, const Options& options)
+    : name_resolver_(new ClassNameResolver), options_(options) {
   InitializeFieldGeneratorInfo(file);
 }
 
 Context::~Context() {
 }
 
-ClassNameResolver* Context::GetNameResolver() {
+ClassNameResolver* Context::GetNameResolver() const {
   return name_resolver_.get();
 }
 
@@ -69,14 +69,14 @@
       // field1 is repeated, and field2 is not.
       if (name1 + "Count" == name2) {
         *info = "both repeated field \"" + field1->name() + "\" and singular " +
-            "field \"" + field2->name() + "\" generates the method \"" +
-            "get" + name1 + "Count()\"";
+                "field \"" + field2->name() + "\" generate the method \"" +
+                "get" + name1 + "Count()\"";
         return true;
       }
       if (name1 + "List" == name2) {
         *info = "both repeated field \"" + field1->name() + "\" and singular " +
-            "field \"" + field2->name() + "\" generates the method \"" +
-            "get" + name1 + "List()\"";
+                "field \"" + field2->name() + "\" generate the method \"" +
+                "get" + name1 + "List()\"";
         return true;
       }
       // Well, there are obviously many more conflicting cases, but it probably
@@ -108,7 +108,7 @@
   for (int i = 0; i < message->nested_type_count(); ++i) {
     InitializeFieldGeneratorInfoForMessage(message->nested_type(i));
   }
-  vector<const FieldDescriptor*> fields;
+  std::vector<const FieldDescriptor*> fields;
   for (int i = 0; i < message->field_count(); ++i) {
     fields.push_back(message->field(i));
   }
@@ -124,11 +124,11 @@
 }
 
 void Context::InitializeFieldGeneratorInfoForFields(
-    const vector<const FieldDescriptor*>& fields) {
+    const std::vector<const FieldDescriptor*>& fields) {
   // Find out all fields that conflict with some other field in the same
   // message.
-  vector<bool> is_conflict(fields.size());
-  vector<string> conflict_reason(fields.size());
+  std::vector<bool> is_conflict(fields.size());
+  std::vector<string> conflict_reason(fields.size());
   for (int i = 0; i < fields.size(); ++i) {
     const FieldDescriptor* field = fields[i];
     const string& name = UnderscoresToCapitalizedCamelCase(field);
@@ -154,7 +154,7 @@
   for (int i = 0; i < fields.size(); ++i) {
     const FieldDescriptor* field = fields[i];
     FieldGeneratorInfo info;
-    info.name = UnderscoresToCamelCase(field);
+    info.name = CamelCaseFieldName(field);
     info.capitalized_name = UnderscoresToCapitalizedCamelCase(field);
     // For fields conflicting with some other fields, we append the field
     // number to their field names in generated code to avoid conflicts.
@@ -189,6 +189,13 @@
   return result;
 }
 
+// Does this message class have generated parsing, serialization, and other
+// standard methods for which reflection-based fallback implementations exist?
+bool Context::HasGeneratedMethods(const Descriptor* descriptor) const {
+  return options_.enforce_lite ||
+         descriptor->file()->options().optimize_for() != FileOptions::CODE_SIZE;
+}
+
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_context.h b/src/google/protobuf/compiler/java/java_context.h
index 5b595d0..9de7415 100644
--- a/src/google/protobuf/compiler/java/java_context.h
+++ b/src/google/protobuf/compiler/java/java_context.h
@@ -33,12 +33,10 @@
 
 #include <map>
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 #include <vector>
 
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_options.h>
 
 namespace google {
 namespace protobuf {
@@ -46,6 +44,7 @@
   class FieldDescriptor;
   class OneofDescriptor;
   class Descriptor;
+  class EnumDescriptor;
   namespace compiler {
     namespace java {
       class ClassNameResolver;  // name_resolver.h
@@ -63,12 +62,12 @@
 // generators.
 class Context {
  public:
-  explicit Context(const FileDescriptor* file);
+  Context(const FileDescriptor* file, const Options& options);
   ~Context();
 
   // Get the name resolver associated with this context. The resolver
   // can be used to map descriptors to Java class names.
-  ClassNameResolver* GetNameResolver();
+  ClassNameResolver* GetNameResolver() const;
 
   // Get the FieldGeneratorInfo for a given field.
   const FieldGeneratorInfo* GetFieldGeneratorInfo(
@@ -78,15 +77,29 @@
   const OneofGeneratorInfo* GetOneofGeneratorInfo(
       const OneofDescriptor* oneof) const;
 
+  const Options& options() const { return options_; }
+
+  // Enforces all the files (including transitive dependencies) to use
+  // LiteRuntime.
+
+  bool EnforceLite() const { return options_.enforce_lite; }
+
+  // Does this message class have generated parsing, serialization, and other
+  // standard methods for which reflection-based fallback implementations exist?
+  bool HasGeneratedMethods(const Descriptor* descriptor) const;
+
  private:
   void InitializeFieldGeneratorInfo(const FileDescriptor* file);
   void InitializeFieldGeneratorInfoForMessage(const Descriptor* message);
   void InitializeFieldGeneratorInfoForFields(
-      const vector<const FieldDescriptor*>& fields);
+      const std::vector<const FieldDescriptor*>& fields);
 
-  google::protobuf::scoped_ptr<ClassNameResolver> name_resolver_;
-  map<const FieldDescriptor*, FieldGeneratorInfo> field_generator_info_map_;
-  map<const OneofDescriptor*, OneofGeneratorInfo> oneof_generator_info_map_;
+  std::unique_ptr<ClassNameResolver> name_resolver_;
+  std::map<const FieldDescriptor*, FieldGeneratorInfo>
+      field_generator_info_map_;
+  std::map<const OneofDescriptor*, OneofGeneratorInfo>
+      oneof_generator_info_map_;
+  Options options_;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Context);
 };
 
diff --git a/src/google/protobuf/compiler/java/java_doc_comment.cc b/src/google/protobuf/compiler/java/java_doc_comment.cc
index 663f0c9..59c04ad 100644
--- a/src/google/protobuf/compiler/java/java_doc_comment.cc
+++ b/src/google/protobuf/compiler/java/java_doc_comment.cc
@@ -115,14 +115,12 @@
     // HTML-escape them so that they don't accidentally close the doc comment.
     comments = EscapeJavadoc(comments);
 
-    vector<string> lines = Split(comments, "\n");
+    std::vector<string> lines = Split(comments, "\n");
     while (!lines.empty() && lines.back().empty()) {
       lines.pop_back();
     }
 
-    printer->Print(
-        " *\n"
-        " * <pre>\n");
+    printer->Print(" * <pre>\n");
     for (int i = 0; i < lines.size(); i++) {
       // Most lines should start with a space.  Watch out for lines that start
       // with a /, since putting that right after the leading asterisk will
@@ -133,7 +131,9 @@
         printer->Print(" *$line$\n", "line", lines[i]);
       }
     }
-    printer->Print(" * </pre>\n");
+    printer->Print(
+        " * </pre>\n"
+        " *\n");
   }
 }
 
@@ -163,12 +163,12 @@
 }
 
 void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) {
-  printer->Print(
-    "/**\n"
-    " * Protobuf type {@code $fullname$}\n",
-    "fullname", EscapeJavadoc(message->full_name()));
+  printer->Print("/**\n");
   WriteDocCommentBody(printer, message);
-  printer->Print(" */\n");
+  printer->Print(
+    " * Protobuf type {@code $fullname$}\n"
+    " */\n",
+    "fullname", EscapeJavadoc(message->full_name()));
 }
 
 void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) {
@@ -176,55 +176,55 @@
   // etc., but in practice everyone already knows the difference between these
   // so it's redundant information.
 
-  // We use the field declaration as the first line of the comment, e.g.:
+  // We start the comment with the main body based on the comments from the
+  // .proto file (if present). We then end with the field declaration, e.g.:
   //   optional string foo = 5;
-  // This communicates a lot of information about the field in a small space.
   // If the field is a group, the debug string might end with {.
+  printer->Print("/**\n");
+  WriteDocCommentBody(printer, field);
   printer->Print(
-    "/**\n"
     " * <code>$def$</code>\n",
     "def", EscapeJavadoc(FirstLineOf(field->DebugString())));
-  WriteDocCommentBody(printer, field);
   printer->Print(" */\n");
 }
 
 void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_) {
-  printer->Print(
-    "/**\n"
-    " * Protobuf enum {@code $fullname$}\n",
-    "fullname", EscapeJavadoc(enum_->full_name()));
+  printer->Print("/**\n");
   WriteDocCommentBody(printer, enum_);
-  printer->Print(" */\n");
+  printer->Print(
+    " * Protobuf enum {@code $fullname$}\n"
+    " */\n",
+    "fullname", EscapeJavadoc(enum_->full_name()));
 }
 
 void WriteEnumValueDocComment(io::Printer* printer,
                               const EnumValueDescriptor* value) {
-  printer->Print(
-    "/**\n"
-    " * <code>$def$</code>\n",
-    "def", EscapeJavadoc(FirstLineOf(value->DebugString())));
+  printer->Print("/**\n");
   WriteDocCommentBody(printer, value);
-  printer->Print(" */\n");
+  printer->Print(
+    " * <code>$def$</code>\n"
+    " */\n",
+    "def", EscapeJavadoc(FirstLineOf(value->DebugString())));
 }
 
 void WriteServiceDocComment(io::Printer* printer,
                             const ServiceDescriptor* service) {
-  printer->Print(
-    "/**\n"
-    " * Protobuf service {@code $fullname$}\n",
-    "fullname", EscapeJavadoc(service->full_name()));
+  printer->Print("/**\n");
   WriteDocCommentBody(printer, service);
-  printer->Print(" */\n");
+  printer->Print(
+    " * Protobuf service {@code $fullname$}\n"
+    " */\n",
+    "fullname", EscapeJavadoc(service->full_name()));
 }
 
 void WriteMethodDocComment(io::Printer* printer,
                            const MethodDescriptor* method) {
-  printer->Print(
-    "/**\n"
-    " * <code>$def$</code>\n",
-    "def", EscapeJavadoc(FirstLineOf(method->DebugString())));
+  printer->Print("/**\n");
   WriteDocCommentBody(printer, method);
-  printer->Print(" */\n");
+  printer->Print(
+    " * <code>$def$</code>\n"
+    " */\n",
+    "def", EscapeJavadoc(FirstLineOf(method->DebugString())));
 }
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc
index 5fc9b00..bef69f1 100644
--- a/src/google/protobuf/compiler/java/java_enum.cc
+++ b/src/google/protobuf/compiler/java/java_enum.cc
@@ -36,12 +36,12 @@
 #include <string>
 
 #include <google/protobuf/compiler/java/java_context.h>
-#include <google/protobuf/compiler/java/java_enum.h>
 #include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_enum.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
-#include <google/protobuf/io/printer.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
 #include <google/protobuf/stubs/strutil.h>
 
 namespace google {
@@ -49,21 +49,11 @@
 namespace compiler {
 namespace java {
 
-namespace {
-bool EnumHasCustomOptions(const EnumDescriptor* descriptor) {
-  if (descriptor->options().unknown_fields().field_count() > 0) return true;
-  for (int i = 0; i < descriptor->value_count(); ++i) {
-    const EnumValueDescriptor* value = descriptor->value(i);
-    if (value->options().unknown_fields().field_count() > 0) return true;
-  }
-  return false;
-}
-}  // namespace
-
 EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
                              bool immutable_api,
                              Context* context)
   : descriptor_(descriptor), immutable_api_(immutable_api),
+    context_(context),
     name_resolver_(context->GetNameResolver())  {
   for (int i = 0; i < descriptor_->value_count(); i++) {
     const EnumValueDescriptor* value = descriptor_->value(i);
@@ -85,14 +75,26 @@
 
 void EnumGenerator::Generate(io::Printer* printer) {
   WriteEnumDocComment(printer, descriptor_);
+  MaybePrintGeneratedAnnotation(context_, printer, descriptor_, immutable_api_);
   printer->Print(
-    "public enum $classname$\n"
-    "    implements com.google.protobuf.ProtocolMessageEnum {\n",
-    "classname", descriptor_->name());
+      "public enum $classname$\n"
+      "    implements com.google.protobuf.ProtocolMessageEnum {\n",
+      "classname", descriptor_->name());
+  printer->Annotate("classname", descriptor_);
   printer->Indent();
 
+  bool ordinal_is_index = true;
+  string index_text = "ordinal()";
   for (int i = 0; i < canonical_values_.size(); i++) {
-    map<string, string> vars;
+    if (canonical_values_[i]->index() != i) {
+      ordinal_is_index = false;
+      index_text = "index";
+      break;
+    }
+  }
+
+  for (int i = 0; i < canonical_values_.size(); i++) {
+    std::map<string, string> vars;
     vars["name"] = canonical_values_[i]->name();
     vars["index"] = SimpleItoa(canonical_values_[i]->index());
     vars["number"] = SimpleItoa(canonical_values_[i]->number());
@@ -100,12 +102,23 @@
     if (canonical_values_[i]->options().deprecated()) {
       printer->Print("@java.lang.Deprecated\n");
     }
-    printer->Print(vars,
-      "$name$($index$, $number$),\n");
+    if (ordinal_is_index) {
+      printer->Print(vars,
+        "$name$($number$),\n");
+    } else {
+      printer->Print(vars,
+        "$name$($index$, $number$),\n");
+    }
+    printer->Annotate("name", canonical_values_[i]);
   }
 
   if (SupportUnknownEnumValue(descriptor_->file())) {
-    printer->Print("UNRECOGNIZED(-1, -1),\n");
+    if (ordinal_is_index) {
+      printer->Print("${$UNRECOGNIZED$}$(-1),\n", "{", "", "}", "");
+    } else {
+      printer->Print("${$UNRECOGNIZED$}$(-1, -1),\n", "{", "", "}", "");
+    }
+    printer->Annotate("{", "}", descriptor_);
   }
 
   printer->Print(
@@ -115,22 +128,26 @@
   // -----------------------------------------------------------------
 
   for (int i = 0; i < aliases_.size(); i++) {
-    map<string, string> vars;
+    std::map<string, string> vars;
     vars["classname"] = descriptor_->name();
     vars["name"] = aliases_[i].value->name();
     vars["canonical_name"] = aliases_[i].canonical_value->name();
     WriteEnumValueDocComment(printer, aliases_[i].value);
     printer->Print(vars,
       "public static final $classname$ $name$ = $canonical_name$;\n");
+    printer->Annotate("name", aliases_[i].value);
   }
 
   for (int i = 0; i < descriptor_->value_count(); i++) {
-    map<string, string> vars;
+    std::map<string, string> vars;
     vars["name"] = descriptor_->value(i)->name();
     vars["number"] = SimpleItoa(descriptor_->value(i)->number());
+    vars["{"] = "";
+    vars["}"] = "";
     WriteEnumValueDocComment(printer, descriptor_->value(i));
     printer->Print(vars,
-      "public static final int $name$_VALUE = $number$;\n");
+      "public static final int ${$$name$_VALUE$}$ = $number$;\n");
+    printer->Annotate("{", "}", descriptor_->value(i));
   }
   printer->Print("\n");
 
@@ -140,17 +157,33 @@
     "\n"
     "public final int getNumber() {\n");
   if (SupportUnknownEnumValue(descriptor_->file())) {
-    printer->Print(
-      "  if (index == -1) {\n"
-      "    throw new java.lang.IllegalArgumentException(\n"
-      "        \"Can't get the number of an unknown enum value.\");\n"
-      "  }\n");
+    if (ordinal_is_index) {
+      printer->Print(
+        "  if (this == UNRECOGNIZED) {\n"
+        "    throw new java.lang.IllegalArgumentException(\n"
+        "        \"Can't get the number of an unknown enum value.\");\n"
+        "  }\n");
+    } else {
+      printer->Print(
+        "  if (index == -1) {\n"
+        "    throw new java.lang.IllegalArgumentException(\n"
+        "        \"Can't get the number of an unknown enum value.\");\n"
+        "  }\n");
+    }
   }
   printer->Print(
     "  return value;\n"
     "}\n"
     "\n"
+    "/**\n"
+    " * @deprecated Use {@link #forNumber(int)} instead.\n"
+    " */\n"
+    "@java.lang.Deprecated\n"
     "public static $classname$ valueOf(int value) {\n"
+    "  return forNumber(value);\n"
+    "}\n"
+    "\n"
+    "public static $classname$ forNumber(int value) {\n"
     "  switch (value) {\n",
     "classname", descriptor_->name());
   printer->Indent();
@@ -178,7 +211,7 @@
     "    $classname$> internalValueMap =\n"
     "      new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
     "        public $classname$ findValueByNumber(int number) {\n"
-    "          return $classname$.valueOf(number);\n"
+    "          return $classname$.forNumber(number);\n"
     "        }\n"
     "      };\n"
     "\n",
@@ -187,66 +220,32 @@
   // -----------------------------------------------------------------
   // Reflection
 
-  if (HasDescriptorMethods(descriptor_)) {
+  if (HasDescriptorMethods(descriptor_, context_->EnforceLite())) {
     printer->Print(
       "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n"
       "    getValueDescriptor() {\n"
-      "  return getDescriptor().getValues().get(index);\n"
+      "  return getDescriptor().getValues().get($index_text$);\n"
       "}\n"
       "public final com.google.protobuf.Descriptors.EnumDescriptor\n"
       "    getDescriptorForType() {\n"
       "  return getDescriptor();\n"
       "}\n"
       "public static final com.google.protobuf.Descriptors.EnumDescriptor\n"
-      "    getDescriptor() {\n");
+      "    getDescriptor() {\n",
+      "index_text", index_text);
 
     // TODO(kenton):  Cache statically?  Note that we can't access descriptors
     //   at module init time because it wouldn't work with descriptor.proto, but
     //   we can cache the value the first time getDescriptor() is called.
     if (descriptor_->containing_type() == NULL) {
-      if (!MultipleJavaFiles(descriptor_->file(), immutable_api_)) {
-        printer->Print(
-          "  return $file$.getDescriptor().getEnumTypes().get($index$);\n",
-          "file", name_resolver_->GetClassName(descriptor_->file(),
-                                               immutable_api_),
-          "index", SimpleItoa(descriptor_->index()));
-      } else {
-        printer->Indent();
-        if (EnumHasCustomOptions(descriptor_)) {
-          // We need to load the immutable classes in order to parse custom
-          // options. However, since file level enums (no outer class) are
-          // shared by immutable code and mutable code, the immutable classes
-          // may not exist. So we try to use Java reflection to retrieve the
-          // descriptor from immutable classes.
-          printer->Print(
-            "try {\n"
-            "  java.lang.Class immutableFileClass =\n"
-            "      java.lang.Class.forName(\"$immutable_file_class_name$\");\n"
-            "  @java.lang.SuppressWarnings(\"unchecked\")\n"
-            "  java.lang.reflect.Method m =\n"
-            "      immutableFileClass.getMethod(\"getDescriptor\");\n"
-            "  com.google.protobuf.Descriptors.FileDescriptor file =\n"
-            "      (com.google.protobuf.Descriptors.FileDescriptor)\n"
-            "          m.invoke(immutableFileClass);\n"
-            "  return file.getEnumTypes().get($index$);\n"
-            "} catch (Exception e) {\n"
-            // Immutable classes cannot be found. Proceed as if custom options
-            // don't exist.
-            "}\n",
-            "immutable_file_class_name",
-            name_resolver_->GetImmutableClassName(descriptor_->file()),
-            "index", SimpleItoa(descriptor_->index()));
-        }
-        printer->Print(
-          "return $immutable_package$.$descriptor_class$.$descriptor$\n"
-          "    .getEnumTypes().get($index$);\n",
-          "immutable_package", FileJavaPackage(descriptor_->file(), true),
-          "descriptor_class",
-          name_resolver_->GetDescriptorClassName(descriptor_->file()),
-          "descriptor", "getDescriptor()",
-          "index", SimpleItoa(descriptor_->index()));
-        printer->Outdent();
-      }
+      // The class generated for the File fully populates the descriptor with
+      // extensions in both the mutable and immutable cases. (In the mutable api
+      // this is accomplished by attempting to load the immutable outer class).
+      printer->Print(
+        "  return $file$.getDescriptor().getEnumTypes().get($index$);\n",
+        "file", name_resolver_->GetClassName(descriptor_->file(),
+                                             immutable_api_),
+        "index", SimpleItoa(descriptor_->index()));
     } else {
       printer->Print(
           "  return $parent$.$descriptor$.getEnumTypes().get($index$);\n",
@@ -304,16 +303,27 @@
       "}\n"
       "\n");
 
-    printer->Print("private final int index;\n");
+    if (!ordinal_is_index) {
+      printer->Print("private final int index;\n");
+    }
   }
 
   // -----------------------------------------------------------------
 
   printer->Print(
-    "private final int value;\n\n"
-    "private $classname$(int index, int value) {\n",
-    "classname", descriptor_->name());
-  if (HasDescriptorMethods(descriptor_)) {
+    "private final int value;\n\n");
+
+  if (ordinal_is_index) {
+    printer->Print(
+      "private $classname$(int value) {\n",
+      "classname", descriptor_->name());
+  } else {
+    printer->Print(
+      "private $classname$(int index, int value) {\n",
+      "classname", descriptor_->name());
+  }
+  if (HasDescriptorMethods(descriptor_, context_->EnforceLite()) &&
+      !ordinal_is_index) {
     printer->Print("  this.index = index;\n");
   }
   printer->Print(
diff --git a/src/google/protobuf/compiler/java/java_enum.h b/src/google/protobuf/compiler/java/java_enum.h
index a0d91f5..13dfc32 100644
--- a/src/google/protobuf/compiler/java/java_enum.h
+++ b/src/google/protobuf/compiler/java/java_enum.h
@@ -58,9 +58,8 @@
 
 class EnumGenerator {
  public:
-  explicit EnumGenerator(const EnumDescriptor* descriptor,
-                         bool immutable_api,
-                         Context* context);
+  EnumGenerator(const EnumDescriptor* descriptor, bool immutable_api,
+                Context* context);
   ~EnumGenerator();
 
   void Generate(io::Printer* printer);
@@ -73,13 +72,13 @@
   // considered equivalent.  We treat the first defined constant for any
   // given numeric value as "canonical" and the rest as aliases of that
   // canonical value.
-  vector<const EnumValueDescriptor*> canonical_values_;
+  std::vector<const EnumValueDescriptor*> canonical_values_;
 
   struct Alias {
     const EnumValueDescriptor* value;
     const EnumValueDescriptor* canonical_value;
   };
-  vector<Alias> aliases_;
+  std::vector<Alias> aliases_;
 
   bool immutable_api_;
 
diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
index 558da96..0686ea0 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -58,7 +58,7 @@
                       int builderBitIndex,
                       const FieldGeneratorInfo* info,
                       ClassNameResolver* name_resolver,
-                      map<string, string>* variables) {
+                      std::map<string, string>* variables) {
   SetCommonFieldVariables(descriptor, info, variables);
 
   (*variables)["type"] =
@@ -68,21 +68,20 @@
   (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
   (*variables)["default_number"] = SimpleItoa(
       descriptor->default_value_enum()->number());
-  if (descriptor->is_packed()) {
-    (*variables)["tag"] = SimpleItoa(internal::WireFormatLite::MakeTag(
-        descriptor->number(),
-        internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
-  } else {
-    (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
-  }
+  (*variables)["tag"] =
+      SimpleItoa(static_cast<int32>(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();" : "";
+  (*variables)["on_changed"] = "onChanged();";
+  // Use deprecated valueOf() method to be compatible with old generated code
+  // for v2.5.0/v2.6.1.
+  // TODO(xiaofeng): Use "forNumber" when we no longer support compatibility
+  // with v2.5.0/v2.6.1, and remove the @SuppressWarnings annotations.
+  (*variables)["for_number"] = "valueOf";
 
   if (SupportFieldPresence(descriptor->file())) {
     // For singular messages and builders, one bit is used for the hasField bit.
@@ -184,23 +183,27 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
       "  return $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
-    "  $type$ result = $type$.valueOf($name$_);\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+    "  @SuppressWarnings(\"deprecation\")\n"
+    "  $type$ result = $type$.$for_number$($name$_);\n"
     "  return result == null ? $unknown$ : result;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableEnumFieldGenerator::
@@ -210,33 +213,39 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_builder$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
       "  return $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+      "$deprecation$public Builder "
+      "${$set$capitalized_name$Value$}$(int value) {\n"
       "  $name$_ = value;\n"
       "  $on_changed$\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
-    "  $type$ result = $type$.valueOf($name$_);\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+    "  @SuppressWarnings(\"deprecation\")\n"
+    "  $type$ result = $type$.$for_number$($name$_);\n"
     "  return result == null ? $unknown$ : result;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$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"
@@ -245,14 +254,16 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+    printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  $clear_has_field_bit_builder$\n"
     "  $name$_ = $default_number$;\n"
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableEnumFieldGenerator::
@@ -311,13 +322,10 @@
   } else {
     printer->Print(variables_,
       "int rawValue = input.readEnum();\n"
-      "$type$ value = $type$.valueOf(rawValue);\n"
-      "if (value == null) {\n");
-    if (PreserveUnknownFields(descriptor_->containing_type())) {
-      printer->Print(variables_,
-        "  unknownFields.mergeVarintField($number$, rawValue);\n");
-    }
-    printer->Print(variables_,
+    "  @SuppressWarnings(\"deprecation\")\n"
+      "$type$ value = $type$.$for_number$(rawValue);\n"
+      "if (value == null) {\n"
+      "  unknownFields.mergeVarintField($number$, rawValue);\n"
       "} else {\n"
       "  $set_has_field_bit_message$\n"
       "  $name$_ = rawValue;\n"
@@ -387,29 +395,34 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $has_oneof_case_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
       "  if ($has_oneof_case_message$) {\n"
       "    return (java.lang.Integer) $oneof_name$_;\n"
       "  }\n"
       "  return $default_number$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
-    "    $type$ result =  $type$.valueOf((java.lang.Integer) $oneof_name$_);\n"
+    "    @SuppressWarnings(\"deprecation\")\n"
+    "    $type$ result = $type$.$for_number$(\n"
+    "        (java.lang.Integer) $oneof_name$_);\n"
     "    return result == null ? $unknown$ : result;\n"
     "  }\n"
     "  return $default$;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableEnumOneofFieldGenerator::
@@ -417,40 +430,47 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $has_oneof_case_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
       "  if ($has_oneof_case_message$) {\n"
       "    return ((java.lang.Integer) $oneof_name$_).intValue();\n"
       "  }\n"
       "  return $default_number$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+      "$deprecation$public Builder "
+      "${$set$capitalized_name$Value$}$(int value) {\n"
       "  $set_oneof_case_message$;\n"
       "  $oneof_name$_ = value;\n"
       "  $on_changed$\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
-    "    $type$ result =  $type$.valueOf((java.lang.Integer) $oneof_name$_);\n"
+    "    @SuppressWarnings(\"deprecation\")\n"
+    "    $type$ result = $type$.$for_number$(\n"
+    "        (java.lang.Integer) $oneof_name$_);\n"
     "    return result == null ? $unknown$ : result;\n"
     "  }\n"
     "  return $default$;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$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"
@@ -459,9 +479,10 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "    $clear_oneof_case_message$;\n"
     "    $oneof_name$_ = null;\n"
@@ -469,6 +490,7 @@
     "  }\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableEnumOneofFieldGenerator::
@@ -500,13 +522,10 @@
   } else {
     printer->Print(variables_,
       "int rawValue = input.readEnum();\n"
-      "$type$ value = $type$.valueOf(rawValue);\n"
-      "if (value == null) {\n");
-    if (PreserveUnknownFields(descriptor_->containing_type())) {
-      printer->Print(variables_,
-        "  unknownFields.mergeVarintField($number$, rawValue);\n");
-    }
-    printer->Print(variables_,
+      "@SuppressWarnings(\"deprecation\")\n"
+      "$type$ value = $type$.$for_number$(rawValue);\n"
+      "if (value == null) {\n"
+      "  unknownFields.mergeVarintField($number$, rawValue);\n"
       "} else {\n"
       "  $set_oneof_case_message$;\n"
       "  $oneof_name$_ = rawValue;\n"
@@ -613,43 +632,49 @@
     "        new com.google.protobuf.Internal.ListAdapter.Converter<\n"
     "            java.lang.Integer, $type$>() {\n"
     "          public $type$ convert(java.lang.Integer from) {\n"
-    "            $type$ result = $type$.valueOf(from);\n"
+    "            @SuppressWarnings(\"deprecation\")\n"
+    "            $type$ result = $type$.$for_number$(from);\n"
     "            return result == null ? $unknown$ : result;\n"
     "          }\n"
     "        };\n");
   PrintExtraFieldInfo(variables_, printer);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "$deprecation$public java.util.List<$type$> "
+    "${$get$capitalized_name$List$}$() {\n"
     "  return new com.google.protobuf.Internal.ListAdapter<\n"
     "      java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_converter_.convert($name$_.get(index));\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
       "$deprecation$public java.util.List<java.lang.Integer>\n"
-      "get$capitalized_name$ValueList() {\n"
+      "${$get$capitalized_name$ValueList$}$() {\n"
       "  return $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$(int index) {\n"
       "  return $name$_.get(index);\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
-  if (descriptor_->is_packed() &&
-      HasGeneratedMethods(descriptor_->containing_type())) {
+  if (descriptor_->is_packed()) {
     printer->Print(variables_,
       "private int $name$MemoizedSerializedSize;\n");
   }
@@ -683,23 +708,27 @@
     //   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.
-    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "$deprecation$public java.util.List<$type$> "
+    "${$get$capitalized_name$List$}$() {\n"
     "  return new com.google.protobuf.Internal.ListAdapter<\n"
     "      java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_converter_.convert($name$_.get(index));\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, $type$ value) {\n"
     "  if (value == null) {\n"
     "    throw new NullPointerException();\n"
@@ -709,9 +738,10 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$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"
@@ -720,9 +750,10 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
     "    java.lang.Iterable<? extends $type$> values) {\n"
     "  ensure$capitalized_name$IsMutable();\n"
     "  for ($type$ value : values) {\n"
@@ -731,47 +762,54 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\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");
+  printer->Annotate("{", "}", descriptor_);
 
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
       "$deprecation$public java.util.List<java.lang.Integer>\n"
-      "get$capitalized_name$ValueList() {\n"
+      "${$get$capitalized_name$ValueList$}$() {\n"
       "  return java.util.Collections.unmodifiableList($name$_);\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$(int index) {\n"
       "  return $name$_.get(index);\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder set$capitalized_name$Value(\n"
+      "$deprecation$public Builder ${$set$capitalized_name$Value$}$(\n"
       "    int index, int value) {\n"
       "  ensure$capitalized_name$IsMutable();\n"
       "  $name$_.set(index, value);\n"
       "  $on_changed$\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder add$capitalized_name$Value(int value) {\n"
+      "$deprecation$public Builder "
+      "${$add$capitalized_name$Value$}$(int value) {\n"
       "  ensure$capitalized_name$IsMutable();\n"
       "  $name$_.add(value);\n"
       "  $on_changed$\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder addAll$capitalized_name$Value(\n"
+      "$deprecation$public Builder ${$addAll$capitalized_name$Value$}$(\n"
       "    java.lang.Iterable<java.lang.Integer> values) {\n"
       "  ensure$capitalized_name$IsMutable();\n"
       "  for (int value : values) {\n"
@@ -780,6 +818,7 @@
       "  $on_changed$\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 }
 
@@ -846,13 +885,10 @@
   } else {
     printer->Print(variables_,
       "int rawValue = input.readEnum();\n"
-      "$type$ value = $type$.valueOf(rawValue);\n"
-        "if (value == null) {\n");
-    if (PreserveUnknownFields(descriptor_->containing_type())) {
-      printer->Print(variables_,
-        "  unknownFields.mergeVarintField($number$, rawValue);\n");
-    }
-    printer->Print(variables_,
+      "@SuppressWarnings(\"deprecation\")\n"
+      "$type$ value = $type$.$for_number$(rawValue);\n"
+      "if (value == null) {\n"
+      "  unknownFields.mergeVarintField($number$, rawValue);\n"
       "} else {\n"
       "  if (!$get_mutable_bit_parser$) {\n"
       "    $name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
@@ -894,8 +930,8 @@
   if (descriptor_->is_packed()) {
     printer->Print(variables_,
       "if (get$capitalized_name$List().size() > 0) {\n"
-      "  output.writeRawVarint32($tag$);\n"
-      "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+      "  output.writeUInt32NoTag($tag$);\n"
+      "  output.writeUInt32NoTag($name$MemoizedSerializedSize);\n"
       "}\n"
       "for (int i = 0; i < $name$_.size(); i++) {\n"
       "  output.writeEnumNoTag($name$_.get(i));\n"
@@ -927,7 +963,7 @@
       "if (!get$capitalized_name$List().isEmpty()) {"
       "  size += $tag_size$;\n"
       "  size += com.google.protobuf.CodedOutputStream\n"
-      "    .computeRawVarint32Size(dataSize);\n"
+      "    .computeUInt32SizeNoTag(dataSize);\n"
       "}");
   } else {
     printer->Print(variables_,
diff --git a/src/google/protobuf/compiler/java/java_enum_field.h b/src/google/protobuf/compiler/java/java_enum_field.h
index b8ff734..924ff28 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.h
+++ b/src/google/protobuf/compiler/java/java_enum_field.h
@@ -82,7 +82,7 @@
 
  protected:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   const int messageBitIndex_;
   const int builderBitIndex_;
   Context* context_;
@@ -143,7 +143,7 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   const int messageBitIndex_;
   const int builderBitIndex_;
   Context* context_;
diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
index e3e87c5..f1fe71b 100644
--- a/src/google/protobuf/compiler/java/java_enum_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
@@ -58,7 +58,7 @@
                       int builderBitIndex,
                       const FieldGeneratorInfo* info,
                       ClassNameResolver* name_resolver,
-                      map<string, string>* variables) {
+                      std::map<string, string>* variables) {
   SetCommonFieldVariables(descriptor, info, variables);
 
   (*variables)["type"] =
@@ -68,15 +68,15 @@
   (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
   (*variables)["default_number"] = SimpleItoa(
       descriptor->default_value_enum()->number());
-  (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
+  (*variables)["tag"] =
+      SimpleItoa(static_cast<int32>(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();" : "";
+  (*variables)["required"] = descriptor->is_required() ? "true" : "false";
 
   if (SupportFieldPresence(descriptor->file())) {
     // For singular messages and builders, one bit is used for the hasField bit.
@@ -165,23 +165,29 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
       "  return $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
-    "  $type$ result = $type$.valueOf($name$_);\n"
+    "@java.lang.Override\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
+    "  $type$ result = $type$.forNumber($name$_);\n"
     "  return result == null ? $unknown$ : result;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Generate private setters for the builder to proxy into.
   if (SupportUnknownEnumValue(descriptor_->file())) {
@@ -214,43 +220,53 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return instance.has$capitalized_name$();\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
       "  return instance.get$capitalized_name$Value();\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+      "$deprecation$public Builder "
+      "${$set$capitalized_name$Value$}$(int value) {\n"
       "  copyOnWrite();\n"
-      "  instance.set$capitalized_name$Value(int value);\n"
+      "  instance.set$capitalized_name$Value(value);\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  return instance.get$capitalized_name$();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableEnumFieldLiteGenerator::
@@ -260,21 +276,21 @@
 
 void ImmutableEnumFieldLiteGenerator::
 GenerateInitializationCode(io::Printer* printer) const {
-  printer->Print(variables_, "$name$_ = $default_number$;\n");
+  if (!IsDefaultValueJavaDefault(descriptor_)) {
+    printer->Print(variables_, "$name$_ = $default_number$;\n");
+  }
 }
 
 void ImmutableEnumFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
+GenerateVisitCode(io::Printer* printer) const {
   if (SupportFieldPresence(descriptor_->file())) {
     printer->Print(variables_,
-      "if (other.has$capitalized_name$()) {\n"
-      "  set$capitalized_name$(other.get$capitalized_name$());\n"
-      "}\n");
+      "$name$_ = visitor.visitInt(has$capitalized_name$(), $name$_,\n"
+      "    other.has$capitalized_name$(), other.$name$_);\n");
   } else if (SupportUnknownEnumValue(descriptor_->file())) {
     printer->Print(variables_,
-      "if (other.$name$_ != $default_number$) {\n"
-      "  set$capitalized_name$Value(other.get$capitalized_name$Value());\n"
-      "}\n");
+      "$name$_ = visitor.visitInt($name$_ != $default_number$, $name$_,"
+      "    other.$name$_ != $default_number$, other.$name$_);\n");
   } else {
     GOOGLE_LOG(FATAL) << "Can't reach here.";
   }
@@ -295,13 +311,9 @@
   } else {
     printer->Print(variables_,
       "int rawValue = input.readEnum();\n"
-      "$type$ value = $type$.valueOf(rawValue);\n"
-      "if (value == null) {\n");
-    if (PreserveUnknownFields(descriptor_->containing_type())) {
-      printer->Print(variables_,
-        "  super.mergeVarintField($number$, rawValue);\n");
-    }
-    printer->Print(variables_,
+      "$type$ value = $type$.forNumber(rawValue);\n"
+      "if (value == null) {\n"
+      "  super.mergeVarintField($number$, rawValue);\n"
       "} else {\n"
       "  $set_has_field_bit_message$\n"
       "  $name$_ = rawValue;\n"
@@ -314,6 +326,7 @@
   // noop for enums
 }
 
+
 void ImmutableEnumFieldLiteGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
   printer->Print(variables_,
@@ -371,29 +384,35 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $has_oneof_case_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
       "  if ($has_oneof_case_message$) {\n"
       "    return (java.lang.Integer) $oneof_name$_;\n"
       "  }\n"
       "  return $default_number$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
-    "    $type$ result =  $type$.valueOf((java.lang.Integer) $oneof_name$_);\n"
+    "    $type$ result = $type$.forNumber((java.lang.Integer) $oneof_name$_);\n"
     "    return result == null ? $unknown$ : result;\n"
     "  }\n"
     "  return $default$;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Generate private setters for the builder to proxy into.
   if (SupportUnknownEnumValue(descriptor_->file())) {
@@ -423,59 +442,66 @@
     "}\n");
 }
 
+
 void ImmutableEnumOneofFieldLiteGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return instance.has$capitalized_name$();\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
       "  return instance.get$capitalized_name$Value();\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+      "$deprecation$public Builder "
+      "${$set$capitalized_name$Value$}$(int value) {\n"
       "  copyOnWrite();\n"
       "  instance.set$capitalized_name$Value(value);\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  return instance.get$capitalized_name$();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableEnumOneofFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
-  if (SupportUnknownEnumValue(descriptor_->file())) {
-    printer->Print(variables_,
-      "set$capitalized_name$Value(other.get$capitalized_name$Value());\n");
-  } else {
-    printer->Print(variables_,
-      "set$capitalized_name$(other.get$capitalized_name$());\n");
-  }
+GenerateVisitCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$oneof_name$_ = visitor.visitOneofInt(\n"
+    "   $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n");
 }
 
 void ImmutableEnumOneofFieldLiteGenerator::
@@ -488,13 +514,9 @@
   } else {
     printer->Print(variables_,
       "int rawValue = input.readEnum();\n"
-      "$type$ value = $type$.valueOf(rawValue);\n"
-      "if (value == null) {\n");
-    if (PreserveUnknownFields(descriptor_->containing_type())) {
-      printer->Print(variables_,
-        "  super.mergeVarintField($number$, rawValue);\n");
-    }
-    printer->Print(variables_,
+      "$type$ value = $type$.forNumber(rawValue);\n"
+      "if (value == null) {\n"
+      "  super.mergeVarintField($number$, rawValue);\n"
       "} else {\n"
       "  $set_oneof_case_message$;\n"
       "  $oneof_name$_ = rawValue;\n"
@@ -601,44 +623,56 @@
     "    java.lang.Integer, $type$> $name$_converter_ =\n"
     "        new com.google.protobuf.Internal.ListAdapter.Converter<\n"
     "            java.lang.Integer, $type$>() {\n"
+    "          @java.lang.Override\n"
     "          public $type$ convert(java.lang.Integer from) {\n"
-    "            $type$ result = $type$.valueOf(from);\n"
+    "            $type$ result = $type$.forNumber(from);\n"
     "            return result == null ? $unknown$ : result;\n"
     "          }\n"
     "        };\n");
   PrintExtraFieldInfo(variables_, printer);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public java.util.List<$type$> "
+    "${$get$capitalized_name$List$}$() {\n"
     "  return new com.google.protobuf.Internal.ListAdapter<\n"
     "      java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_converter_.convert($name$_.getInt(index));\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
+      "@java.lang.Override\n"
       "$deprecation$public java.util.List<java.lang.Integer>\n"
-      "get$capitalized_name$ValueList() {\n"
+      "${$get$capitalized_name$ValueList$}$() {\n"
       "  return $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$(int index) {\n"
       "  return $name$_.getInt(index);\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
-  if (descriptor_->options().packed() &&
-      HasGeneratedMethods(descriptor_->containing_type())) {
+  if (descriptor_->is_packed() &&
+      context_->HasGeneratedMethods(descriptor_->containing_type())) {
     printer->Print(variables_,
       "private int $name$MemoizedSerializedSize;\n");
   }
@@ -647,7 +681,8 @@
   printer->Print(variables_,
     "private void ensure$capitalized_name$IsMutable() {\n"
     "  if (!$is_mutable$) {\n"
-    "    $name$_ = newIntList($name$_);\n"
+    "    $name$_ =\n"
+    "        com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
     "  }\n"
     "}\n");
   WriteFieldDocComment(printer, descriptor_);
@@ -710,89 +745,109 @@
   }
 }
 
+
 void RepeatedImmutableEnumFieldLiteGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public java.util.List<$type$> "
+    "${$get$capitalized_name$List$}$() {\n"
     "  return instance.get$capitalized_name$List();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return instance.get$capitalized_name$Count();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return instance.get$capitalized_name$(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, $type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(index, value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.add$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
     "    java.lang.Iterable<? extends $type$> values) {\n"
     "  copyOnWrite();\n"
     "  instance.addAll$capitalized_name$(values);"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
+      "@java.lang.Override\n"
       "$deprecation$public java.util.List<java.lang.Integer>\n"
-      "get$capitalized_name$ValueList() {\n"
+      "${$get$capitalized_name$ValueList$}$() {\n"
       "  return java.util.Collections.unmodifiableList(\n"
       "      instance.get$capitalized_name$ValueList());\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$(int index) {\n"
       "  return instance.get$capitalized_name$Value(index);\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder set$capitalized_name$Value(\n"
+      "$deprecation$public Builder ${$set$capitalized_name$Value$}$(\n"
       "    int index, int value) {\n"
       "  copyOnWrite();\n"
       "  instance.set$capitalized_name$Value(index, value);\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder add$capitalized_name$Value(int value) {\n"
+      "$deprecation$public Builder "
+      "${$add$capitalized_name$Value$}$(int value) {\n"
       "  instance.add$capitalized_name$Value(value);\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder addAll$capitalized_name$Value(\n"
+      "$deprecation$public Builder ${$addAll$capitalized_name$Value$}$(\n"
       "    java.lang.Iterable<java.lang.Integer> values) {\n"
       "  copyOnWrite();\n"
       "  instance.addAll$capitalized_name$Value(values);\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 }
 
@@ -807,22 +862,9 @@
 }
 
 void RepeatedImmutableEnumFieldLiteGenerator::
-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.
+GenerateVisitCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (!other.$name$_.isEmpty()) {\n"
-    "  if ($name$_.isEmpty()) {\n"
-    "    $name$_ = other.$name$_;\n"
-    "  } else {\n"
-    "    ensure$capitalized_name$IsMutable();\n"
-    "    $name$_.addAll(other.$name$_);\n"
-    "  }\n"
-    "  $on_changed$\n"
-    "}\n");
+    "$name$_= visitor.visitIntList($name$_, other.$name$_);\n");
 }
 
 void RepeatedImmutableEnumFieldLiteGenerator::
@@ -834,27 +876,23 @@
 void RepeatedImmutableEnumFieldLiteGenerator::
 GenerateParsingCode(io::Printer* printer) const {
   // Read and store the enum
+  printer->Print(variables_,
+    "if (!$is_mutable$) {\n"
+    "  $name$_ =\n"
+    "      com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+    "}\n");
+
   if (SupportUnknownEnumValue(descriptor_->file())) {
     printer->Print(variables_,
-      "int rawValue = input.readEnum();\n"
-      "if (!$is_mutable$) {\n"
-      "  $name$_ = newIntList();\n"
-      "}\n"
-      "$name$_.addInt(rawValue);\n");
+      "$name$_.addInt(input.readEnum());\n");
   } else {
     printer->Print(variables_,
       "int rawValue = input.readEnum();\n"
-      "$type$ value = $type$.valueOf(rawValue);\n"
-        "if (value == null) {\n");
-    if (PreserveUnknownFields(descriptor_->containing_type())) {
-      printer->Print(variables_,
-        "  super.mergeVarintField($number$, rawValue);\n");
-    }
-    printer->Print(variables_,
+      "$type$ value = $type$.forNumber(rawValue);\n"
+      "if (value == null) {\n"
+      // We store the unknown value in unknown fields.
+      "  super.mergeVarintField($number$, rawValue);\n"
       "} else {\n"
-      "  if (!$is_mutable$) {\n"
-      "    $name$_ = newIntList();\n"
-      "  }\n"
       "  $name$_.addInt(rawValue);\n"
       "}\n");
   }
@@ -862,7 +900,11 @@
 
 void RepeatedImmutableEnumFieldLiteGenerator::
 GenerateParsingCodeFromPacked(io::Printer* printer) const {
-  // Wrap GenerateParsingCode's contents with a while loop.
+  printer->Print(variables_,
+    "if (!$is_mutable$) {\n"
+    "  $name$_ =\n"
+    "      com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
+    "}\n");
 
   printer->Print(variables_,
     "int length = input.readRawVarint32();\n"
@@ -870,7 +912,21 @@
     "while(input.getBytesUntilLimit() > 0) {\n");
   printer->Indent();
 
-  GenerateParsingCode(printer);
+  // Read and store the enum
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(variables_,
+      "$name$_.addInt(input.readEnum());\n");
+  } else {
+    printer->Print(variables_,
+      "int rawValue = input.readEnum();\n"
+      "$type$ value = $type$.forNumber(rawValue);\n"
+      "if (value == null) {\n"
+      // We store the unknown value in unknown fields.
+      "  super.mergeVarintField($number$, rawValue);\n"
+      "} else {\n"
+      "  $name$_.addInt(rawValue);\n"
+      "}\n");
+  }
 
   printer->Outdent();
   printer->Print(variables_,
@@ -888,11 +944,11 @@
 
 void RepeatedImmutableEnumFieldLiteGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
-  if (descriptor_->options().packed()) {
+  if (descriptor_->is_packed()) {
     printer->Print(variables_,
       "if (get$capitalized_name$List().size() > 0) {\n"
-      "  output.writeRawVarint32($tag$);\n"
-      "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+      "  output.writeUInt32NoTag($tag$);\n"
+      "  output.writeUInt32NoTag($name$MemoizedSerializedSize);\n"
       "}\n"
       "for (int i = 0; i < $name$_.size(); i++) {\n"
       "  output.writeEnumNoTag($name$_.getInt(i));\n"
@@ -919,12 +975,12 @@
     "}\n");
   printer->Print(
     "size += dataSize;\n");
-  if (descriptor_->options().packed()) {
+  if (descriptor_->is_packed()) {
     printer->Print(variables_,
       "if (!get$capitalized_name$List().isEmpty()) {"
       "  size += $tag_size$;\n"
       "  size += com.google.protobuf.CodedOutputStream\n"
-      "    .computeRawVarint32Size(dataSize);\n"
+      "    .computeUInt32SizeNoTag(dataSize);\n"
       "}");
   } else {
     printer->Print(variables_,
@@ -932,7 +988,7 @@
   }
 
   // cache the data size for packed fields.
-  if (descriptor_->options().packed()) {
+  if (descriptor_->is_packed()) {
     printer->Print(variables_,
       "$name$MemoizedSerializedSize = dataSize;\n");
   }
diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.h b/src/google/protobuf/compiler/java/java_enum_field_lite.h
index 2c41c3e..fa00472 100644
--- a/src/google/protobuf/compiler/java/java_enum_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.h
@@ -67,7 +67,7 @@
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
   void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateParsingDoneCode(io::Printer* printer) const;
@@ -81,7 +81,7 @@
 
  protected:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   const int messageBitIndex_;
   const int builderBitIndex_;
   Context* context_;
@@ -101,7 +101,7 @@
 
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
@@ -127,7 +127,7 @@
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
   void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateParsingCodeFromPacked(io::Printer* printer) const;
@@ -142,7 +142,7 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   const int messageBitIndex_;
   const int builderBitIndex_;
   Context* context_;
diff --git a/src/google/protobuf/compiler/java/java_enum_lite.cc b/src/google/protobuf/compiler/java/java_enum_lite.cc
index ed415ee..806008e 100644
--- a/src/google/protobuf/compiler/java/java_enum_lite.cc
+++ b/src/google/protobuf/compiler/java/java_enum_lite.cc
@@ -36,12 +36,12 @@
 #include <string>
 
 #include <google/protobuf/compiler/java/java_context.h>
-#include <google/protobuf/compiler/java/java_enum_lite.h>
 #include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_enum_lite.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
-#include <google/protobuf/io/printer.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
 #include <google/protobuf/stubs/strutil.h>
 
 namespace google {
@@ -49,22 +49,12 @@
 namespace compiler {
 namespace java {
 
-namespace {
-bool EnumHasCustomOptions(const EnumDescriptor* descriptor) {
-  if (descriptor->options().unknown_fields().field_count() > 0) return true;
-  for (int i = 0; i < descriptor->value_count(); ++i) {
-    const EnumValueDescriptor* value = descriptor->value(i);
-    if (value->options().unknown_fields().field_count() > 0) return true;
-  }
-  return false;
-}
-}  // namespace
-
 EnumLiteGenerator::EnumLiteGenerator(const EnumDescriptor* descriptor,
-                             bool immutable_api,
-                             Context* context)
-  : descriptor_(descriptor), immutable_api_(immutable_api),
-    name_resolver_(context->GetNameResolver())  {
+                                     bool immutable_api, Context* context)
+    : descriptor_(descriptor),
+      immutable_api_(immutable_api),
+      context_(context),
+      name_resolver_(context->GetNameResolver()) {
   for (int i = 0; i < descriptor_->value_count(); i++) {
     const EnumValueDescriptor* value = descriptor_->value(i);
     const EnumValueDescriptor* canonical_value =
@@ -85,14 +75,16 @@
 
 void EnumLiteGenerator::Generate(io::Printer* printer) {
   WriteEnumDocComment(printer, descriptor_);
+  MaybePrintGeneratedAnnotation(context_, printer, descriptor_, immutable_api_);
   printer->Print(
-    "public enum $classname$\n"
-    "    implements com.google.protobuf.Internal.EnumLite {\n",
-    "classname", descriptor_->name());
+      "public enum $classname$\n"
+      "    implements com.google.protobuf.Internal.EnumLite {\n",
+      "classname", descriptor_->name());
+  printer->Annotate("classname", descriptor_);
   printer->Indent();
 
   for (int i = 0; i < canonical_values_.size(); i++) {
-    map<string, string> vars;
+    std::map<string, string> vars;
     vars["name"] = canonical_values_[i]->name();
     vars["number"] = SimpleItoa(canonical_values_[i]->number());
     WriteEnumValueDocComment(printer, canonical_values_[i]);
@@ -101,10 +93,12 @@
     }
     printer->Print(vars,
       "$name$($number$),\n");
+    printer->Annotate("name", canonical_values_[i]);
   }
 
   if (SupportUnknownEnumValue(descriptor_->file())) {
-    printer->Print("UNRECOGNIZED(-1),\n");
+    printer->Print("${$UNRECOGNIZED$}$(-1),\n", "{", "", "}", "");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   printer->Print(
@@ -114,36 +108,57 @@
   // -----------------------------------------------------------------
 
   for (int i = 0; i < aliases_.size(); i++) {
-    map<string, string> vars;
+    std::map<string, string> vars;
     vars["classname"] = descriptor_->name();
     vars["name"] = aliases_[i].value->name();
     vars["canonical_name"] = aliases_[i].canonical_value->name();
     WriteEnumValueDocComment(printer, aliases_[i].value);
     printer->Print(vars,
       "public static final $classname$ $name$ = $canonical_name$;\n");
+    printer->Annotate("name", aliases_[i].value);
   }
 
   for (int i = 0; i < descriptor_->value_count(); i++) {
-    map<string, string> vars;
+    std::map<string, string> vars;
     vars["name"] = descriptor_->value(i)->name();
     vars["number"] = SimpleItoa(descriptor_->value(i)->number());
+    vars["{"] = "";
+    vars["}"] = "";
     WriteEnumValueDocComment(printer, descriptor_->value(i));
     printer->Print(vars,
-      "public static final int $name$_VALUE = $number$;\n");
+      "public static final int ${$$name$_VALUE$}$ = $number$;\n");
+    printer->Annotate("{", "}", descriptor_->value(i));
   }
   printer->Print("\n");
 
   // -----------------------------------------------------------------
 
   printer->Print(
-    "\n"
-    "public final int getNumber() {\n"
-    "  return value;\n"
-    "}\n"
-    "\n"
-    "public static $classname$ valueOf(int value) {\n"
-    "  switch (value) {\n",
-    "classname", descriptor_->name());
+      "\n"
+      "@java.lang.Override\n"
+      "public final int getNumber() {\n");
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(
+        "  if (this == UNRECOGNIZED) {\n"
+        "    throw new java.lang.IllegalArgumentException(\n"
+        "        \"Can't get the number of an unknown enum value.\");\n"
+        "  }\n");
+  }
+  printer->Print(
+      "  return value;\n"
+      "}\n"
+      "\n"
+      "/**\n"
+      " * @deprecated Use {@link #forNumber(int)} instead.\n"
+      " */\n"
+      "@java.lang.Deprecated\n"
+      "public static $classname$ valueOf(int value) {\n"
+      "  return forNumber(value);\n"
+      "}\n"
+      "\n"
+      "public static $classname$ forNumber(int value) {\n"
+      "  switch (value) {\n",
+      "classname", descriptor_->name());
   printer->Indent();
   printer->Indent();
 
@@ -168,8 +183,9 @@
     "private static final com.google.protobuf.Internal.EnumLiteMap<\n"
     "    $classname$> internalValueMap =\n"
     "      new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
+    "        @java.lang.Override\n"
     "        public $classname$ findValueByNumber(int number) {\n"
-    "          return $classname$.valueOf(number);\n"
+    "          return $classname$.forNumber(number);\n"
     "        }\n"
     "      };\n"
     "\n",
diff --git a/src/google/protobuf/compiler/java/java_enum_lite.h b/src/google/protobuf/compiler/java/java_enum_lite.h
index ee2f5f7..b7be912 100644
--- a/src/google/protobuf/compiler/java/java_enum_lite.h
+++ b/src/google/protobuf/compiler/java/java_enum_lite.h
@@ -58,9 +58,8 @@
 
 class EnumLiteGenerator {
  public:
-  explicit EnumLiteGenerator(const EnumDescriptor* descriptor,
-                         bool immutable_api,
-                         Context* context);
+  EnumLiteGenerator(const EnumDescriptor* descriptor, bool immutable_api,
+                    Context* context);
   ~EnumLiteGenerator();
 
   void Generate(io::Printer* printer);
@@ -73,13 +72,13 @@
   // considered equivalent.  We treat the first defined constant for any
   // given numeric value as "canonical" and the rest as aliases of that
   // canonical value.
-  vector<const EnumValueDescriptor*> canonical_values_;
+  std::vector<const EnumValueDescriptor*> canonical_values_;
 
   struct Alias {
     const EnumValueDescriptor* value;
     const EnumValueDescriptor* canonical_value;
   };
-  vector<Alias> aliases_;
+  std::vector<Alias> aliases_;
 
   bool immutable_api_;
 
diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc
index 4db7085..3eb1370 100644
--- a/src/google/protobuf/compiler/java/java_extension.cc
+++ b/src/google/protobuf/compiler/java/java_extension.cc
@@ -61,12 +61,10 @@
 ImmutableExtensionGenerator::~ImmutableExtensionGenerator() {}
 
 // Initializes the vars referenced in the generated code templates.
-void ExtensionGenerator::InitTemplateVars(const FieldDescriptor* descriptor,
-                                          const string& scope,
-                                          bool immutable,
-                                          ClassNameResolver* name_resolver,
-                                          map<string, string>* vars_pointer) {
-  map<string, string> &vars = *vars_pointer;
+void ExtensionGenerator::InitTemplateVars(
+    const FieldDescriptor* descriptor, const string& scope, bool immutable,
+    ClassNameResolver* name_resolver, std::map<string, string>* vars_pointer) {
+  std::map<string, string> &vars = *vars_pointer;
   vars["scope"] = scope;
   vars["name"] = UnderscoresToCamelCase(descriptor);
   vars["containing_type"] =
@@ -77,7 +75,7 @@
   vars["default"] = descriptor->is_repeated() ?
       "" : DefaultValue(descriptor, immutable, name_resolver);
   vars["type_constant"] = FieldTypeName(GetType(descriptor));
-  vars["packed"] = descriptor->options().packed() ? "true" : "false";
+  vars["packed"] = descriptor->is_packed() ? "true" : "false";
   vars["enum_map"] = "null";
   vars["prototype"] = "null";
 
@@ -110,7 +108,7 @@
 }
 
 void ImmutableExtensionGenerator::Generate(io::Printer* printer) {
-  map<string, string> vars;
+  std::map<string, string> vars;
   const bool kUseImmutableNames = true;
   InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_,
                    &vars);
@@ -118,75 +116,39 @@
       "public static final int $constant_name$ = $number$;\n");
 
   WriteFieldDocComment(printer, descriptor_);
-  if (HasDescriptorMethods(descriptor_->file())) {
-    // 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 {
-      // 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");
-    }
+  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 {
-    // 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"
-          "      $singular_type$.class);\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"
-          "      $singular_type$.class);\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");
   }
+  printer->Annotate("name", descriptor_);
 }
 
 int ImmutableExtensionGenerator::GenerateNonNestedInitializationCode(
     io::Printer* printer) {
   int bytecode_estimate = 0;
-  if (descriptor_->extension_scope() == NULL &&
-      HasDescriptorMethods(descriptor_->file())) {
-    // Only applies to non-nested, non-lite extensions.
+  if (descriptor_->extension_scope() == NULL) {
+    // Only applies to non-nested extensions.
     printer->Print(
         "$name$.internalInit(descriptor.getExtensions().get($index$));\n",
         "name", UnderscoresToCamelCase(descriptor_),
diff --git a/src/google/protobuf/compiler/java/java_extension.h b/src/google/protobuf/compiler/java/java_extension.h
index bdd4226..fb8d520 100644
--- a/src/google/protobuf/compiler/java/java_extension.h
+++ b/src/google/protobuf/compiler/java/java_extension.h
@@ -79,7 +79,7 @@
                                const string& scope,
                                bool immutable,
                                ClassNameResolver* name_resolver,
-                               map<string, string>* vars_pointer);
+                               std::map<string, string>* vars_pointer);
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
diff --git a/src/google/protobuf/compiler/java/java_extension_lite.cc b/src/google/protobuf/compiler/java/java_extension_lite.cc
index e69de29..70ce8e7 100644
--- a/src/google/protobuf/compiler/java/java_extension_lite.cc
+++ b/src/google/protobuf/compiler/java/java_extension_lite.cc
@@ -0,0 +1,119 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/compiler/java/java_extension_lite.h>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+ImmutableExtensionLiteGenerator::ImmutableExtensionLiteGenerator(
+    const FieldDescriptor* descriptor, Context* context)
+  : descriptor_(descriptor), context_(context),
+    name_resolver_(context->GetNameResolver()) {
+  if (descriptor_->extension_scope() != NULL) {
+    scope_ = name_resolver_->GetImmutableClassName(
+        descriptor_->extension_scope());
+  } else {
+    scope_ = name_resolver_->GetImmutableClassName(descriptor_->file());
+  }
+}
+
+ImmutableExtensionLiteGenerator::~ImmutableExtensionLiteGenerator() {}
+
+void ImmutableExtensionLiteGenerator::Generate(io::Printer* printer) {
+  std::map<string, string> vars;
+  const bool kUseImmutableNames = true;
+  InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_,
+                   &vars);
+  printer->Print(vars,
+      "public static final int $constant_name$ = $number$;\n");
+
+  WriteFieldDocComment(printer, descriptor_);
+  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"
+        "      $singular_type$.class);\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"
+        "      $singular_type$.class);\n");
+  }
+  printer->Annotate("name", descriptor_);
+}
+
+int ImmutableExtensionLiteGenerator::GenerateNonNestedInitializationCode(
+    io::Printer* printer) {
+  return 0;
+}
+
+int ImmutableExtensionLiteGenerator::GenerateRegistrationCode(
+    io::Printer* printer) {
+  printer->Print(
+    "registry.add($scope$.$name$);\n",
+    "scope", scope_,
+    "name", UnderscoresToCamelCase(descriptor_));
+  return 7;
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/java/java_extension_lite.h b/src/google/protobuf/compiler/java/java_extension_lite.h
index e69de29..4cd49bd 100644
--- a/src/google/protobuf/compiler/java/java_extension_lite.h
+++ b/src/google/protobuf/compiler/java/java_extension_lite.h
@@ -0,0 +1,76 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_LITE_H__
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_extension.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+// Generates code for a lite extension, which may be within the scope of some
+// message or may be at file scope.  This is much simpler than FieldGenerator
+// since extensions are just simple identifiers with interesting types.
+class ImmutableExtensionLiteGenerator : public ExtensionGenerator {
+ public:
+  explicit ImmutableExtensionLiteGenerator(const FieldDescriptor* descriptor,
+                                           Context* context);
+  virtual ~ImmutableExtensionLiteGenerator();
+
+  virtual void Generate(io::Printer* printer);
+
+  // Returns an estimate of the number of bytes the printed code will compile to
+  virtual int GenerateNonNestedInitializationCode(io::Printer* printer);
+
+  // Returns an estimate of the number of bytes the printed code will compile to
+  virtual int GenerateRegistrationCode(io::Printer* printer);
+
+ private:
+  const FieldDescriptor* descriptor_;
+  Context* context_;
+  ClassNameResolver* name_resolver_;
+  string scope_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableExtensionLiteGenerator);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_LITE_H__
diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc
index c543476..93de022 100644
--- a/src/google/protobuf/compiler/java/java_field.cc
+++ b/src/google/protobuf/compiler/java/java_field.cc
@@ -35,9 +35,6 @@
 #include <google/protobuf/compiler/java/java_field.h>
 
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
@@ -45,8 +42,6 @@
 #include <google/protobuf/compiler/java/java_enum_field.h>
 #include <google/protobuf/compiler/java/java_enum_field_lite.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
-#include <google/protobuf/compiler/java/java_lazy_message_field.h>
-#include <google/protobuf/compiler/java/java_lazy_message_field_lite.h>
 #include <google/protobuf/compiler/java/java_map_field.h>
 #include <google/protobuf/compiler/java/java_map_field_lite.h>
 #include <google/protobuf/compiler/java/java_message_field.h>
@@ -77,13 +72,8 @@
           return new ImmutableMapFieldGenerator(
               field, messageBitIndex, builderBitIndex, context);
         } else {
-          if (IsLazy(field)) {
-            return new RepeatedImmutableLazyMessageFieldGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          } else {
-            return new RepeatedImmutableMessageFieldGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          }
+          return new RepeatedImmutableMessageFieldGenerator(
+              field, messageBitIndex, builderBitIndex, context);
         }
       case JAVATYPE_ENUM:
         return new RepeatedImmutableEnumFieldGenerator(
@@ -99,13 +89,8 @@
     if (field->containing_oneof()) {
       switch (GetJavaType(field)) {
         case JAVATYPE_MESSAGE:
-          if (IsLazy(field)) {
-            return new ImmutableLazyMessageOneofFieldGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          } else {
-            return new ImmutableMessageOneofFieldGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          }
+          return new ImmutableMessageOneofFieldGenerator(
+              field, messageBitIndex, builderBitIndex, context);
         case JAVATYPE_ENUM:
           return new ImmutableEnumOneofFieldGenerator(
               field, messageBitIndex, builderBitIndex, context);
@@ -119,13 +104,8 @@
     } else {
       switch (GetJavaType(field)) {
         case JAVATYPE_MESSAGE:
-          if (IsLazy(field)) {
-            return new ImmutableLazyMessageFieldGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          } else {
-            return new ImmutableMessageFieldGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          }
+          return new ImmutableMessageFieldGenerator(
+              field, messageBitIndex, builderBitIndex, context);
         case JAVATYPE_ENUM:
           return new ImmutableEnumFieldGenerator(
               field, messageBitIndex, builderBitIndex, context);
@@ -150,13 +130,8 @@
           return new ImmutableMapFieldLiteGenerator(
               field, messageBitIndex, builderBitIndex, context);
         } else {
-          if (IsLazy(field)) {
-            return new RepeatedImmutableLazyMessageFieldLiteGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          } else {
-            return new RepeatedImmutableMessageFieldLiteGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          }
+          return new RepeatedImmutableMessageFieldLiteGenerator(
+              field, messageBitIndex, builderBitIndex, context);
         }
       case JAVATYPE_ENUM:
         return new RepeatedImmutableEnumFieldLiteGenerator(
@@ -172,13 +147,8 @@
     if (field->containing_oneof()) {
       switch (GetJavaType(field)) {
         case JAVATYPE_MESSAGE:
-          if (IsLazy(field)) {
-            return new ImmutableLazyMessageOneofFieldLiteGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          } else {
-            return new ImmutableMessageOneofFieldLiteGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          }
+          return new ImmutableMessageOneofFieldLiteGenerator(
+              field, messageBitIndex, builderBitIndex, context);
         case JAVATYPE_ENUM:
           return new ImmutableEnumOneofFieldLiteGenerator(
               field, messageBitIndex, builderBitIndex, context);
@@ -192,13 +162,8 @@
     } else {
       switch (GetJavaType(field)) {
         case JAVATYPE_MESSAGE:
-          if (IsLazy(field)) {
-            return new ImmutableLazyMessageFieldLiteGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          } else {
-            return new ImmutableMessageFieldLiteGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          }
+          return new ImmutableMessageFieldLiteGenerator(
+              field, messageBitIndex, builderBitIndex, context);
         case JAVATYPE_ENUM:
           return new ImmutableEnumFieldLiteGenerator(
               field, messageBitIndex, builderBitIndex, context);
@@ -246,8 +211,7 @@
 FieldGeneratorMap<ImmutableFieldGenerator>::FieldGeneratorMap(
     const Descriptor* descriptor, Context* context)
     : descriptor_(descriptor),
-      field_generators_(new google::protobuf::scoped_ptr<
-          ImmutableFieldGenerator>[descriptor->field_count()]) {
+      field_generators_(descriptor->field_count()) {
 
   // Construct all the FieldGenerators and assign them bit indices for their
   // bit fields.
@@ -269,8 +233,7 @@
 FieldGeneratorMap<ImmutableFieldLiteGenerator>::FieldGeneratorMap(
     const Descriptor* descriptor, Context* context)
     : descriptor_(descriptor),
-      field_generators_(new google::protobuf::scoped_ptr<
-          ImmutableFieldLiteGenerator>[descriptor->field_count()]) {
+      field_generators_(descriptor->field_count()) {
   // Construct all the FieldGenerators and assign them bit indices for their
   // bit fields.
   int messageBitIndex = 0;
@@ -290,18 +253,25 @@
 
 void SetCommonFieldVariables(const FieldDescriptor* descriptor,
                              const FieldGeneratorInfo* info,
-                             map<string, string>* variables) {
+                             std::map<string, string>* variables) {
   (*variables)["field_name"] = descriptor->name();
   (*variables)["name"] = info->name;
+  (*variables)["classname"] = descriptor->containing_type()->name();
   (*variables)["capitalized_name"] = info->capitalized_name;
   (*variables)["disambiguated_reason"] = info->disambiguated_reason;
   (*variables)["constant_name"] = FieldConstantName(descriptor);
   (*variables)["number"] = SimpleItoa(descriptor->number());
+  // These variables are placeholders to pick out the beginning and ends of
+  // identifiers for annotations (when doing so with existing variables would
+  // be ambiguous or impossible). They should never be set to anything but the
+  // empty string.
+  (*variables)["{"] = "";
+  (*variables)["}"] = "";
 }
 
 void SetCommonOneofVariables(const FieldDescriptor* descriptor,
                              const OneofGeneratorInfo* info,
-                             map<string, string>* variables) {
+                             std::map<string, string>* variables) {
   (*variables)["oneof_name"] = info->name;
   (*variables)["oneof_capitalized_name"] = info->capitalized_name;
   (*variables)["oneof_index"] =
@@ -314,9 +284,9 @@
       "Case_ == " + SimpleItoa(descriptor->number());
 }
 
-void PrintExtraFieldInfo(const map<string, string>& variables,
+void PrintExtraFieldInfo(const std::map<string, string>& variables,
                          io::Printer* printer) {
-  const map<string, string>::const_iterator it =
+  const std::map<string, string>::const_iterator it =
       variables.find("disambiguated_reason");
   if (it != variables.end() && !it->second.empty()) {
     printer->Print(
diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h
index 0e24da2..7275c09 100644
--- a/src/google/protobuf/compiler/java/java_field.h
+++ b/src/google/protobuf/compiler/java/java_field.h
@@ -37,9 +37,6 @@
 
 #include <map>
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 #include <string>
 
 #include <google/protobuf/stubs/common.h>
@@ -105,7 +102,7 @@
   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 GenerateMergingCode(io::Printer* printer) const = 0;
+  virtual void GenerateVisitCode(io::Printer* printer) const = 0;
   virtual void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer)
       const = 0;
   virtual void GenerateParsingCode(io::Printer* printer) const = 0;
@@ -119,6 +116,7 @@
   virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
   virtual void GenerateHashCode(io::Printer* printer) const = 0;
 
+
   virtual string GetBoxedType() const = 0;
 
  private:
@@ -140,7 +138,7 @@
   const Descriptor* descriptor_;
   Context* context_;
   ClassNameResolver* name_resolver_;
-  google::protobuf::scoped_array<google::protobuf::scoped_ptr<FieldGeneratorType> > field_generators_;
+  std::vector<std::unique_ptr<FieldGeneratorType>> field_generators_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
 };
@@ -162,6 +160,14 @@
 FieldGeneratorMap<ImmutableFieldGenerator>::~FieldGeneratorMap();
 
 
+template <>
+FieldGeneratorMap<ImmutableFieldLiteGenerator>::FieldGeneratorMap(
+    const Descriptor* descriptor, Context* context);
+
+template <>
+FieldGeneratorMap<ImmutableFieldLiteGenerator>::~FieldGeneratorMap();
+
+
 // Field information used in FieldGeneartors.
 struct FieldGeneratorInfo {
   string name;
@@ -169,7 +175,7 @@
   string disambiguated_reason;
 };
 
-// Oneof information used in OneofFieldGeneartors.
+// Oneof information used in OneofFieldGenerators.
 struct OneofGeneratorInfo {
   string name;
   string capitalized_name;
@@ -178,15 +184,15 @@
 // Set some common variables used in variable FieldGenerators.
 void SetCommonFieldVariables(const FieldDescriptor* descriptor,
                              const FieldGeneratorInfo* info,
-                             map<string, string>* variables);
+                             std::map<string, string>* variables);
 
 // Set some common oneof variables used in OneofFieldGenerators.
 void SetCommonOneofVariables(const FieldDescriptor* descriptor,
                              const OneofGeneratorInfo* info,
-                             map<string, string>* variables);
+                             std::map<string, string>* variables);
 
 // Print useful comments before a field's accessors.
-void PrintExtraFieldInfo(const map<string, string>& variables,
+void PrintExtraFieldInfo(const std::map<string, string>& variables,
                          io::Printer* printer);
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index c817233..5583b77 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -35,9 +35,6 @@
 #include <google/protobuf/compiler/java/java_file.h>
 
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 #include <set>
 
 #include <google/protobuf/compiler/java/java_context.h>
@@ -51,9 +48,9 @@
 #include <google/protobuf/compiler/java/java_service.h>
 #include <google/protobuf/compiler/java/java_shared_code_generator.h>
 #include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/stubs/strutil.h>
 
@@ -65,7 +62,7 @@
 namespace {
 
 struct FieldDescriptorCompare {
-  bool operator ()(const FieldDescriptor* f1, const FieldDescriptor* f2) {
+  bool operator ()(const FieldDescriptor* f1, const FieldDescriptor* f2) const {
     if(f1 == NULL) {
       return false;
     }
@@ -90,7 +87,7 @@
   // There are unknown fields that could be extensions, thus this call fails.
   if (reflection->GetUnknownFields(message).field_count() > 0) return false;
 
-  vector<const FieldDescriptor*> fields;
+  std::vector<const FieldDescriptor*> fields;
   reflection->ListFields(message, &fields);
 
   for (int i = 0; i < fields.size(); i++) {
@@ -136,7 +133,7 @@
            "descriptor.proto is not in the transitive dependencies. "
            "This normally should not happen. Please report a bug.";
     DynamicMessageFactory factory;
-    google::protobuf::scoped_ptr<Message> dynamic_file_proto(
+    std::unique_ptr<Message> dynamic_file_proto(
         factory.GetPrototype(file_proto_desc)->New());
     GOOGLE_CHECK(dynamic_file_proto.get() != NULL);
     GOOGLE_CHECK(dynamic_file_proto->ParseFromString(file_data));
@@ -154,12 +151,6 @@
   }
 }
 
-// Compare two field descriptors, returning true if the first should come
-// before the second.
-bool CompareFieldsByName(const FieldDescriptor *a, const FieldDescriptor *b) {
-  return a->full_name() < b->full_name();
-}
-
 // Our static initialization methods can become very, very large.
 // So large that if we aren't careful we end up blowing the JVM's
 // 64K bytes of bytecode/method. Fortunately, since these static
@@ -177,7 +168,7 @@
   // since otherwise we hit a hardcoded limit in the jvm and javac will
   // then fail with the error "code too large". This limit lets our
   // estimates be off by a factor of two and still we're okay.
-  static const int bytesPerMethod = 1<<15;  // aka 32K
+  static const int bytesPerMethod = kMaxStaticSize;
 
   if ((*bytecode_estimate) > bytesPerMethod) {
     ++(*method_num);
@@ -189,19 +180,17 @@
     *bytecode_estimate = 0;
   }
 }
-
-
 }  // namespace
 
-FileGenerator::FileGenerator(const FileDescriptor* file, bool immutable_api)
+FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options,
+                             bool immutable_api)
     : file_(file),
       java_package_(FileJavaPackage(file, immutable_api)),
-      message_generators_(
-          new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]),
-      extension_generators_(
-          new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]),
-      context_(new Context(file)),
+      message_generators_(file->message_type_count()),
+      extension_generators_(file->extension_count()),
+      context_(new Context(file, options)),
       name_resolver_(context_->GetNameResolver()),
+      options_(options),
       immutable_api_(immutable_api) {
   classname_ = name_resolver_->GetFileClassName(file, immutable_api);
   generator_factory_.reset(
@@ -234,6 +223,16 @@
       "option to specify a different outer class name for the .proto file.");
     return false;
   }
+  // Print a warning if optimize_for = LITE_RUNTIME is used.
+  if (file_->options().optimize_for() == FileOptions::LITE_RUNTIME) {
+    GOOGLE_LOG(WARNING)
+        << "The optimize_for = LITE_RUNTIME option is no longer supported by "
+        << "protobuf Java code generator and may generate broken code. It "
+        << "will be ignored by protoc in the future and protoc will always "
+        << "generate full runtime code for Java. To use Java Lite runtime, "
+        << "users should use the Java Lite plugin instead. See:\n"
+        << "  https://github.com/google/protobuf/blob/master/java/lite.md";
+  }
   return true;
 }
 
@@ -251,18 +250,23 @@
       "\n",
       "package", java_package_);
   }
+  PrintGeneratedAnnotation(
+      printer, '$', options_.annotate_code ? classname_ + ".java.pb.meta" : "");
   printer->Print(
-    "public final class $classname$ {\n"
-    "  private $classname$() {}\n",
-    "classname", classname_);
+      "$deprecation$public final class $classname$ {\n"
+      "  private $ctor$() {}\n",
+      "deprecation", file_->options().deprecated() ?
+          "@java.lang.Deprecated " : "",
+      "classname", classname_,
+      "ctor", classname_);
+  printer->Annotate("classname", file_->name());
   printer->Indent();
 
   // -----------------------------------------------------------------
 
   printer->Print(
     "public static void registerAllExtensions(\n"
-    "    com.google.protobuf.ExtensionRegistry$lite$ registry) {\n",
-    "lite", HasDescriptorMethods(file_) ? "" : "Lite");
+    "    com.google.protobuf.ExtensionRegistryLite registry) {\n");
 
   printer->Indent();
 
@@ -277,12 +281,26 @@
   printer->Outdent();
   printer->Print(
     "}\n");
+  if (HasDescriptorMethods(file_, context_->EnforceLite())) {
+    // Overload registerAllExtensions for the non-lite usage to
+    // redundantly maintain the original signature (this is
+    // redundant because ExtensionRegistryLite now invokes
+    // ExtensionRegistry in the non-lite usage). Intent is
+    // to remove this in the future.
+    printer->Print(
+      "\n"
+      "public static void registerAllExtensions(\n"
+      "    com.google.protobuf.ExtensionRegistry registry) {\n"
+      "  registerAllExtensions(\n"
+      "      (com.google.protobuf.ExtensionRegistryLite) registry);\n"
+      "}\n");
+  }
 
   // -----------------------------------------------------------------
 
   if (!MultipleJavaFiles(file_, immutable_api_)) {
     for (int i = 0; i < file_->enum_type_count(); i++) {
-      if (HasDescriptorMethods(file_)) {
+      if (HasDescriptorMethods(file_, context_->EnforceLite())) {
         EnumGenerator(file_->enum_type(i), immutable_api_, context_.get())
             .Generate(printer);
       } else {
@@ -294,9 +312,9 @@
       message_generators_[i]->GenerateInterface(printer);
       message_generators_[i]->Generate(printer);
     }
-    if (HasGenericServices(file_)) {
+    if (HasGenericServices(file_, context_->EnforceLite())) {
       for (int i = 0; i < file_->service_count(); i++) {
-        google::protobuf::scoped_ptr<ServiceGenerator> generator(
+        std::unique_ptr<ServiceGenerator> generator(
             generator_factory_->NewServiceGenerator(file_->service(i)));
         generator->Generate(printer);
       }
@@ -309,14 +327,18 @@
     extension_generators_[i]->Generate(printer);
   }
 
-  // Static variables.
+  // Static variables. We'd like them to be final if possible, but due to
+  // the JVM's 64k size limit on static blocks, we have to initialize some
+  // of them in methods; thus they cannot be final.
+  int static_block_bytecode_estimate = 0;
   for (int i = 0; i < file_->message_type_count(); i++) {
-    message_generators_[i]->GenerateStaticVariables(printer);
+    message_generators_[i]->GenerateStaticVariables(
+        printer, &static_block_bytecode_estimate);
   }
 
   printer->Print("\n");
 
-  if (HasDescriptorMethods(file_)) {
+  if (HasDescriptorMethods(file_, context_->EnforceLite())) {
     if (immutable_api_) {
       GenerateDescriptorInitializationCodeForImmutable(printer);
     } else {
@@ -358,12 +380,14 @@
     "    getDescriptor() {\n"
     "  return descriptor;\n"
     "}\n"
-    "private static com.google.protobuf.Descriptors.FileDescriptor\n"
+    "private static $final$ com.google.protobuf.Descriptors.FileDescriptor\n"
     "    descriptor;\n"
-    "static {\n");
+    "static {\n",
+    // TODO(dweis): Mark this as final.
+    "final", "");
   printer->Indent();
 
-  SharedCodeGenerator shared_code_generator(file_);
+  SharedCodeGenerator shared_code_generator(file_, options_);
   shared_code_generator.GenerateDescriptors(printer);
 
   int bytecode_estimate = 0;
@@ -416,7 +440,7 @@
       "    com.google.protobuf.ExtensionRegistry.newInstance();\n");
     FieldDescriptorSet::iterator it;
     for (it = extensions.begin(); it != extensions.end(); it++) {
-      google::protobuf::scoped_ptr<ExtensionGenerator> generator(
+      std::unique_ptr<ExtensionGenerator> generator(
           generator_factory_->NewExtensionGenerator(*it));
       bytecode_estimate += generator->GenerateRegistrationCode(printer);
       MaybeRestartJavaMethod(
@@ -453,7 +477,7 @@
     "    getDescriptor() {\n"
     "  return descriptor;\n"
     "}\n"
-    "private static com.google.protobuf.Descriptors.FileDescriptor\n"
+    "private static final com.google.protobuf.Descriptors.FileDescriptor\n"
     "    descriptor;\n"
     "static {\n");
   printer->Indent();
@@ -483,19 +507,57 @@
     // Try to load immutable messages' outer class. Its initialization code
     // will take care of interpreting custom options.
     printer->Print(
-      "try {\n"
-      // Note that we have to load the immutable class dynamically here as
-      // we want the mutable code to be independent from the immutable code
-      // at compile time. It is required to implement dual-compile for
-      // mutable and immutable API in blaze.
-      "  java.lang.Class immutableClass = java.lang.Class.forName(\n"
-      "      \"$immutable_classname$\");\n"
-      "} catch (java.lang.ClassNotFoundException e) {\n"
-      // The immutable class can not be found. Custom options are left
-      // as unknown fields.
-      // TODO(xiaofeng): inform the user with a warning?
-      "}\n",
-      "immutable_classname", name_resolver_->GetImmutableClassName(file_));
+        "try {\n"
+        // Note that we have to load the immutable class dynamically here as
+        // we want the mutable code to be independent from the immutable code
+        // at compile time. It is required to implement dual-compile for
+        // mutable and immutable API in blaze.
+        "  java.lang.Class immutableClass = java.lang.Class.forName(\n"
+        "      \"$immutable_classname$\");\n"
+        "} catch (java.lang.ClassNotFoundException e) {\n",
+        "immutable_classname", name_resolver_->GetImmutableClassName(file_));
+    printer->Indent();
+
+    // The immutable class can not be found. We try our best to collect all
+    // custom option extensions to interpret the custom options.
+    printer->Print(
+        "com.google.protobuf.ExtensionRegistry registry =\n"
+        "    com.google.protobuf.ExtensionRegistry.newInstance();\n"
+        "com.google.protobuf.MessageLite defaultExtensionInstance = null;\n");
+    FieldDescriptorSet::iterator it;
+    for (it = extensions.begin(); it != extensions.end(); it++) {
+      const FieldDescriptor* field = *it;
+      string scope;
+      if (field->extension_scope() != NULL) {
+        scope = name_resolver_->GetMutableClassName(field->extension_scope()) +
+                ".getDescriptor()";
+      } else {
+        scope = FileJavaPackage(field->file(), true) + "." +
+                name_resolver_->GetDescriptorClassName(field->file()) +
+                ".descriptor";
+      }
+      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+        printer->Print(
+            "defaultExtensionInstance = com.google.protobuf.Internal\n"
+            "    .getDefaultInstance(\"$class$\");\n"
+            "if (defaultExtensionInstance != null) {\n"
+            "  registry.add(\n"
+            "      $scope$.getExtensions().get($index$),\n"
+            "      (com.google.protobuf.Message) defaultExtensionInstance);\n"
+            "}\n",
+            "scope", scope, "index", SimpleItoa(field->index()), "class",
+            name_resolver_->GetImmutableClassName(field->message_type()));
+      } else {
+        printer->Print("registry.add($scope$.getExtensions().get($index$));\n",
+                       "scope", scope, "index", SimpleItoa(field->index()));
+      }
+    }
+    printer->Print(
+        "com.google.protobuf.Descriptors.FileDescriptor\n"
+        "    .internalUpdateFileDescriptor(descriptor, registry);\n");
+
+    printer->Outdent();
+    printer->Print("}\n");
   }
 
   // Force descriptor initialization of all dependencies.
@@ -514,20 +576,26 @@
     "}\n");
 }
 
-template<typename GeneratorClass, typename DescriptorClass>
+template <typename GeneratorClass, typename DescriptorClass>
 static void GenerateSibling(const string& package_dir,
                             const string& java_package,
                             const DescriptorClass* descriptor,
                             GeneratorContext* context,
-                            vector<string>* file_list,
+                            std::vector<string>* file_list, bool annotate_code,
+                            std::vector<string>* annotation_list,
                             const string& name_suffix,
                             GeneratorClass* generator,
                             void (GeneratorClass::*pfn)(io::Printer* printer)) {
   string filename = package_dir + descriptor->name() + name_suffix + ".java";
   file_list->push_back(filename);
+  string info_full_path = filename + ".pb.meta";
+  GeneratedCodeInfo annotations;
+  io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+      &annotations);
 
-  google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
-  io::Printer printer(output.get(), '$');
+  std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+  io::Printer printer(output.get(), '$',
+                      annotate_code ? &annotation_collector : NULL);
 
   printer.Print(
     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
@@ -542,55 +610,57 @@
   }
 
   (generator->*pfn)(&printer);
+
+  if (annotate_code) {
+    std::unique_ptr<io::ZeroCopyOutputStream> info_output(
+        context->Open(info_full_path));
+    annotations.SerializeToZeroCopyStream(info_output.get());
+    annotation_list->push_back(info_full_path);
+  }
 }
 
 void FileGenerator::GenerateSiblings(const string& package_dir,
                                      GeneratorContext* context,
-                                     vector<string>* file_list) {
+                                     std::vector<string>* file_list,
+                                     std::vector<string>* annotation_list) {
   if (MultipleJavaFiles(file_, immutable_api_)) {
     for (int i = 0; i < file_->enum_type_count(); i++) {
-      if (HasDescriptorMethods(file_)) {
+      if (HasDescriptorMethods(file_, context_->EnforceLite())) {
         EnumGenerator generator(file_->enum_type(i), immutable_api_,
                                 context_.get());
-        GenerateSibling<EnumGenerator>(package_dir, java_package_,
-                                       file_->enum_type(i),
-                                       context, file_list, "",
-                                       &generator,
-                                       &EnumGenerator::Generate);
+        GenerateSibling<EnumGenerator>(
+            package_dir, java_package_, file_->enum_type(i), context, file_list,
+            options_.annotate_code, annotation_list, "", &generator,
+            &EnumGenerator::Generate);
       } else {
         EnumLiteGenerator generator(file_->enum_type(i), immutable_api_,
                                     context_.get());
-        GenerateSibling<EnumLiteGenerator>(package_dir, java_package_,
-                                           file_->enum_type(i),
-                                           context, file_list, "",
-                                           &generator,
-                                           &EnumLiteGenerator::Generate);
+        GenerateSibling<EnumLiteGenerator>(
+            package_dir, java_package_, file_->enum_type(i), context, file_list,
+            options_.annotate_code, annotation_list, "", &generator,
+            &EnumLiteGenerator::Generate);
       }
     }
     for (int i = 0; i < file_->message_type_count(); i++) {
       if (immutable_api_) {
-        GenerateSibling<MessageGenerator>(package_dir, java_package_,
-                                          file_->message_type(i),
-                                          context, file_list,
-                                          "OrBuilder",
-                                          message_generators_[i].get(),
-                                          &MessageGenerator::GenerateInterface);
+        GenerateSibling<MessageGenerator>(
+            package_dir, java_package_, file_->message_type(i), context,
+            file_list, options_.annotate_code, annotation_list, "OrBuilder",
+            message_generators_[i].get(), &MessageGenerator::GenerateInterface);
       }
-      GenerateSibling<MessageGenerator>(package_dir, java_package_,
-                                        file_->message_type(i),
-                                        context, file_list, "",
-                                        message_generators_[i].get(),
-                                        &MessageGenerator::Generate);
+      GenerateSibling<MessageGenerator>(
+          package_dir, java_package_, file_->message_type(i), context,
+          file_list, options_.annotate_code, annotation_list, "",
+          message_generators_[i].get(), &MessageGenerator::Generate);
     }
-    if (HasGenericServices(file_)) {
+    if (HasGenericServices(file_, context_->EnforceLite())) {
       for (int i = 0; i < file_->service_count(); i++) {
-        google::protobuf::scoped_ptr<ServiceGenerator> generator(
+        std::unique_ptr<ServiceGenerator> generator(
             generator_factory_->NewServiceGenerator(file_->service(i)));
-        GenerateSibling<ServiceGenerator>(package_dir, java_package_,
-                                          file_->service(i),
-                                          context, file_list, "",
-                                          generator.get(),
-                                          &ServiceGenerator::Generate);
+        GenerateSibling<ServiceGenerator>(
+            package_dir, java_package_, file_->service(i), context, file_list,
+            options_.annotate_code, annotation_list, "", generator.get(),
+            &ServiceGenerator::Generate);
       }
     }
   }
diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h
index 080b342..78833a4 100644
--- a/src/google/protobuf/compiler/java/java_file.h
+++ b/src/google/protobuf/compiler/java/java_file.h
@@ -36,12 +36,10 @@
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__
 
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 #include <string>
 #include <vector>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_options.h>
 
 namespace google {
 namespace protobuf {
@@ -67,7 +65,8 @@
 
 class FileGenerator {
  public:
-  FileGenerator(const FileDescriptor* file, bool immutable_api = true);
+  FileGenerator(const FileDescriptor* file, const Options& options,
+                bool immutable_api = true);
   ~FileGenerator();
 
   // Checks for problems that would otherwise lead to cryptic compile errors.
@@ -82,12 +81,12 @@
   // service type).
   void GenerateSiblings(const string& package_dir,
                         GeneratorContext* generator_context,
-                        vector<string>* file_list);
+                        std::vector<string>* file_list,
+                        std::vector<string>* annotation_list);
 
   const string& java_package() { return java_package_; }
   const string& classname()    { return classname_;    }
 
-
  private:
   void GenerateDescriptorInitializationCodeForImmutable(io::Printer* printer);
   void GenerateDescriptorInitializationCodeForMutable(io::Printer* printer);
@@ -99,14 +98,14 @@
   string java_package_;
   string classname_;
 
-  google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > message_generators_;
-  google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
-  google::protobuf::scoped_ptr<GeneratorFactory> generator_factory_;
-  google::protobuf::scoped_ptr<Context> context_;
+  std::vector<std::unique_ptr<MessageGenerator>> message_generators_;
+  std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_;
+  std::unique_ptr<GeneratorFactory> generator_factory_;
+  std::unique_ptr<Context> context_;
   ClassNameResolver* name_resolver_;
+  const Options options_;
   bool immutable_api_;
 
-
   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 6c6f728..a5b2e78 100644
--- a/src/google/protobuf/compiler/java/java_generator.cc
+++ b/src/google/protobuf/compiler/java/java_generator.cc
@@ -35,17 +35,17 @@
 #include <google/protobuf/compiler/java/java_generator.h>
 
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 
 #include <google/protobuf/compiler/java/java_file.h>
 #include <google/protobuf/compiler/java/java_generator_factory.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/java/java_options.h>
 #include <google/protobuf/compiler/java/java_shared_code_generator.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/descriptor.pb.h>
+
 #include <google/protobuf/stubs/strutil.h>
 
 namespace google {
@@ -64,51 +64,58 @@
   // -----------------------------------------------------------------
   // parse generator options
 
-  // Name a file where we will write a list of generated file names, one
-  // per line.
-  string output_list_file;
 
-
-  vector<pair<string, string> > options;
+  std::vector<std::pair<string, string> > options;
   ParseGeneratorParameter(parameter, &options);
+  Options file_options;
 
-  bool generate_immutable_code = false;
-  bool generate_mutable_code = false;
-  bool generate_shared_code = false;
   for (int i = 0; i < options.size(); i++) {
     if (options[i].first == "output_list_file") {
-      output_list_file = options[i].second;
+      file_options.output_list_file = options[i].second;
     } else if (options[i].first == "immutable") {
-      generate_immutable_code = true;
+      file_options.generate_immutable_code = true;
     } else if (options[i].first == "mutable") {
-      generate_mutable_code = true;
+      file_options.generate_mutable_code = true;
     } else if (options[i].first == "shared") {
-      generate_shared_code = true;
+      file_options.generate_shared_code = true;
+    } else if (options[i].first == "annotate_code") {
+      file_options.annotate_code = true;
+    } else if (options[i].first == "annotation_list_file") {
+      file_options.annotation_list_file = options[i].second;
     } else {
       *error = "Unknown generator option: " + options[i].first;
       return false;
     }
   }
 
+  if (file_options.enforce_lite && file_options.generate_mutable_code) {
+    *error = "lite runtime generator option cannot be used with mutable API.";
+    return false;
+  }
+
   // By default we generate immutable code and shared code for immutable API.
-  if (!generate_immutable_code && !generate_mutable_code &&
-      !generate_shared_code) {
-    generate_immutable_code = true;
-    generate_shared_code = true;
+  if (!file_options.generate_immutable_code &&
+      !file_options.generate_mutable_code &&
+      !file_options.generate_shared_code) {
+    file_options.generate_immutable_code = true;
+    file_options.generate_shared_code = true;
   }
 
   // -----------------------------------------------------------------
 
 
-  vector<string> all_files;
+  std::vector<string> all_files;
+  std::vector<string> all_annotations;
 
 
-  vector<FileGenerator*> file_generators;
-  if (generate_immutable_code) {
-    file_generators.push_back(new FileGenerator(file, /* immutable = */ true));
+  std::vector<FileGenerator*> file_generators;
+  if (file_options.generate_immutable_code) {
+    file_generators.push_back(new FileGenerator(file, file_options,
+                                                /* immutable = */ true));
   }
-  if (generate_mutable_code) {
-    file_generators.push_back(new FileGenerator(file, /* mutable = */ false));
+  if (file_options.generate_mutable_code) {
+    file_generators.push_back(new FileGenerator(file, file_options,
+                                                /* mutable = */ false));
   }
   for (int i = 0; i < file_generators.size(); ++i) {
     if (!file_generators[i]->Validate(error)) {
@@ -128,15 +135,32 @@
     java_filename += file_generator->classname();
     java_filename += ".java";
     all_files.push_back(java_filename);
+    string info_full_path = java_filename + ".pb.meta";
+    if (file_options.annotate_code) {
+      all_annotations.push_back(info_full_path);
+    }
 
     // Generate main java file.
-    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+    std::unique_ptr<io::ZeroCopyOutputStream> output(
         context->Open(java_filename));
-    io::Printer printer(output.get(), '$');
+    GeneratedCodeInfo annotations;
+    io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+        &annotations);
+    io::Printer printer(output.get(), '$', file_options.annotate_code
+                                               ? &annotation_collector
+                                               : NULL);
+
     file_generator->Generate(&printer);
 
     // Generate sibling files.
-    file_generator->GenerateSiblings(package_dir, context, &all_files);
+    file_generator->GenerateSiblings(package_dir, context, &all_files,
+                                     &all_annotations);
+
+    if (file_options.annotate_code) {
+      std::unique_ptr<io::ZeroCopyOutputStream> info_output(
+          context->Open(info_full_path));
+      annotations.SerializeToZeroCopyStream(info_output.get());
+    }
   }
 
   for (int i = 0; i < file_generators.size(); ++i) {
@@ -145,17 +169,29 @@
   file_generators.clear();
 
   // Generate output list if requested.
-  if (!output_list_file.empty()) {
+  if (!file_options.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.
-    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
-        context->Open(output_list_file));
+    std::unique_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
+        context->Open(file_options.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]);
     }
   }
 
+  if (!file_options.annotation_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.
+    std::unique_ptr<io::ZeroCopyOutputStream> annotation_list_raw_output(
+        context->Open(file_options.annotation_list_file));
+    io::Printer annotation_list_printer(annotation_list_raw_output.get(), '$');
+    for (int i = 0; i < all_annotations.size(); i++) {
+      annotation_list_printer.Print("$filename$\n", "filename",
+                                    all_annotations[i]);
+    }
+  }
+
   return true;
 }
 
diff --git a/src/google/protobuf/compiler/java/java_generator_factory.cc b/src/google/protobuf/compiler/java/java_generator_factory.cc
index 92ef851..3218b41 100644
--- a/src/google/protobuf/compiler/java/java_generator_factory.cc
+++ b/src/google/protobuf/compiler/java/java_generator_factory.cc
@@ -35,6 +35,7 @@
 #include <google/protobuf/compiler/java/java_context.h>
 #include <google/protobuf/compiler/java/java_enum_field.h>
 #include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_extension_lite.h>
 #include <google/protobuf/compiler/java/java_field.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_message.h>
@@ -58,17 +59,20 @@
 
 MessageGenerator* ImmutableGeneratorFactory::NewMessageGenerator(
     const Descriptor* descriptor) const {
-  if (descriptor->file()->options().optimize_for() ==
-      FileOptions::LITE_RUNTIME) {
-    return new ImmutableMessageLiteGenerator(descriptor, context_);
-  } else {
+  if (HasDescriptorMethods(descriptor, context_->EnforceLite())) {
     return new ImmutableMessageGenerator(descriptor, context_);
+  } else {
+    return new ImmutableMessageLiteGenerator(descriptor, context_);
   }
 }
 
 ExtensionGenerator* ImmutableGeneratorFactory::NewExtensionGenerator(
     const FieldDescriptor* descriptor) const {
-  return new ImmutableExtensionGenerator(descriptor, context_);
+  if (HasDescriptorMethods(descriptor->file(), context_->EnforceLite())) {
+    return new ImmutableExtensionGenerator(descriptor, context_);
+  } else {
+    return new ImmutableExtensionLiteGenerator(descriptor, context_);
+  }
 }
 
 ServiceGenerator* ImmutableGeneratorFactory::NewServiceGenerator(
diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc
index e24894b..957076c 100644
--- a/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/src/google/protobuf/compiler/java/java_helpers.cc
@@ -37,6 +37,7 @@
 #include <limits>
 #include <vector>
 
+#include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
 #include <google/protobuf/descriptor.pb.h>
@@ -44,6 +45,9 @@
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
 
+
+#include <google/protobuf/stubs/hash.h>  // for hash<T *>
+
 namespace google {
 namespace protobuf {
 namespace compiler {
@@ -71,6 +75,8 @@
   "class",
 };
 
+const int kDefaultLookUpStartFieldNumber = 40;
+
 bool IsForbidden(const string& field_name) {
   for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) {
     if (field_name == kForbiddenWordList[i]) {
@@ -99,8 +105,36 @@
 }
 
 
+// Judge whether should use table or use look up.
+// Copied from com.google.protobuf.SchemaUtil.shouldUseTableSwitch
+bool ShouldUseTable(int lo, int hi, int number_of_fields) {
+  if (hi < kDefaultLookUpStartFieldNumber) {
+    return true;
+  }
+  int64 table_space_cost = (static_cast<int64>(hi) - lo + 1);  // words
+  int64 table_time_cost = 3;           // comparisons
+  int64 lookup_space_cost = 3 + 2 * static_cast<int64>(number_of_fields);
+  int64 lookup_time_cost = 3 + number_of_fields;
+  return table_space_cost + 3 * table_time_cost <=
+         lookup_space_cost + 3 * lookup_time_cost;
+}
+
 }  // namespace
 
+void PrintGeneratedAnnotation(io::Printer* printer, char delimiter,
+                              const string& annotation_file) {
+  if (annotation_file.empty()) {
+    return;
+  }
+  string ptemplate =
+      "@javax.annotation.Generated(value=\"protoc\", comments=\"annotations:";
+  ptemplate.push_back(delimiter);
+  ptemplate.append("annotation_file");
+  ptemplate.push_back(delimiter);
+  ptemplate.append("\")\n");
+  printer->Print(ptemplate.c_str(), "annotation_file", annotation_file);
+}
+
 string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
   string result;
   // Note:  I distrust ctype.h due to locales.
@@ -152,6 +186,14 @@
   return "static_" + StringReplace(descriptor->full_name(), ".", "_", true);
 }
 
+string CamelCaseFieldName(const FieldDescriptor* field) {
+  string fieldName = UnderscoresToCamelCase(field);
+  if ('0' <= fieldName[0] && fieldName[0] <= '9') {
+    return '_' + fieldName;
+  }
+  return fieldName;
+}
+
 string StripProto(const string& filename) {
   if (HasSuffixString(filename, ".protodevel")) {
     return StripSuffixString(filename, ".protodevel");
@@ -231,6 +273,7 @@
   return name_resolver.GetClassName(descriptor, true);
 }
 
+
 string ExtraMessageInterfaces(const Descriptor* descriptor) {
   string interfaces = "// @@protoc_insertion_point(message_implements:"
       + descriptor->full_name() + ")";
@@ -346,6 +389,7 @@
   return NULL;
 }
 
+
 const char* FieldTypeName(FieldDescriptor::Type field_type) {
   switch (field_type) {
     case FieldDescriptor::TYPE_INT32   : return "INT32";
@@ -401,9 +445,9 @@
              "L";
     case FieldDescriptor::CPPTYPE_DOUBLE: {
       double value = field->default_value_double();
-      if (value == numeric_limits<double>::infinity()) {
+      if (value == std::numeric_limits<double>::infinity()) {
         return "Double.POSITIVE_INFINITY";
-      } else if (value == -numeric_limits<double>::infinity()) {
+      } else if (value == -std::numeric_limits<double>::infinity()) {
         return "Double.NEGATIVE_INFINITY";
       } else if (value != value) {
         return "Double.NaN";
@@ -413,9 +457,9 @@
     }
     case FieldDescriptor::CPPTYPE_FLOAT: {
       float value = field->default_value_float();
-      if (value == numeric_limits<float>::infinity()) {
+      if (value == std::numeric_limits<float>::infinity()) {
         return "Float.POSITIVE_INFINITY";
-      } else if (value == -numeric_limits<float>::infinity()) {
+      } else if (value == -std::numeric_limits<float>::infinity()) {
         return "Float.NEGATIVE_INFINITY";
       } else if (value != value) {
         return "Float.NaN";
@@ -481,9 +525,9 @@
       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:
+      return field->default_value_enum()->number() == 0;
+    case FieldDescriptor::CPPTYPE_STRING:
     case FieldDescriptor::CPPTYPE_MESSAGE:
       return false;
 
@@ -495,6 +539,11 @@
   return false;
 }
 
+bool IsByteStringWithCustomDefaultValue(const FieldDescriptor* field) {
+  return GetJavaType(field) == JAVATYPE_BYTES &&
+         field->default_value_string() != "";
+}
+
 const char* bit_masks[] = {
   "0x00000001",
   "0x00000002",
@@ -751,6 +800,154 @@
   return false;
 }
 
+// Encode an unsigned 32-bit value into a sequence of UTF-16 characters.
+//
+// If the value is in [0x0000, 0xD7FF], we encode it with a single character
+// with the same numeric value.
+//
+// If the value is larger than 0xD7FF, we encode its lowest 13 bits into a
+// character in the range [0xE000, 0xFFFF] by combining these 13 bits with
+// 0xE000 using logic-or. Then we shift the value to the right by 13 bits, and
+// encode the remaining value by repeating this same process until we get to
+// a value in [0x0000, 0xD7FF] where we will encode it using a character with
+// the same numeric value.
+//
+// Note that we only use code points in [0x0000, 0xD7FF] and [0xE000, 0xFFFF].
+// There will be no surrogate pairs in the encoded character sequence.
+void WriteUInt32ToUtf16CharSequence(uint32 number,
+                                    std::vector<uint16>* output) {
+  // For values in [0x0000, 0xD7FF], only use one char to encode it.
+  if (number < 0xD800) {
+    output->push_back(static_cast<uint16>(number));
+    return;
+  }
+  // Encode into multiple chars. All except the last char will be in the range
+  // [0xE000, 0xFFFF], and the last char will be in the range [0x0000, 0xD7FF].
+  // Note that we don't use any value in range [0xD800, 0xDFFF] because they
+  // have to come in pairs and the encoding is just more space-efficient w/o
+  // them.
+  while (number >= 0xD800) {
+    // [0xE000, 0xFFFF] can represent 13 bits of info.
+    output->push_back(static_cast<uint16>(0xE000 | (number & 0x1FFF)));
+    number >>= 13;
+  }
+  output->push_back(static_cast<uint16>(number));
+}
+
+int GetExperimentalJavaFieldTypeForSingular(const FieldDescriptor* field) {
+  // j/c/g/protobuf/FieldType.java lists field types in a slightly different
+  // order from FieldDescriptor::Type so we can't do a simple cast.
+  //
+  // TODO(xiaofeng): Make j/c/g/protobuf/FieldType.java follow the same order.
+  int result = field->type();
+  if (result == FieldDescriptor::TYPE_GROUP) {
+    return 17;
+  } else if (result < FieldDescriptor::TYPE_GROUP) {
+    return result - 1;
+  } else {
+    return result - 2;
+  }
+}
+
+int GetExperimentalJavaFieldTypeForRepeated(const FieldDescriptor* field) {
+  if (field->type() == FieldDescriptor::TYPE_GROUP) {
+    return 49;
+  } else {
+    return GetExperimentalJavaFieldTypeForSingular(field) + 18;
+  }
+}
+
+int GetExperimentalJavaFieldTypeForPacked(const FieldDescriptor* field) {
+  int result = field->type();
+  if (result < FieldDescriptor::TYPE_STRING) {
+    return result + 34;
+  } else if (result > FieldDescriptor::TYPE_BYTES) {
+    return result + 30;
+  } else {
+    GOOGLE_LOG(FATAL) << field->full_name() << " can't be packed.";
+    return 0;
+  }
+}
+
+int GetExperimentalJavaFieldType(const FieldDescriptor* field) {
+  static const int kMapFieldType = 50;
+  static const int kOneofFieldTypeOffset = 51;
+  static const int kRequiredBit = 0x100;
+  static const int kUtf8CheckBit = 0x200;
+  static const int kCheckInitialized = 0x400;
+  static const int kMapWithProto2EnumValue = 0x800;
+  int extra_bits = field->is_required() ? kRequiredBit : 0;
+  if (field->type() == FieldDescriptor::TYPE_STRING && CheckUtf8(field)) {
+    extra_bits |= kUtf8CheckBit;
+  }
+  if (field->is_required() || (GetJavaType(field) == JAVATYPE_MESSAGE &&
+                               HasRequiredFields(field->message_type()))) {
+    extra_bits |= kCheckInitialized;
+  }
+
+  if (field->is_map()) {
+    if (SupportFieldPresence(field->file())) {
+      const FieldDescriptor* value =
+          field->message_type()->FindFieldByName("value");
+      if (GetJavaType(value) == JAVATYPE_ENUM) {
+        extra_bits |= kMapWithProto2EnumValue;
+      }
+    }
+    return kMapFieldType | extra_bits;
+  } else if (field->is_packed()) {
+    return GetExperimentalJavaFieldTypeForPacked(field);
+  } else if (field->is_repeated()) {
+    return GetExperimentalJavaFieldTypeForRepeated(field) | extra_bits;
+  } else if (field->containing_oneof() != NULL) {
+    return (GetExperimentalJavaFieldTypeForSingular(field) +
+            kOneofFieldTypeOffset) |
+           extra_bits;
+  } else {
+    return GetExperimentalJavaFieldTypeForSingular(field) | extra_bits;
+  }
+}
+
+// Escape a UTF-16 character to be embedded in a Java string.
+void EscapeUtf16ToString(uint16 code, string* output) {
+  if (code == '\t') {
+    output->append("\\t");
+  } else if (code == '\b') {
+    output->append("\\b");
+  } else if (code == '\n') {
+    output->append("\\n");
+  } else if (code == '\r') {
+    output->append("\\r");
+  } else if (code == '\f') {
+    output->append("\\f");
+  } else if (code == '\'') {
+    output->append("\\'");
+  } else if (code == '\"') {
+    output->append("\\\"");
+  } else if (code == '\\') {
+    output->append("\\\\");
+  } else if (code >= 0x20 && code <= 0x7f) {
+    output->push_back(static_cast<char>(code));
+  } else {
+    output->append(StringPrintf("\\u%04x", code));
+  }
+}
+
+std::pair<int, int> GetTableDrivenNumberOfEntriesAndLookUpStartFieldNumber(
+    const FieldDescriptor** fields, int count) {
+  GOOGLE_CHECK_GT(count, 0);
+  int table_driven_number_of_entries = count;
+  int look_up_start_field_number = 0;
+  for (int i = 0; i < count; i++) {
+    const int field_number = fields[i]->number();
+    if (ShouldUseTable(fields[0]->number(), field_number, i + 1)) {
+      table_driven_number_of_entries =
+          field_number - fields[0]->number() + 1 + count - i - 1;
+      look_up_start_field_number = field_number + 1;
+    }
+  }
+  return std::make_pair(
+      table_driven_number_of_entries, look_up_start_field_number);
+}
 }  // 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 5392d6d..dd9b65b 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -36,7 +36,9 @@
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
 
 #include <string>
+#include <google/protobuf/compiler/java/java_context.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
 #include <google/protobuf/descriptor.h>
 
 namespace google {
@@ -49,6 +51,17 @@
 extern const char kThickSeparator[];
 extern const char kThinSeparator[];
 
+// If annotation_file is non-empty, prints a javax.annotation.Generated
+// annotation to the given Printer. annotation_file will be referenced in the
+// annotation's comments field. delimiter should be the Printer's delimiter
+// character. annotation_file will be included verbatim into a Java literal
+// string, so it should not contain quotes or invalid Java escape sequences;
+// however, these are unlikely to appear in practice, as the value of
+// annotation_file should be generated from the filename of the source file
+// being annotated (which in turn must be a Java identifier plus ".java").
+void PrintGeneratedAnnotation(io::Printer* printer, char delimiter = '$',
+                              const string& annotation_file = "");
+
 // Converts a name to camel-case. If cap_first_letter is true, capitalize the
 // first letter.
 string UnderscoresToCamelCase(const string& name, bool cap_first_letter);
@@ -61,6 +74,10 @@
 // of lower-casing the first letter of the name.)
 string UnderscoresToCamelCase(const MethodDescriptor* method);
 
+// Similar to UnderscoresToCamelCase, but guarentees that the result is a
+// complete Java identifier by adding a _ if needed.
+string CamelCaseFieldName(const FieldDescriptor* field);
+
 // Get an identifier that uniquely identifies this type within the file.
 // This is used to declare static variables related to this type at the
 // outermost file scope.
@@ -119,6 +136,13 @@
   return descriptor->name();
 }
 
+// Whether the given descriptor is for one of the core descriptor protos. We
+// cannot currently use the new runtime with core protos since there is a
+// bootstrapping problem with obtaining their descriptors.
+inline bool IsDescriptorProto(const Descriptor* descriptor) {
+  return descriptor->file()->name() == "google/protobuf/descriptor.proto";
+}
+
 
 // Whether we should generate multiple java files for messages.
 inline bool MultipleJavaFiles(
@@ -126,6 +150,38 @@
   return descriptor->options().java_multiple_files();
 }
 
+// Returns true if `descriptor` will be written to its own .java file.
+// `immutable` should be set to true if we're generating for the immutable API.
+template <typename Descriptor>
+bool IsOwnFile(const Descriptor* descriptor, bool immutable) {
+  return descriptor->containing_type() == NULL &&
+         MultipleJavaFiles(descriptor->file(), immutable);
+}
+
+template <>
+inline bool IsOwnFile(const ServiceDescriptor* descriptor, bool immutable) {
+  return MultipleJavaFiles(descriptor->file(), immutable);
+}
+
+// If `descriptor` describes an object with its own .java file,
+// returns the name (relative to that .java file) of the file that stores
+// annotation data for that descriptor. `suffix` is usually empty, but may
+// (e.g.) be "OrBuilder" for some generated interfaces.
+template <typename Descriptor>
+string AnnotationFileName(const Descriptor* descriptor, const string& suffix) {
+  return descriptor->name() + suffix + ".java.pb.meta";
+}
+
+template <typename Descriptor>
+void MaybePrintGeneratedAnnotation(Context* context, io::Printer* printer,
+                                   Descriptor* descriptor, bool immutable,
+                                   const string& suffix = "") {
+  if (context->options().annotate_code && IsOwnFile(descriptor, immutable)) {
+    PrintGeneratedAnnotation(printer, '$',
+                             AnnotationFileName(descriptor, suffix));
+  }
+}
+
 // Get the unqualified name that should be used for a field's field
 // number constant.
 string FieldConstantName(const FieldDescriptor *field);
@@ -169,50 +225,34 @@
   return DefaultValue(field, true, name_resolver);
 }
 bool IsDefaultValueJavaDefault(const FieldDescriptor* field);
-
-// Does this message class have generated parsing, serialization, and other
-// standard methods for which reflection-based fallback implementations exist?
-inline bool HasGeneratedMethods(const Descriptor* descriptor) {
-  return descriptor->file()->options().optimize_for() !=
-           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();
-}
+bool IsByteStringWithCustomDefaultValue(const FieldDescriptor* field);
 
 // Does this message class have descriptor and reflection methods?
-inline bool HasDescriptorMethods(const Descriptor* descriptor) {
-  return descriptor->file()->options().optimize_for() !=
-           FileOptions::LITE_RUNTIME;
+inline bool HasDescriptorMethods(const Descriptor* descriptor,
+                                 bool enforce_lite) {
+  return !enforce_lite &&
+         descriptor->file()->options().optimize_for() !=
+             FileOptions::LITE_RUNTIME;
 }
-inline bool HasDescriptorMethods(const EnumDescriptor* descriptor) {
-  return descriptor->file()->options().optimize_for() !=
-           FileOptions::LITE_RUNTIME;
+inline bool HasDescriptorMethods(const EnumDescriptor* descriptor,
+                                 bool enforce_lite) {
+  return !enforce_lite &&
+         descriptor->file()->options().optimize_for() !=
+             FileOptions::LITE_RUNTIME;
 }
-inline bool HasDescriptorMethods(const FileDescriptor* descriptor) {
-  return descriptor->options().optimize_for() !=
-           FileOptions::LITE_RUNTIME;
+inline bool HasDescriptorMethods(const FileDescriptor* descriptor,
+                                 bool enforce_lite) {
+  return !enforce_lite &&
+         descriptor->options().optimize_for() != FileOptions::LITE_RUNTIME;
 }
 
 // Should we generate generic services for this file?
-inline bool HasGenericServices(const FileDescriptor *file) {
+inline bool HasGenericServices(const FileDescriptor *file, bool enforce_lite) {
   return file->service_count() > 0 &&
-         file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
+         HasDescriptorMethods(file, enforce_lite) &&
          file->options().java_generic_services();
 }
 
-inline bool IsLazy(const FieldDescriptor* descriptor) {
-  // Currently, the proto-lite version suports lazy field.
-  // TODO(niwasaki): Support lazy fields also for other proto runtimes.
-  if (descriptor->file()->options().optimize_for() !=
-      FileOptions::LITE_RUNTIME) {
-    return false;
-  }
-  return descriptor->options().lazy();
-}
-
 // Methods for shared bitfields.
 
 // Gets the name of the shared bitfield for the given index.
@@ -334,19 +374,51 @@
   return descriptor->is_map();
 }
 
-inline bool PreserveUnknownFields(const Descriptor* descriptor) {
-  return descriptor->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
-}
-
 inline bool IsAnyMessage(const Descriptor* descriptor) {
   return descriptor->full_name() == "google.protobuf.Any";
 }
 
+inline bool IsWrappersProtoFile(const FileDescriptor* descriptor) {
+  return descriptor->name() == "google/protobuf/wrappers.proto";
+}
+
 inline bool CheckUtf8(const FieldDescriptor* descriptor) {
   return descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ||
       descriptor->file()->options().java_string_check_utf8();
 }
 
+inline string GeneratedCodeVersionSuffix() {
+  return "V3";
+}
+
+inline bool EnableExperimentalRuntime(Context* context) {
+  return false;
+}
+
+void WriteUInt32ToUtf16CharSequence(uint32 number, std::vector<uint16>* output);
+
+inline void WriteIntToUtf16CharSequence(int value,
+                                        std::vector<uint16>* output) {
+  WriteUInt32ToUtf16CharSequence(static_cast<uint32>(value), output);
+}
+
+// Escape a UTF-16 character so it can be embedded in a Java string literal.
+void EscapeUtf16ToString(uint16 code, string* output);
+
+// Only the lowest two bytes of the return value are used. The lowest byte
+// is the integer value of a j/c/g/protobuf/FieldType enum. For the other
+// byte:
+//    bit 0: whether the field is required.
+//    bit 1: whether the field requires UTF-8 validation.
+//    bit 2: whether the field needs isInitialized check.
+//    bit 3: whether the field is a map field with proto2 enum value.
+//    bits 4-7: unused
+int GetExperimentalJavaFieldType(const FieldDescriptor* field);
+
+// To get the total number of entries need to be built for experimental runtime
+// and the first field number that are not in the table part
+std::pair<int, int> GetTableDrivenNumberOfEntriesAndLookUpStartFieldNumber(
+    const FieldDescriptor** fields, int count);
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.cc b/src/google/protobuf/compiler/java/java_lazy_message_field.cc
index 0de8cbe..abf8e55 100644
--- a/src/google/protobuf/compiler/java/java_lazy_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_lazy_message_field.cc
@@ -93,7 +93,7 @@
   printer->Print(variables_,
     // If this builder is non-null, it is used and the other fields are
     // ignored.
-    "private com.google.protobuf.SingleFieldBuilder<\n"
+    "private com.google.protobuf.SingleFieldBuilder$ver$<\n"
     "    $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
     "\n");
 
@@ -193,11 +193,11 @@
     "}\n");
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "private com.google.protobuf.SingleFieldBuilder<\n"
+    "private com.google.protobuf.SingleFieldBuilder$ver$<\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"
+    "    $name$Builder_ = new com.google.protobuf.SingleFieldBuilder$ver$<\n"
     "        $type$, $type$.Builder, $type$OrBuilder>(\n"
     "            $name$_,\n"
     "            getParentForChildren(),\n"
@@ -535,7 +535,7 @@
   printer->Print(variables_,
     // If this builder is non-null, it is used and the other fields are
     // ignored.
-    "private com.google.protobuf.RepeatedFieldBuilder<\n"
+    "private com.google.protobuf.RepeatedFieldBuilder$ver$<\n"
     "    $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
     "\n");
 
@@ -763,11 +763,11 @@
     "     get$capitalized_name$BuilderList() {\n"
     "  return get$capitalized_name$FieldBuilder().getBuilderList();\n"
     "}\n"
-    "private com.google.protobuf.RepeatedFieldBuilder<\n"
+    "private com.google.protobuf.RepeatedFieldBuilder$ver$<\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"
+    "    $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder$ver$<\n"
     "        $type$, $type$.Builder, $type$OrBuilder>(\n"
     "            $name$_,\n"
     "            $get_mutable_bit_builder$,\n"
diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc
index 283ba1d..51bb11f 100644
--- a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc
@@ -59,19 +59,28 @@
 void ImmutableLazyMessageFieldLiteGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private com.google.protobuf.LazyFieldLite $name$_ =\n"
-    "    new com.google.protobuf.LazyFieldLite();\n");
+    "private com.google.protobuf.LazyFieldLite $name$_;");
 
   PrintExtraFieldInfo(variables_, printer);
   WriteFieldDocComment(printer, descriptor_);
-  printer->Print(variables_,
-    "$deprecation$public boolean has$capitalized_name$() {\n"
-    "  return $get_has_field_bit_message$;\n"
-    "}\n");
+  if (SupportFieldPresence(descriptor_->file())) {
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $get_has_field_bit_message$;\n"
+      "}\n");
+  } else {
+    printer->Print(variables_,
+      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "  return $name$_ != null;\n"
+      "}\n");
+  }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "  if ($name$_ == null) {\n"
+    "    return $type$.getDefaultInstance();\n"
+    "  }\n"
     "  return ($type$) $name$_.getValue($type$.getDefaultInstance());\n"
    "}\n");
 
@@ -82,8 +91,11 @@
     "  if (value == null) {\n"
     "    throw new NullPointerException();\n"
     "  }\n"
+    "  if ($name$_ == null) {\n"
+    "    $name$_ = new com.google.protobuf.LazyFieldLite();\n"
+    "  }\n"
     "  $name$_.setValue(value);\n"
-    "  $set_has_field_bit_message$;\n"
+    "  $set_has_field_bit_message$\n"
     "}\n");
 
   // Field.Builder setField(Field.Builder builderForValue)
@@ -91,30 +103,36 @@
   printer->Print(variables_,
     "private void set$capitalized_name$(\n"
     "    $type$.Builder builderForValue) {\n"
+    "  if ($name$_ == null) {\n"
+    "    $name$_ = new com.google.protobuf.LazyFieldLite();\n"
+    "  }\n"
     "  $name$_.setValue(builderForValue.build());\n"
-    "  $set_has_field_bit_message$;\n"
+    "  $set_has_field_bit_message$\n"
     "}\n");
 
   // Field.Builder mergeField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "private void merge$capitalized_name$($type$ value) {\n"
-    "  if ($get_has_field_bit_message$ &&\n"
+    "  if (has$capitalized_name$() &&\n"
     "      !$name$_.containsDefaultInstance()) {\n"
     "    $name$_.setValue(\n"
     "      $type$.newBuilder(\n"
     "          get$capitalized_name$()).mergeFrom(value).buildPartial());\n"
     "  } else {\n"
+    "    if ($name$_ == null) {\n"
+    "      $name$_ = new com.google.protobuf.LazyFieldLite();\n"
+    "    }\n"
     "    $name$_.setValue(value);\n"
+    "    $set_has_field_bit_message$\n"
     "  }\n"
-    "  $set_has_field_bit_message$;\n"
     "}\n");
 
   // Field.Builder clearField()
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "private void clear$capitalized_name$() {\n"
-    "  $name$_.clear();\n"
+    "  $name$_ = null;\n"
     "  $clear_has_field_bit_message$;\n"
     "}\n");
 }
@@ -177,32 +195,30 @@
 
 
 void ImmutableLazyMessageFieldLiteGenerator::
-GenerateInitializationCode(io::Printer* printer) const {
-  printer->Print(variables_, "$name$_.clear();\n");
-}
+GenerateInitializationCode(io::Printer* printer) const {}
 
 void ImmutableLazyMessageFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
+GenerateVisitCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (other.has$capitalized_name$()) {\n"
-    "  $name$_.merge(other.$name$_);\n"
-    "  $set_has_field_bit_message$;\n"
-    "}\n");
+    "$name$_ = visitor.visitLazyMessage($name$_, other.$name$_);\n");
 }
 
 void ImmutableLazyMessageFieldLiteGenerator::
 GenerateParsingCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "$name$_.setByteString(input.readBytes(), extensionRegistry);\n");
+    "if ($name$_ == null) {\n"
+    "  $name$_ = new com.google.protobuf.LazyFieldLite();\n"
+    "}\n"
+    "$name$_.mergeFrom(input, extensionRegistry);\n");
   printer->Print(variables_,
-    "$set_has_field_bit_message$;\n");
+    "$set_has_field_bit_message$\n");
 }
 
 void ImmutableLazyMessageFieldLiteGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
   // Do not de-serialize lazy fields.
   printer->Print(variables_,
-    "if ($get_has_field_bit_message$) {\n"
+    "if (has$capitalized_name$()) {\n"
     "  output.writeBytes($number$, $name$_.toByteString());\n"
     "}\n");
 }
@@ -210,12 +226,13 @@
 void ImmutableLazyMessageFieldLiteGenerator::
 GenerateSerializedSizeCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if ($get_has_field_bit_message$) {\n"
+    "if (has$capitalized_name$()) {\n"
     "  size += com.google.protobuf.CodedOutputStream\n"
     "    .computeLazyFieldSize($number$, $name$_);\n"
     "}\n");
 }
 
+
 // ===================================================================
 
 ImmutableLazyMessageOneofFieldLiteGenerator::
@@ -362,14 +379,12 @@
 }
 
 void ImmutableLazyMessageOneofFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
+GenerateVisitCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (!($has_oneof_case_message$)) {\n"
-    "  $oneof_name$_ = new $lazy_type$();\n"
-    "}\n"
-    "(($lazy_type$) $oneof_name$_).merge(\n"
-    "    ($lazy_type$) other.$oneof_name$_);\n"
-    "$set_oneof_case_message$;\n");
+    "$oneof_name$_ = visitor.visitOneofLazyMessage(\n"
+    "    $has_oneof_case_message$,\n"
+    "    ($lazy_type$) $oneof_name$_,\n"
+    "    ($lazy_type$) other.$oneof_name$_);\n");
 }
 
 void ImmutableLazyMessageOneofFieldLiteGenerator::
@@ -378,8 +393,7 @@
     "if (!($has_oneof_case_message$)) {\n"
     "  $oneof_name$_ = new $lazy_type$();\n"
     "}\n"
-    "(($lazy_type$) $oneof_name$_).setByteString(\n"
-    "    input.readBytes(), extensionRegistry);\n"
+    "(($lazy_type$) $oneof_name$_).mergeFrom(input, extensionRegistry);\n"
     "$set_oneof_case_message$;\n");
 }
 
@@ -402,6 +416,7 @@
     "}\n");
 }
 
+
 // ===================================================================
 
 RepeatedImmutableLazyMessageFieldLiteGenerator::
@@ -433,8 +448,7 @@
     "  for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n"
     "    list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n"
     "  }\n"
-    // TODO(dweis): Make this list immutable?
-    "  return list;\n"
+    "  return java.util.Collections.unmodifiableList(list);\n"
     "}\n");
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
@@ -464,7 +478,8 @@
   printer->Print(variables_,
     "private void ensure$capitalized_name$IsMutable() {\n"
     "  if (!$is_mutable$) {\n"
-    "    $name$_ = newProtobufList($name$_);\n"
+    "    $name$_ =\n"
+    "        com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
     "   }\n"
     "}\n"
     "\n");
@@ -679,7 +694,8 @@
 GenerateParsingCode(io::Printer* printer) const {
   printer->Print(variables_,
     "if (!$is_mutable$) {\n"
-    "  $name$_ = newProtobufList();\n"
+    "  $name$_ =\n"
+    "      com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
     "}\n"
     "$name$_.add(new com.google.protobuf.LazyFieldLite(\n"
     "    extensionRegistry, input.readBytes()));\n");
@@ -702,6 +718,7 @@
     "}\n");
 }
 
+
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h
index e85ec0f..65b84fb 100644
--- a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h
@@ -63,11 +63,12 @@
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
 
+
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageFieldLiteGenerator);
 };
@@ -82,11 +83,12 @@
 
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
 
+
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageOneofFieldLiteGenerator);
 };
@@ -106,6 +108,7 @@
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
 
+
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableLazyMessageFieldLiteGenerator);
 };
diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc
index 3e035c8..b22a219 100644
--- a/src/google/protobuf/compiler/java/java_map_field.cc
+++ b/src/google/protobuf/compiler/java/java_map_field.cc
@@ -79,19 +79,31 @@
                          int messageBitIndex,
                          int builderBitIndex,
                          const FieldGeneratorInfo* info,
-                         ClassNameResolver* name_resolver,
-                         map<string, string>* variables) {
+                         Context* context,
+                         std::map<string, string>* variables) {
   SetCommonFieldVariables(descriptor, info, variables);
+  ClassNameResolver* name_resolver = context->GetNameResolver();
 
   (*variables)["type"] =
       name_resolver->GetImmutableClassName(descriptor->message_type());
   const FieldDescriptor* key = KeyField(descriptor);
   const FieldDescriptor* value = ValueField(descriptor);
+  const JavaType keyJavaType = GetJavaType(key);
+  const JavaType valueJavaType = GetJavaType(value);
+
   (*variables)["key_type"] = TypeName(key, name_resolver, false);
-  (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true);
+  string boxed_key_type = TypeName(key, name_resolver, true);
+  (*variables)["boxed_key_type"] = boxed_key_type;
+  // Used for calling the serialization function.
+  (*variables)["short_key_type"] =
+      boxed_key_type.substr(boxed_key_type.rfind('.') + 1);
   (*variables)["key_wire_type"] = WireType(key);
   (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver);
-  if (GetJavaType(value) == JAVATYPE_ENUM) {
+  (*variables)["key_null_check"] = IsReferenceType(keyJavaType) ?
+      "if (key == null) { throw new java.lang.NullPointerException(); }" : "";
+  (*variables)["value_null_check"] = IsReferenceType(valueJavaType) ?
+      "if (value == null) { throw new java.lang.NullPointerException(); }" : "";
+  if (valueJavaType == JAVATYPE_ENUM) {
     // We store enums as Integers internally.
     (*variables)["value_type"] = "int";
     (*variables)["boxed_value_type"] = "java.lang.Integer";
@@ -123,8 +135,7 @@
   // by the proto compiler
   (*variables)["deprecation"] = descriptor->options().deprecated()
       ? "@java.lang.Deprecated " : "";
-  (*variables)["on_changed"] =
-      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+  (*variables)["on_changed"] = "onChanged();";
 
   // For repeated fields, one bit is used for whether the array is immutable
   // in the parsing constructor.
@@ -135,18 +146,12 @@
 
   (*variables)["default_entry"] = (*variables)["capitalized_name"] +
       "DefaultEntryHolder.defaultEntry";
-  if (HasDescriptorMethods(descriptor->file())) {
-    (*variables)["lite"] = "";
-    (*variables)["map_field_parameter"] = (*variables)["default_entry"];
-    (*variables)["descriptor"] =
-        name_resolver->GetImmutableClassName(descriptor->file()) +
-        ".internal_" + UniqueFileScopeIdentifier(descriptor->message_type()) +
-        "_descriptor, ";
-  } else {
-    (*variables)["lite"] = "Lite";
-    (*variables)["map_field_parameter"] = "";
-    (*variables)["descriptor"] = "";
-  }
+  (*variables)["map_field_parameter"] = (*variables)["default_entry"];
+  (*variables)["descriptor"] =
+      name_resolver->GetImmutableClassName(descriptor->file()) +
+      ".internal_" + UniqueFileScopeIdentifier(descriptor->message_type()) +
+      "_descriptor, ";
+  (*variables)["ver"] = GeneratedCodeVersionSuffix();
 }
 
 }  // namespace
@@ -159,7 +164,7 @@
   : descriptor_(descriptor), name_resolver_(context->GetNameResolver())  {
   SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
                       context->GetFieldGeneratorInfo(descriptor),
-                      name_resolver_, &variables_);
+                      context, &variables_);
 }
 
 ImmutableMapFieldGenerator::
@@ -175,25 +180,109 @@
 
 void ImmutableMapFieldGenerator::
 GenerateInterfaceMembers(io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecation$int ${$get$capitalized_name$Count$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecation$boolean ${$contains$capitalized_name$$}$(\n"
+      "    $key_type$ key);\n");
+  printer->Annotate("{", "}", descriptor_);
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+    printer->Print(
+        variables_,
+        "/**\n"
+        " * Use {@link #get$capitalized_name$Map()} instead.\n"
+        " */\n"
+        "@java.lang.Deprecated\n"
+        "java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+        "${$get$capitalized_name$$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "get$capitalized_name$();\n");
+        "${$get$capitalized_name$Map$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$$value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+        "    $key_type$ key,\n"
+        "    $value_enum_type$ defaultValue);\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$$value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+        "    $key_type$ key);\n");
+    printer->Annotate("{", "}", descriptor_);
     if (SupportUnknownEnumValue(descriptor_->file())) {
+      printer->Print(
+          variables_,
+          "/**\n"
+          " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
+          " */\n"
+          "@java.lang.Deprecated\n"
+          "java.util.Map<$type_parameters$>\n"
+          "${$get$capitalized_name$Value$}$();\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
           "$deprecation$java.util.Map<$type_parameters$>\n"
-          "get$capitalized_name$Value();\n");
+          "${$get$capitalized_name$ValueMap$}$();\n");
+      printer->Annotate("{", "}", descriptor_);
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$\n"
+          "$value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
+          "    $key_type$ key,\n"
+          "    $value_type$ defaultValue);\n");
+      printer->Annotate("{", "}", descriptor_);
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$\n"
+          "$value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
+          "    $key_type$ key);\n");
+      printer->Annotate("{", "}", descriptor_);
     }
   } else {
+    printer->Print(
+        variables_,
+        "/**\n"
+        " * Use {@link #get$capitalized_name$Map()} instead.\n"
+        " */\n"
+        "@java.lang.Deprecated\n"
+        "java.util.Map<$type_parameters$>\n"
+        "${$get$capitalized_name$$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$java.util.Map<$type_parameters$>\n"
-        "get$capitalized_name$();\n");
+        "${$get$capitalized_name$Map$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "$value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+        "    $key_type$ key,\n"
+        "    $value_type$ defaultValue);\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "$value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+        "    $key_type$ key);\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 }
 
@@ -202,9 +291,9 @@
   printer->Print(
       variables_,
       "private static final class $capitalized_name$DefaultEntryHolder {\n"
-      "  static final com.google.protobuf.MapEntry$lite$<\n"
+      "  static final com.google.protobuf.MapEntry<\n"
       "      $type_parameters$> defaultEntry =\n"
-      "          com.google.protobuf.MapEntry$lite$\n"
+      "          com.google.protobuf.MapEntry\n"
       "          .<$type_parameters$>newDefaultInstance(\n"
       "              $descriptor$\n"
       "              $key_wire_type$,\n"
@@ -214,14 +303,14 @@
       "}\n");
   printer->Print(
       variables_,
-      "private com.google.protobuf.MapField$lite$<\n"
+      "private com.google.protobuf.MapField<\n"
       "    $type_parameters$> $name$_;\n"
-      "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+      "private com.google.protobuf.MapField<$type_parameters$>\n"
       "internalGet$capitalized_name$() {\n"
       "  if ($name$_ == null) {\n"
-      "    return com.google.protobuf.MapField$lite$.emptyMapField(\n"
+      "    return com.google.protobuf.MapField.emptyMapField(\n"
       "        $map_field_parameter$);\n"
-      " }\n"
+      "  }\n"
       "  return $name$_;\n"
       "}\n");
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
@@ -233,57 +322,39 @@
         "        com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n"
         "            $value_enum_type$.internalGetValueMap(),\n"
         "            $unrecognized_value$);\n");
-    if (SupportUnknownEnumValue(descriptor_->file())) {
-      WriteFieldDocComment(printer, descriptor_);
-      printer->Print(
-          variables_,
-          "$deprecation$\n"
-          "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
-          "get$capitalized_name$Value() {\n"
-          "  return internalGet$capitalized_name$().getMap();\n"
-          "}\n");
-    }
-    WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
-        "$deprecation$\n"
-        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "get$capitalized_name$() {\n"
+        "private static final java.util.Map<$boxed_key_type$, "
+        "$value_enum_type$>\n"
+        "internalGetAdapted$capitalized_name$Map(\n"
+        "    java.util.Map<$boxed_key_type$, $boxed_value_type$> map) {\n"
         "  return new com.google.protobuf.Internal.MapAdapter<\n"
         "      $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
-        "          internalGet$capitalized_name$().getMap(),\n"
-        "          $name$ValueConverter);\n"
-        "}\n");
-  } else {
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(
-        variables_,
-        "$deprecation$\n"
-        "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
-        "  return internalGet$capitalized_name$().getMap();\n"
+        "          map, $name$ValueConverter);\n"
         "}\n");
   }
+  GenerateMapGetters(printer);
 }
 
 void ImmutableMapFieldGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
   printer->Print(
       variables_,
-      "private com.google.protobuf.MapField$lite$<\n"
+      "private com.google.protobuf.MapField<\n"
       "    $type_parameters$> $name$_;\n"
-      "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+      "private com.google.protobuf.MapField<$type_parameters$>\n"
       "internalGet$capitalized_name$() {\n"
       "  if ($name$_ == null) {\n"
-      "    return com.google.protobuf.MapField$lite$.emptyMapField(\n"
+      "    return com.google.protobuf.MapField.emptyMapField(\n"
       "        $map_field_parameter$);\n"
-      " }\n"
+      "  }\n"
       "  return $name$_;\n"
       "}\n"
-      "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+      "private com.google.protobuf.MapField<$type_parameters$>\n"
       "internalGetMutable$capitalized_name$() {\n"
       "  $on_changed$;\n"
       "  if ($name$_ == null) {\n"
-      "    $name$_ = com.google.protobuf.MapField$lite$.newMapField(\n"
+      "    $name$_ = com.google.protobuf.MapField.newMapField(\n"
       "        $map_field_parameter$);\n"
       "  }\n"
       "  if (!$name$_.isMutable()) {\n"
@@ -291,85 +362,309 @@
       "  }\n"
       "  return $name$_;\n"
       "}\n");
+  GenerateMapGetters(printer);
+  printer->Print(
+      variables_,
+      "$deprecation$\n"
+      "public Builder ${$clear$capitalized_name$$}$() {\n"
+      "  internalGetMutable$capitalized_name$().getMutableMap()\n"
+      "      .clear();\n"
+      "  return this;\n"
+      "}\n");
+  printer->Annotate("{", "}", descriptor_);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecation$\n"
+      "public Builder ${$remove$capitalized_name$$}$(\n"
+      "    $key_type$ key) {\n"
+      "  $key_null_check$\n"
+      "  internalGetMutable$capitalized_name$().getMutableMap()\n"
+      "      .remove(key);\n"
+      "  return this;\n"
+      "}\n");
+  printer->Annotate("{", "}", descriptor_);
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
-    WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
-        "$deprecation$\n"
+        "/**\n"
+        " * Use alternate mutation accessors instead.\n"
+        " */\n"
+        "@java.lang.Deprecated\n"
         "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "get$capitalized_name$() {\n"
-        "  return new com.google.protobuf.Internal.MapAdapter<\n"
-        "      $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
-        "          internalGet$capitalized_name$().getMap(),\n"
-        "          $name$ValueConverter);\n"
+        "${$getMutable$capitalized_name$$}$() {\n"
+        "  return internalGetAdapted$capitalized_name$Map(\n"
+        "       internalGetMutable$capitalized_name$().getMutableMap());\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(variables_,
+                   "$deprecation$public Builder ${$put$capitalized_name$$}$(\n"
+                   "    $key_type$ key,\n"
+                   "    $value_enum_type$ value) {\n"
+                   "  $key_null_check$\n"
+                   "  $value_null_check$\n"
+                   "  internalGetMutable$capitalized_name$().getMutableMap()\n"
+                   "      .put(key, $name$ValueConverter.doBackward(value));\n"
+                   "  return this;\n"
+                   "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
-        "$deprecation$\n"
-        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "getMutable$capitalized_name$() {\n"
-        "  return new com.google.protobuf.Internal.MapAdapter<\n"
-        "      $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
-        "          internalGetMutable$capitalized_name$().getMutableMap(),\n"
-        "          $name$ValueConverter);\n"
-        "}\n");
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(
-        variables_,
-        "$deprecation$public Builder putAll$capitalized_name$(\n"
+        "$deprecation$public Builder ${$putAll$capitalized_name$$}$(\n"
         "    java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
-        "  getMutable$capitalized_name$().putAll(values);\n"
+        "  internalGetAdapted$capitalized_name$Map(\n"
+        "      internalGetMutable$capitalized_name$().getMutableMap())\n"
+        "          .putAll(values);\n"
         "  return this;\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     if (SupportUnknownEnumValue(descriptor_->file())) {
-      WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
-          "$deprecation$\n"
+          "/**\n"
+          " * Use alternate mutation accessors instead.\n"
+          " */\n"
+          "@java.lang.Deprecated\n"
           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
-          "get$capitalized_name$Value() {\n"
-          "  return internalGet$capitalized_name$().getMap();\n"
-          "}\n");
-      WriteFieldDocComment(printer, descriptor_);
-      printer->Print(
-          variables_,
-          "$deprecation$\n"
-          "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
-          "getMutable$capitalized_name$Value() {\n"
+          "${$getMutable$capitalized_name$Value$}$() {\n"
           "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
-          "$deprecation$public Builder putAll$capitalized_name$Value(\n"
-          "    java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
-          "  getMutable$capitalized_name$Value().putAll(values);\n"
+          "$deprecation$public Builder ${$put$capitalized_name$Value$}$(\n"
+          "    $key_type$ key,\n"
+          "    $value_type$ value) {\n"
+          "  $key_null_check$\n"
+          "  internalGetMutable$capitalized_name$().getMutableMap()\n"
+          "      .put(key, value);\n"
           "  return this;\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$public Builder ${$putAll$capitalized_name$Value$}$(\n"
+          "    java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
+          "  internalGetMutable$capitalized_name$().getMutableMap()\n"
+          "      .putAll(values);\n"
+          "  return this;\n"
+          "}\n");
+      printer->Annotate("{", "}", descriptor_);
     }
   } else {
-    WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
-        "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
-        "  return internalGet$capitalized_name$().getMap();\n"
-        "}\n");
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(
-        variables_,
+        "/**\n"
+        " * Use alternate mutation accessors instead.\n"
+        " */\n"
+        "@java.lang.Deprecated\n"
         "public java.util.Map<$type_parameters$>\n"
-        "getMutable$capitalized_name$() {\n"
+        "${$getMutable$capitalized_name$$}$() {\n"
         "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
-        "$deprecation$public Builder putAll$capitalized_name$(\n"
-        "    java.util.Map<$type_parameters$> values) {\n"
-        "  getMutable$capitalized_name$().putAll(values);\n"
+        "$deprecation$"
+        "public Builder ${$put$capitalized_name$$}$(\n"
+        "    $key_type$ key,\n"
+        "    $value_type$ value) {\n"
+        "  $key_null_check$\n"
+        "  $value_null_check$\n"
+        "  internalGetMutable$capitalized_name$().getMutableMap()\n"
+        "      .put(key, value);\n"
         "  return this;\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "public Builder ${$putAll$capitalized_name$$}$(\n"
+        "    java.util.Map<$type_parameters$> values) {\n"
+        "  internalGetMutable$capitalized_name$().getMutableMap()\n"
+        "      .putAll(values);\n"
+        "  return this;\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+  }
+}
+
+void ImmutableMapFieldGenerator::
+GenerateMapGetters(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "$deprecation$\n"
+      "public int ${$get$capitalized_name$Count$}$() {\n"
+      "  return internalGet$capitalized_name$().getMap().size();\n"
+      "}\n");
+  printer->Annotate("{", "}", descriptor_);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecation$\n"
+      "public boolean ${$contains$capitalized_name$$}$(\n"
+      "    $key_type$ key) {\n"
+      "  $key_null_check$\n"
+      "  return internalGet$capitalized_name$().getMap().containsKey(key);\n"
+      "}\n");
+  printer->Annotate("{", "}", descriptor_);
+  if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+    printer->Print(
+        variables_,
+        "/**\n"
+        " * Use {@link #get$capitalized_name$Map()} instead.\n"
+        " */\n"
+        "@java.lang.Deprecated\n"
+        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+        "${$get$capitalized_name$$}$() {\n"
+        "  return get$capitalized_name$Map();\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+        "${$get$capitalized_name$Map$}$() {\n"
+        "  return internalGetAdapted$capitalized_name$Map(\n"
+        "      internalGet$capitalized_name$().getMap());"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "public $value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+        "    $key_type$ key,\n"
+        "    $value_enum_type$ defaultValue) {\n"
+        "  $key_null_check$\n"
+        "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+        "      internalGet$capitalized_name$().getMap();\n"
+        "  return map.containsKey(key)\n"
+        "         ? $name$ValueConverter.doForward(map.get(key))\n"
+        "         : defaultValue;\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+        "    $key_type$ key) {\n"
+        "  $key_null_check$\n"
+        "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+        "      internalGet$capitalized_name$().getMap();\n"
+        "  if (!map.containsKey(key)) {\n"
+        "    throw new java.lang.IllegalArgumentException();\n"
+        "  }\n"
+        "  return $name$ValueConverter.doForward(map.get(key));\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    if (SupportUnknownEnumValue(descriptor_->file())) {
+      printer->Print(
+          variables_,
+          "/**\n"
+          " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
+          " */\n"
+          "@java.lang.Deprecated\n"
+          "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+          "${$get$capitalized_name$Value$}$() {\n"
+          "  return get$capitalized_name$ValueMap();\n"
+          "}\n");
+      printer->Annotate("{", "}", descriptor_);
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$\n"
+          "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+          "${$get$capitalized_name$ValueMap$}$() {\n"
+          "  return internalGet$capitalized_name$().getMap();\n"
+          "}\n");
+      printer->Annotate("{", "}", descriptor_);
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$\n"
+          "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
+          "    $key_type$ key,\n"
+          "    $value_type$ defaultValue) {\n"
+          "  $key_null_check$\n"
+          "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+          "      internalGet$capitalized_name$().getMap();\n"
+          "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
+          "}\n");
+      printer->Annotate("{", "}", descriptor_);
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$\n"
+          "public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
+          "    $key_type$ key) {\n"
+          "  $key_null_check$\n"
+          "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+          "      internalGet$capitalized_name$().getMap();\n"
+          "  if (!map.containsKey(key)) {\n"
+          "    throw new java.lang.IllegalArgumentException();\n"
+          "  }\n"
+          "  return map.get(key);\n"
+          "}\n");
+      printer->Annotate("{", "}", descriptor_);
+    }
+  } else {
+    printer->Print(
+        variables_,
+        "/**\n"
+        " * Use {@link #get$capitalized_name$Map()} instead.\n"
+        " */\n"
+        "@java.lang.Deprecated\n"
+        "public java.util.Map<$type_parameters$> "
+        "${$get$capitalized_name$$}$() {\n"
+        "  return get$capitalized_name$Map();\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "public java.util.Map<$type_parameters$> "
+        "${$get$capitalized_name$Map$}$() {\n"
+        "  return internalGet$capitalized_name$().getMap();\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+        "    $key_type$ key,\n"
+        "    $value_type$ defaultValue) {\n"
+        "  $key_null_check$\n"
+        "  java.util.Map<$type_parameters$> map =\n"
+        "      internalGet$capitalized_name$().getMap();\n"
+        "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+        "    $key_type$ key) {\n"
+        "  $key_null_check$\n"
+        "  java.util.Map<$type_parameters$> map =\n"
+        "      internalGet$capitalized_name$().getMap();\n"
+        "  if (!map.containsKey(key)) {\n"
+        "    throw new java.lang.IllegalArgumentException();\n"
+        "  }\n"
+        "  return map.get(key);\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 }
 
@@ -411,7 +706,7 @@
   printer->Print(
       variables_,
       "if (!$get_mutable_bit_parser$) {\n"
-      "  $name$_ = com.google.protobuf.MapField$lite$.newMapField(\n"
+      "  $name$_ = com.google.protobuf.MapField.newMapField(\n"
       "      $map_field_parameter$);\n"
       "  $set_mutable_bit_parser$;\n"
       "}\n");
@@ -420,22 +715,24 @@
     printer->Print(
         variables_,
         "com.google.protobuf.ByteString bytes = input.readBytes();\n"
-        "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
-        "$name$ = $default_entry$.getParserForType().parseFrom(bytes);\n");
+        "com.google.protobuf.MapEntry<$type_parameters$>\n"
+        "$name$__ = $default_entry$.getParserForType().parseFrom(bytes);\n");
     printer->Print(
         variables_,
-        "if ($value_enum_type$.valueOf($name$.getValue()) == null) {\n"
+        "if ($value_enum_type$.forNumber($name$__.getValue()) == null) {\n"
         "  unknownFields.mergeLengthDelimitedField($number$, bytes);\n"
         "} else {\n"
-        "  $name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"
+        "  $name$_.getMutableMap().put(\n"
+        "      $name$__.getKey(), $name$__.getValue());\n"
         "}\n");
   } else {
     printer->Print(
         variables_,
-        "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
-        "$name$ = input.readMessage(\n"
+        "com.google.protobuf.MapEntry<$type_parameters$>\n"
+        "$name$__ = input.readMessage(\n"
         "    $default_entry$.getParserForType(), extensionRegistry);\n"
-        "$name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n");
+        "$name$_.getMutableMap().put(\n"
+        "    $name$__.getKey(), $name$__.getValue());\n");
   }
 }
 
@@ -448,15 +745,12 @@
 GenerateSerializationCode(io::Printer* printer) const {
   printer->Print(
       variables_,
-      "for (java.util.Map.Entry<$type_parameters$> entry\n"
-      "     : internalGet$capitalized_name$().getMap().entrySet()) {\n"
-      "  com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
-      "  $name$ = $default_entry$.newBuilderForType()\n"
-      "      .setKey(entry.getKey())\n"
-      "      .setValue(entry.getValue())\n"
-      "      .build();\n"
-      "  output.writeMessage($number$, $name$);\n"
-      "}\n");
+      "com.google.protobuf.GeneratedMessage$ver$\n"
+      "  .serialize$short_key_type$MapTo(\n"
+      "    output,\n"
+      "    internalGet$capitalized_name$(),\n"
+      "    $default_entry$,\n"
+      "    $number$);\n");
 }
 
 void ImmutableMapFieldGenerator::
@@ -465,13 +759,13 @@
       variables_,
       "for (java.util.Map.Entry<$type_parameters$> entry\n"
       "     : internalGet$capitalized_name$().getMap().entrySet()) {\n"
-      "  com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
-      "  $name$ = $default_entry$.newBuilderForType()\n"
+      "  com.google.protobuf.MapEntry<$type_parameters$>\n"
+      "  $name$__ = $default_entry$.newBuilderForType()\n"
       "      .setKey(entry.getKey())\n"
       "      .setValue(entry.getValue())\n"
       "      .build();\n"
       "  size += com.google.protobuf.CodedOutputStream\n"
-      "      .computeMessageSize($number$, $name$);\n"
+      "      .computeMessageSize($number$, $name$__);\n"
       "}\n");
 }
 
diff --git a/src/google/protobuf/compiler/java/java_map_field.h b/src/google/protobuf/compiler/java/java_map_field.h
index f2768f3..4702174 100644
--- a/src/google/protobuf/compiler/java/java_map_field.h
+++ b/src/google/protobuf/compiler/java/java_map_field.h
@@ -67,8 +67,9 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   ClassNameResolver* name_resolver_;
+  void GenerateMapGetters(io::Printer* printer) const;
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.cc b/src/google/protobuf/compiler/java/java_map_field_lite.cc
index d203940..e2e6807 100644
--- a/src/google/protobuf/compiler/java/java_map_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc
@@ -79,18 +79,27 @@
                          int messageBitIndex,
                          int builderBitIndex,
                          const FieldGeneratorInfo* info,
-                         ClassNameResolver* name_resolver,
-                         map<string, string>* variables) {
+                         Context* context,
+                         std::map<string, string>* variables) {
   SetCommonFieldVariables(descriptor, info, variables);
 
+  ClassNameResolver* name_resolver = context->GetNameResolver();
   (*variables)["type"] =
       name_resolver->GetImmutableClassName(descriptor->message_type());
   const FieldDescriptor* key = KeyField(descriptor);
   const FieldDescriptor* value = ValueField(descriptor);
+  const JavaType keyJavaType = GetJavaType(key);
+  const JavaType valueJavaType = GetJavaType(value);
+
   (*variables)["key_type"] = TypeName(key, name_resolver, false);
   (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true);
   (*variables)["key_wire_type"] = WireType(key);
   (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver);
+  (*variables)["key_null_check"] = IsReferenceType(keyJavaType) ?
+      "if (key == null) { throw new java.lang.NullPointerException(); }" : "";
+  (*variables)["value_null_check"] = IsReferenceType(valueJavaType) ?
+      "if (value == null) { throw new java.lang.NullPointerException(); }" : "";
+
   if (GetJavaType(value) == JAVATYPE_ENUM) {
     // We store enums as Integers internally.
     (*variables)["value_type"] = "int";
@@ -123,13 +132,9 @@
   // by the proto compiler
   (*variables)["deprecation"] = descriptor->options().deprecated()
       ? "@java.lang.Deprecated " : "";
-  (*variables)["on_changed"] =
-      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
 
   (*variables)["default_entry"] = (*variables)["capitalized_name"] +
       "DefaultEntryHolder.defaultEntry";
-  (*variables)["lite"] = "Lite";
-  (*variables)["descriptor"] = "";
 }
 
 }  // namespace
@@ -142,7 +147,7 @@
   : descriptor_(descriptor), name_resolver_(context->GetNameResolver())  {
   SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
                       context->GetFieldGeneratorInfo(descriptor),
-                      name_resolver_, &variables_);
+                      context, &variables_);
 }
 
 ImmutableMapFieldLiteGenerator::
@@ -158,25 +163,109 @@
 
 void ImmutableMapFieldLiteGenerator::
 GenerateInterfaceMembers(io::Printer* printer) const {
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecation$int ${$get$capitalized_name$Count$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecation$boolean ${$contains$capitalized_name$$}$(\n"
+      "    $key_type$ key);\n");
+  printer->Annotate("{", "}", descriptor_);
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+    printer->Print(
+        variables_,
+        "/**\n"
+        " * Use {@link #get$capitalized_name$Map()} instead.\n"
+        " */\n"
+        "@java.lang.Deprecated\n"
+        "java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+        "${$get$capitalized_name$$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "get$capitalized_name$();\n");
+        "${$get$capitalized_name$Map$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$$value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+        "    $key_type$ key,\n"
+        "    $value_enum_type$ defaultValue);\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$$value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+        "    $key_type$ key);\n");
+    printer->Annotate("{", "}", descriptor_);
     if (SupportUnknownEnumValue(descriptor_->file())) {
+      printer->Print(
+          variables_,
+          "/**\n"
+          " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
+          " */\n"
+          "@java.lang.Deprecated\n"
+          "java.util.Map<$type_parameters$>\n"
+          "${$get$capitalized_name$Value$}$();\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
           "$deprecation$java.util.Map<$type_parameters$>\n"
-          "get$capitalized_name$Value();\n");
+          "${$get$capitalized_name$ValueMap$}$();\n");
+      printer->Annotate("{", "}", descriptor_);
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$\n"
+          "$value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
+          "    $key_type$ key,\n"
+          "    $value_type$ defaultValue);\n");
+      printer->Annotate("{", "}", descriptor_);
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$\n"
+          "$value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
+          "    $key_type$ key);\n");
+      printer->Annotate("{", "}", descriptor_);
     }
   } else {
+    printer->Print(
+        variables_,
+        "/**\n"
+        " * Use {@link #get$capitalized_name$Map()} instead.\n"
+        " */\n"
+        "@java.lang.Deprecated\n"
+        "java.util.Map<$type_parameters$>\n"
+        "${$get$capitalized_name$$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$java.util.Map<$type_parameters$>\n"
-        "get$capitalized_name$();\n");
+        "${$get$capitalized_name$Map$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "$value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+        "    $key_type$ key,\n"
+        "    $value_type$ defaultValue);\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "$value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+        "    $key_type$ key);\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 }
 
@@ -185,11 +274,10 @@
   printer->Print(
       variables_,
       "private static final class $capitalized_name$DefaultEntryHolder {\n"
-      "  static final com.google.protobuf.MapEntry$lite$<\n"
+      "  static final com.google.protobuf.MapEntryLite<\n"
       "      $type_parameters$> defaultEntry =\n"
-      "          com.google.protobuf.MapEntry$lite$\n"
+      "          com.google.protobuf.MapEntryLite\n"
       "          .<$type_parameters$>newDefaultInstance(\n"
-      "              $descriptor$\n"
       "              $key_wire_type$,\n"
       "              $key_default_value$,\n"
       "              $value_wire_type$,\n"
@@ -197,20 +285,39 @@
       "}\n");
   printer->Print(
       variables_,
-      "private com.google.protobuf.MapField$lite$<\n"
+      "private com.google.protobuf.MapFieldLite<\n"
       "    $type_parameters$> $name$_ =\n"
-      "        com.google.protobuf.MapField$lite$.emptyMapField();\n"
-      "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+      "        com.google.protobuf.MapFieldLite.emptyMapField();\n"
+      "private com.google.protobuf.MapFieldLite<$type_parameters$>\n"
       "internalGet$capitalized_name$() {\n"
       "  return $name$_;\n"
       "}\n"
-      "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+      "private com.google.protobuf.MapFieldLite<$type_parameters$>\n"
       "internalGetMutable$capitalized_name$() {\n"
       "  if (!$name$_.isMutable()) {\n"
-      "    $name$_ = $name$_.copy();\n"
+      "    $name$_ = $name$_.mutableCopy();\n"
       "  }\n"
       "  return $name$_;\n"
       "}\n");
+  printer->Print(
+      variables_,
+      "@java.lang.Override\n"
+      "$deprecation$\n"
+      "public int ${$get$capitalized_name$Count$}$() {\n"
+      "  return internalGet$capitalized_name$().size();\n"
+      "}\n");
+  printer->Annotate("{", "}", descriptor_);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "@java.lang.Override\n"
+      "$deprecation$\n"
+      "public boolean ${$contains$capitalized_name$$}$(\n"
+      "    $key_type$ key) {\n"
+      "  $key_null_check$\n"
+      "  return internalGet$capitalized_name$().containsKey(key);\n"
+      "}\n");
+  printer->Annotate("{", "}", descriptor_);
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
     printer->Print(
         variables_,
@@ -220,35 +327,172 @@
         "        com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n"
         "            $value_enum_type$.internalGetValueMap(),\n"
         "            $unrecognized_value$);\n");
+    printer->Print(
+        variables_,
+        "/**\n"
+        " * Use {@link #get$capitalized_name$Map()} instead.\n"
+        " */\n"
+        "@java.lang.Deprecated\n"
+        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+        "${$get$capitalized_name$$}$() {\n"
+        "  return get$capitalized_name$Map();\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "@java.lang.Override\n"
+        "$deprecation$\n"
+        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+        "${$get$capitalized_name$Map$}$() {\n"
+        "  return java.util.Collections.unmodifiableMap(\n"
+        "      new com.google.protobuf.Internal.MapAdapter<\n"
+        "        $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
+        "            internalGet$capitalized_name$(),\n"
+        "            $name$ValueConverter));\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "@java.lang.Override\n"
+        "$deprecation$\n"
+        "public $value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+        "    $key_type$ key,\n"
+        "    $value_enum_type$ defaultValue) {\n"
+        "  $key_null_check$\n"
+        "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+        "      internalGet$capitalized_name$();\n"
+        "  return map.containsKey(key)\n"
+        "         ? $name$ValueConverter.doForward(map.get(key))\n"
+        "         : defaultValue;\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "@java.lang.Override\n"
+        "$deprecation$\n"
+        "public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+        "    $key_type$ key) {\n"
+        "  $key_null_check$\n"
+        "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+        "      internalGet$capitalized_name$();\n"
+        "  if (!map.containsKey(key)) {\n"
+        "    throw new java.lang.IllegalArgumentException();\n"
+        "  }\n"
+        "  return $name$ValueConverter.doForward(map.get(key));\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
     if (SupportUnknownEnumValue(descriptor_->file())) {
+      printer->Print(
+          variables_,
+          "/**\n"
+          " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
+          " */\n"
+          "@java.lang.Override\n"
+          "@java.lang.Deprecated\n"
+          "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+          "${$get$capitalized_name$Value$}$() {\n"
+          "  return get$capitalized_name$ValueMap();\n"
+          "}\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
+          "@java.lang.Override\n"
           "$deprecation$\n"
           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
-          "get$capitalized_name$Value() {\n"
-          "  return internalGet$capitalized_name$().getMap();\n"
+          "${$get$capitalized_name$ValueMap$}$() {\n"
+          "  return java.util.Collections.unmodifiableMap(\n"
+          "      internalGet$capitalized_name$());\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "@java.lang.Override\n"
+          "$deprecation$\n"
+          "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
+          "    $key_type$ key,\n"
+          "    $value_type$ defaultValue) {\n"
+          "  $key_null_check$\n"
+          "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+          "      internalGet$capitalized_name$();\n"
+          "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
+          "}\n");
+      printer->Annotate("{", "}", descriptor_);
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "@java.lang.Override\n"
+          "$deprecation$\n"
+          "public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
+          "    $key_type$ key) {\n"
+          "  $key_null_check$\n"
+          "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+          "      internalGet$capitalized_name$();\n"
+          "  if (!map.containsKey(key)) {\n"
+          "    throw new java.lang.IllegalArgumentException();\n"
+          "  }\n"
+          "  return map.get(key);\n"
+          "}\n");
+      printer->Annotate("{", "}", descriptor_);
     }
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(
-        variables_,
-        "$deprecation$\n"
-        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "get$capitalized_name$() {\n"
-        "  return new com.google.protobuf.Internal.MapAdapter<\n"
-        "      $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
-        "          internalGet$capitalized_name$().getMap(),\n"
-        "          $name$ValueConverter);\n"
-        "}\n");
   } else {
+    printer->Print(
+        variables_,
+        "/**\n"
+        " * Use {@link #get$capitalized_name$Map()} instead.\n"
+        " */\n"
+        "@java.lang.Override\n"
+        "@java.lang.Deprecated\n"
+        "public java.util.Map<$type_parameters$> "
+        "${$get$capitalized_name$$}$() {\n"
+        "  return get$capitalized_name$Map();\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
+        "@java.lang.Override\n"
         "$deprecation$\n"
-        "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
-        "  return internalGet$capitalized_name$().getMap();\n"
+        "public java.util.Map<$type_parameters$> "
+        "${$get$capitalized_name$Map$}$() {\n"
+        "  return java.util.Collections.unmodifiableMap(\n"
+        "      internalGet$capitalized_name$());\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "@java.lang.Override\n"
+        "$deprecation$\n"
+        "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+        "    $key_type$ key,\n"
+        "    $value_type$ defaultValue) {\n"
+        "  $key_null_check$\n"
+        "  java.util.Map<$type_parameters$> map =\n"
+        "      internalGet$capitalized_name$();\n"
+        "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "@java.lang.Override\n"
+        "$deprecation$\n"
+        "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+        "    $key_type$ key) {\n"
+        "  $key_null_check$\n"
+        "  java.util.Map<$type_parameters$> map =\n"
+        "      internalGet$capitalized_name$();\n"
+        "  if (!map.containsKey(key)) {\n"
+        "    throw new java.lang.IllegalArgumentException();\n"
+        "  }\n"
+        "  return map.get(key);\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   // Generate private setters for the builder to proxy into.
@@ -257,10 +501,10 @@
     printer->Print(
         variables_,
         "private java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "getMutable$capitalized_name$() {\n"
+        "getMutable$capitalized_name$Map() {\n"
         "  return new com.google.protobuf.Internal.MapAdapter<\n"
         "      $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
-        "          internalGetMutable$capitalized_name$().getMutableMap(),\n"
+        "          internalGetMutable$capitalized_name$(),\n"
         "          $name$ValueConverter);\n"
         "}\n");
     if (SupportUnknownEnumValue(descriptor_->file())) {
@@ -268,8 +512,8 @@
       printer->Print(
           variables_,
           "private java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
-          "getMutable$capitalized_name$Value() {\n"
-          "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
+          "getMutable$capitalized_name$ValueMap() {\n"
+          "  return internalGetMutable$capitalized_name$();\n"
           "}\n");
     }
   } else {
@@ -277,90 +521,289 @@
     printer->Print(
         variables_,
         "private java.util.Map<$type_parameters$>\n"
-        "getMutable$capitalized_name$() {\n"
-        "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
+        "getMutable$capitalized_name$Map() {\n"
+        "  return internalGetMutable$capitalized_name$();\n"
         "}\n");
   }
 }
 
+
 void ImmutableMapFieldLiteGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "@java.lang.Override\n"
+      "$deprecation$\n"
+      "public int ${$get$capitalized_name$Count$}$() {\n"
+      "  return instance.get$capitalized_name$Map().size();\n"
+      "}\n");
+  printer->Annotate("{", "}", descriptor_);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "@java.lang.Override\n"
+      "$deprecation$\n"
+      "public boolean ${$contains$capitalized_name$$}$(\n"
+      "    $key_type$ key) {\n"
+      "  $key_null_check$\n"
+      "  return instance.get$capitalized_name$Map().containsKey(key);\n"
+      "}\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecation$\n"
+      "public Builder ${$clear$capitalized_name$$}$() {\n"
+      "  copyOnWrite();\n"
+      "  instance.getMutable$capitalized_name$Map().clear();\n"
+      "  return this;\n"
+      "}\n");
+  printer->Annotate("{", "}", descriptor_);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecation$\n"
+      "public Builder ${$remove$capitalized_name$$}$(\n"
+      "    $key_type$ key) {\n"
+      "  $key_null_check$\n"
+      "  copyOnWrite();\n"
+      "  instance.getMutable$capitalized_name$Map().remove(key);\n"
+      "  return this;\n"
+      "}\n");
+  printer->Annotate("{", "}", descriptor_);
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
-    WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
-        "$deprecation$\n"
+        "/**\n"
+        " * Use {@link #get$capitalized_name$Map()} instead.\n"
+        " */\n"
+        "@java.lang.Deprecated\n"
         "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "get$capitalized_name$() {\n"
-        "  return instance.get$capitalized_name$();\n"
+        "${$get$capitalized_name$$}$() {\n"
+        "  return get$capitalized_name$Map();\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
+        "@java.lang.Override\n"
         "$deprecation$\n"
         "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "getMutable$capitalized_name$() {\n"
+        "${$get$capitalized_name$Map$}$() {\n"
+        "  return java.util.Collections.unmodifiableMap(\n"
+        "      instance.get$capitalized_name$Map());\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "@java.lang.Override\n"
+        "$deprecation$\n"
+        "public $value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+        "    $key_type$ key,\n"
+        "    $value_enum_type$ defaultValue) {\n"
+        "  $key_null_check$\n"
+        "  java.util.Map<$boxed_key_type$, $value_enum_type$> map =\n"
+        "      instance.get$capitalized_name$Map();\n"
+        "  return map.containsKey(key)\n"
+        "         ? map.get(key)\n"
+        "         : defaultValue;\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "@java.lang.Override\n"
+        "$deprecation$\n"
+        "public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+        "    $key_type$ key) {\n"
+        "  $key_null_check$\n"
+        "  java.util.Map<$boxed_key_type$, $value_enum_type$> map =\n"
+        "      instance.get$capitalized_name$Map();\n"
+        "  if (!map.containsKey(key)) {\n"
+        "    throw new java.lang.IllegalArgumentException();\n"
+        "  }\n"
+        "  return map.get(key);\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$public Builder ${$put$capitalized_name$$}$(\n"
+        "    $key_type$ key,\n"
+        "    $value_enum_type$ value) {\n"
+        "  $key_null_check$\n"
+        "  $value_null_check$\n"
         "  copyOnWrite();\n"
-        "  return instance.getMutable$capitalized_name$();\n"
-        "}\n");
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(
-        variables_,
-        "$deprecation$public Builder putAll$capitalized_name$(\n"
-        "    java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
-        "  getMutable$capitalized_name$().putAll(values);\n"
+        "  instance.getMutable$capitalized_name$Map().put(key, value);\n"
         "  return this;\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$public Builder ${$putAll$capitalized_name$$}$(\n"
+        "    java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
+        "  copyOnWrite();\n"
+        "  instance.getMutable$capitalized_name$Map().putAll(values);\n"
+        "  return this;\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
     if (SupportUnknownEnumValue(descriptor_->file())) {
-      WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
-          "$deprecation$\n"
+          "/**\n"
+          " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
+          " */\n"
+          "@java.lang.Override\n"
+          "@java.lang.Deprecated\n"
           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
-          "get$capitalized_name$Value() {\n"
-          "  return instance.get$capitalized_name$Value();\n"
+          "${$get$capitalized_name$Value$}$() {\n"
+          "  return get$capitalized_name$ValueMap();\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
+          "@java.lang.Override\n"
           "$deprecation$\n"
           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
-          "getMutable$capitalized_name$Value() {\n"
+          "${$get$capitalized_name$ValueMap$}$() {\n"
+          "  return java.util.Collections.unmodifiableMap(\n"
+          "      instance.get$capitalized_name$ValueMap());\n"
+          "}\n");
+      printer->Annotate("{", "}", descriptor_);
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "@java.lang.Override\n"
+          "$deprecation$\n"
+          "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
+          "    $key_type$ key,\n"
+          "    $value_type$ defaultValue) {\n"
+          "  $key_null_check$\n"
+          "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+          "      instance.get$capitalized_name$ValueMap();\n"
+          "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
+          "}\n");
+      printer->Annotate("{", "}", descriptor_);
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "@java.lang.Override\n"
+          "$deprecation$\n"
+          "public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
+          "    $key_type$ key) {\n"
+          "  $key_null_check$\n"
+          "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
+          "      instance.get$capitalized_name$ValueMap();\n"
+          "  if (!map.containsKey(key)) {\n"
+          "    throw new java.lang.IllegalArgumentException();\n"
+          "  }\n"
+          "  return map.get(key);\n"
+          "}\n");
+      printer->Annotate("{", "}", descriptor_);
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$public Builder ${$put$capitalized_name$Value$}$(\n"
+          "    $key_type$ key,\n"
+          "    $value_type$ value) {\n"
+          "  $key_null_check$\n"
           "  copyOnWrite();\n"
-          "  return instance.getMutable$capitalized_name$Value();\n"
-          "}\n");
-      WriteFieldDocComment(printer, descriptor_);
-      printer->Print(
-          variables_,
-          "$deprecation$public Builder putAll$capitalized_name$Value(\n"
-          "    java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
-          "  getMutable$capitalized_name$Value().putAll(values);\n"
+          "  instance.getMutable$capitalized_name$ValueMap().put(key, value);\n"
           "  return this;\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
+      WriteFieldDocComment(printer, descriptor_);
+      printer->Print(
+          variables_,
+          "$deprecation$public Builder ${$putAll$capitalized_name$Value$}$(\n"
+          "    java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
+          "  copyOnWrite();\n"
+          "  instance.getMutable$capitalized_name$ValueMap().putAll(values);\n"
+          "  return this;\n"
+          "}\n");
+      printer->Annotate("{", "}", descriptor_);
     }
   } else {
-    WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
-        "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
-        "  return instance.get$capitalized_name$();\n"
+        "/**\n"
+        " * Use {@link #get$capitalized_name$Map()} instead.\n"
+        " */\n"
+        "@java.lang.Override\n"
+        "@java.lang.Deprecated\n"
+        "public java.util.Map<$type_parameters$> "
+        "${$get$capitalized_name$$}$() {\n"
+        "  return get$capitalized_name$Map();\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
-        "public java.util.Map<$type_parameters$>\n"
-        "getMutable$capitalized_name$() {\n"
+        "@java.lang.Override\n"
+        "$deprecation$"
+        "public java.util.Map<$type_parameters$> "
+        "${$get$capitalized_name$Map$}$() {\n"
+        "  return java.util.Collections.unmodifiableMap(\n"
+        "      instance.get$capitalized_name$Map());\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "@java.lang.Override\n"
+        "$deprecation$\n"
+        "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+        "    $key_type$ key,\n"
+        "    $value_type$ defaultValue) {\n"
+        "  $key_null_check$\n"
+        "  java.util.Map<$type_parameters$> map =\n"
+        "      instance.get$capitalized_name$Map();\n"
+        "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "@java.lang.Override\n"
+        "$deprecation$\n"
+        "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
+        "    $key_type$ key) {\n"
+        "  $key_null_check$\n"
+        "  java.util.Map<$type_parameters$> map =\n"
+        "      instance.get$capitalized_name$Map();\n"
+        "  if (!map.containsKey(key)) {\n"
+        "    throw new java.lang.IllegalArgumentException();\n"
+        "  }\n"
+        "  return map.get(key);\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$"
+        "public Builder ${$put$capitalized_name$$}$(\n"
+        "    $key_type$ key,\n"
+        "    $value_type$ value) {\n"
+        "  $key_null_check$\n"
+        "  $value_null_check$\n"
         "  copyOnWrite();\n"
-        "  return instance.getMutable$capitalized_name$();\n"
-        "}\n");
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(
-        variables_,
-        "public Builder putAll$capitalized_name$(\n"
-        "    java.util.Map<$type_parameters$> values) {\n"
-        "  getMutable$capitalized_name$().putAll(values);\n"
+        "  instance.getMutable$capitalized_name$Map().put(key, value);\n"
         "  return this;\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$"
+        "public Builder ${$putAll$capitalized_name$$}$(\n"
+        "    java.util.Map<$type_parameters$> values) {\n"
+        "  copyOnWrite();\n"
+        "  instance.getMutable$capitalized_name$Map().putAll(values);\n"
+        "  return this;\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 }
 
@@ -375,11 +818,11 @@
 }
 
 void ImmutableMapFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
+GenerateVisitCode(io::Printer* printer) const {
   printer->Print(
       variables_,
-      "internalGetMutable$capitalized_name$().mergeFrom(\n"
-      "    other.internalGet$capitalized_name$());\n");
+      "$name$_ = visitor.visitMap(\n"
+      "    $name$_, other.internalGet$capitalized_name$());\n");
 }
 
 void ImmutableMapFieldLiteGenerator::
@@ -393,29 +836,26 @@
   printer->Print(
       variables_,
       "if (!$name$_.isMutable()) {\n"
-      "  $name$_ = $name$_.copy();\n"
+      "  $name$_ = $name$_.mutableCopy();\n"
       "}\n");
   if (!SupportUnknownEnumValue(descriptor_->file()) &&
       GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
     printer->Print(
         variables_,
         "com.google.protobuf.ByteString bytes = input.readBytes();\n"
-        "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
-        "$name$ = $default_entry$.getParserForType().parseFrom(bytes);\n");
+        "java.util.Map.Entry<$type_parameters$> $name$__ =\n"
+        "    $default_entry$.parseEntry(bytes, extensionRegistry);\n");
     printer->Print(
         variables_,
-        "if ($value_enum_type$.valueOf($name$.getValue()) == null) {\n"
+        "if ($value_enum_type$.forNumber($name$__.getValue()) == null) {\n"
         "  super.mergeLengthDelimitedField($number$, bytes);\n"
         "} else {\n"
-        "  $name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"
+        "  $name$_.put($name$__);\n"
         "}\n");
   } else {
     printer->Print(
         variables_,
-        "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
-        "$name$ = input.readMessage(\n"
-        "    $default_entry$.getParserForType(), extensionRegistry);\n"
-        "$name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n");
+        "$default_entry$.parseInto($name$_, input, extensionRegistry);");
   }
 }
 
@@ -429,13 +869,9 @@
   printer->Print(
       variables_,
       "for (java.util.Map.Entry<$type_parameters$> entry\n"
-      "     : internalGet$capitalized_name$().getMap().entrySet()) {\n"
-      "  com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
-      "  $name$ = $default_entry$.newBuilderForType()\n"
-      "      .setKey(entry.getKey())\n"
-      "      .setValue(entry.getValue())\n"
-      "      .build();\n"
-      "  output.writeMessage($number$, $name$);\n"
+      "     : internalGet$capitalized_name$().entrySet()) {\n"
+      "  $default_entry$.serializeTo(\n"
+      "      output, $number$, entry.getKey(), entry.getValue());\n"
       "}\n");
 }
 
@@ -444,14 +880,9 @@
   printer->Print(
       variables_,
       "for (java.util.Map.Entry<$type_parameters$> entry\n"
-      "     : internalGet$capitalized_name$().getMap().entrySet()) {\n"
-      "  com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
-      "  $name$ = $default_entry$.newBuilderForType()\n"
-      "      .setKey(entry.getKey())\n"
-      "      .setValue(entry.getValue())\n"
-      "      .build();\n"
-      "  size += com.google.protobuf.CodedOutputStream\n"
-      "      .computeMessageSize($number$, $name$);\n"
+      "     : internalGet$capitalized_name$().entrySet()) {\n"
+      "  size += $default_entry$.computeMessageSize(\n"
+      "    $number$, entry.getKey(), entry.getValue());\n"
       "}\n");
 }
 
@@ -467,7 +898,7 @@
 GenerateHashCode(io::Printer* printer) const {
   printer->Print(
       variables_,
-      "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n"
+      "if (!internalGet$capitalized_name$().isEmpty()) {\n"
       "  hash = (37 * hash) + $constant_name$;\n"
       "  hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n"
       "}\n");
diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.h b/src/google/protobuf/compiler/java/java_map_field_lite.h
index a09cd53..94aa481 100644
--- a/src/google/protobuf/compiler/java/java_map_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.h
@@ -52,7 +52,7 @@
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
   void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateParsingDoneCode(io::Printer* printer) const;
@@ -62,11 +62,12 @@
   void GenerateEqualsCode(io::Printer* printer) const;
   void GenerateHashCode(io::Printer* printer) const;
 
+
   string GetBoxedType() const;
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   ClassNameResolver* name_resolver_;
 };
 
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 22a70c3..209c0b2 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -38,9 +38,6 @@
 #include <google/protobuf/stubs/hash.h>
 #include <map>
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 #include <vector>
 
 #include <google/protobuf/compiler/java/java_context.h>
@@ -52,12 +49,13 @@
 #include <google/protobuf/compiler/java/java_message_builder.h>
 #include <google/protobuf/compiler/java/java_message_builder_lite.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/printer.h>
-#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/strutil.h>
+
 
 namespace google {
 namespace protobuf {
@@ -89,19 +87,20 @@
 MessageGenerator::~MessageGenerator() {}
 
 // ===================================================================
-// TODO(api): Move this class to a separate immutable_message.cc file.
 ImmutableMessageGenerator::ImmutableMessageGenerator(
     const Descriptor* descriptor, Context* context)
   : MessageGenerator(descriptor), context_(context),
     name_resolver_(context->GetNameResolver()),
     field_generators_(descriptor, context_) {
-  GOOGLE_CHECK_NE(
-      FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+  GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+      << "Generator factory error: A non-lite message generator is used to "
+         "generate lite messages.";
 }
 
 ImmutableMessageGenerator::~ImmutableMessageGenerator() {}
 
-void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) {
+void ImmutableMessageGenerator::GenerateStaticVariables(
+    io::Printer* printer, int* bytecode_estimate) {
   // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
   // used in the construction of descriptors, we have a tricky bootstrapping
   // problem.  To help control static initialization order, we make sure all
@@ -109,7 +108,7 @@
   // the outermost class in the file.  This way, they will be initialized in
   // a deterministic order.
 
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
   vars["index"] = SimpleItoa(descriptor_->index());
   vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
@@ -124,30 +123,36 @@
   } else {
     vars["private"] = "private ";
   }
+  if (*bytecode_estimate <= kMaxStaticSize) {
+    vars["final"] = "final ";
+  } else {
+    vars["final"] = "";
+  }
 
   // The descriptor for this type.
   printer->Print(vars,
     // TODO(teboring): final needs to be added back. The way to fix it is to
     // generate methods that can construct the types, and then still declare the
     // types, and then init them in clinit with the new method calls.
-    "$private$static com.google.protobuf.Descriptors.Descriptor\n"
+    "$private$static $final$com.google.protobuf.Descriptors.Descriptor\n"
     "  internal_$identifier$_descriptor;\n");
+  *bytecode_estimate += 30;
 
   // And the FieldAccessorTable.
-  GenerateFieldAccessorTable(printer);
+  GenerateFieldAccessorTable(printer, bytecode_estimate);
 
   // Generate static members for all nested types.
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     // TODO(kenton):  Reuse MessageGenerator objects?
     ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
-      .GenerateStaticVariables(printer);
+        .GenerateStaticVariables(printer, bytecode_estimate);
   }
 }
 
 int ImmutableMessageGenerator::GenerateStaticVariableInitializers(
     io::Printer* printer) {
   int bytecode_estimate = 0;
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
   vars["index"] = SimpleItoa(descriptor_->index());
   vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
@@ -183,8 +188,8 @@
 }
 
 void ImmutableMessageGenerator::
-GenerateFieldAccessorTable(io::Printer* printer) {
-  map<string, string> vars;
+GenerateFieldAccessorTable(io::Printer* printer, int* bytecode_estimate) {
+  std::map<string, string> vars;
   vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
   if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
     // We can only make these package-private since the classes that use them
@@ -193,10 +198,20 @@
   } else {
     vars["private"] = "private ";
   }
+  if (*bytecode_estimate <= kMaxStaticSize) {
+    vars["final"] = "final ";
+  } else {
+    vars["final"] = "";
+  }
+  vars["ver"] = GeneratedCodeVersionSuffix();
   printer->Print(vars,
-    "$private$static\n"
-    "  com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+    "$private$static $final$\n"
+    "  com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
     "    internal_$identifier$_fieldAccessorTable;\n");
+
+  // 6 bytes per field and oneof
+  *bytecode_estimate += 10 + 6 * descriptor_->field_count()
+      + 6 * descriptor_->oneof_decl_count();
 }
 
 int ImmutableMessageGenerator::
@@ -204,11 +219,11 @@
   int bytecode_estimate = 10;
   printer->Print(
     "internal_$identifier$_fieldAccessorTable = new\n"
-    "  com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n"
+    "  com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable(\n"
     "    internal_$identifier$_descriptor,\n"
     "    new java.lang.String[] { ",
-    "identifier",
-    UniqueFileScopeIdentifier(descriptor_));
+    "identifier", UniqueFileScopeIdentifier(descriptor_),
+    "ver", GeneratedCodeVersionSuffix());
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
     const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
@@ -232,22 +247,31 @@
 // ===================================================================
 
 void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) {
+  MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
+                                /* immutable = */ true, "OrBuilder");
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(
-      "public interface $classname$OrBuilder extends\n"
-      "    $extra_interfaces$\n"
-      "    com.google.protobuf.GeneratedMessage.\n"
-      "        ExtendableMessageOrBuilder<$classname$> {\n",
-      "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
-      "classname", descriptor_->name());
+        "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
+        "    $extra_interfaces$\n"
+        "    com.google.protobuf.GeneratedMessage$ver$.\n"
+        "        ExtendableMessageOrBuilder<$classname$> {\n",
+        "deprecation", descriptor_->options().deprecated() ?
+            "@java.lang.Deprecated " : "",
+        "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+        "classname", descriptor_->name(),
+        "{", "", "}", "", "ver", GeneratedCodeVersionSuffix());
   } else {
     printer->Print(
-      "public interface $classname$OrBuilder extends\n"
-      "    $extra_interfaces$\n"
-      "    com.google.protobuf.MessageOrBuilder {\n",
-      "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
-      "classname", descriptor_->name());
+        "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
+        "    $extra_interfaces$\n"
+        "    com.google.protobuf.MessageOrBuilder {\n",
+        "deprecation", descriptor_->options().deprecated() ?
+            "@java.lang.Deprecated " : "",
+        "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+        "classname", descriptor_->name(),
+        "{", "", "}", "");
   }
+  printer->Annotate("{", "}", descriptor_);
 
   printer->Indent();
     for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -275,37 +299,53 @@
 // ===================================================================
 
 void ImmutableMessageGenerator::Generate(io::Printer* printer) {
-  bool is_own_file =
-    descriptor_->containing_type() == NULL &&
-    MultipleJavaFiles(descriptor_->file(), /* immutable = */ true);
+  bool is_own_file = IsOwnFile(descriptor_, /* immutable = */ true);
 
-  map<string, string> variables;
+  std::map<string, string> variables;
   variables["static"] = is_own_file ? " " : " static ";
   variables["classname"] = descriptor_->name();
   variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
+  variables["ver"] = GeneratedCodeVersionSuffix();
+  variables["deprecation"] = descriptor_->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
 
   WriteMessageDocComment(printer, descriptor_);
+  MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
+                                /* immutable = */ true);
 
   // The builder_type stores the super type name of the nested Builder class.
   string builder_type;
   if (descriptor_->extension_range_count() > 0) {
+    printer->Print(
+        variables,
+        "$deprecation$public $static$final class $classname$ extends\n");
+    printer->Annotate("classname", descriptor_);
+    printer->Print(
+        variables,
+        "    com.google.protobuf.GeneratedMessage$ver$.ExtendableMessage<\n"
+        "      $classname$> implements\n"
+        "    $extra_interfaces$\n"
+        "    $classname$OrBuilder {\n");
+    builder_type = strings::Substitute(
+        "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>",
+        name_resolver_->GetImmutableClassName(descriptor_),
+        GeneratedCodeVersionSuffix());
+  } else {
+    printer->Print(
+        variables,
+        "$deprecation$public $static$final class $classname$ extends\n");
+    printer->Annotate("classname", descriptor_);
     printer->Print(variables,
-      "public $static$final class $classname$ extends\n"
-      "    com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
-      "      $classname$> implements\n"
+      "    com.google.protobuf.GeneratedMessage$ver$ implements\n"
       "    $extra_interfaces$\n"
       "    $classname$OrBuilder {\n");
     builder_type = strings::Substitute(
-             "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>",
-             name_resolver_->GetImmutableClassName(descriptor_));
-  } else {
-    printer->Print(variables,
-      "public $static$final class $classname$ extends\n"
-      "    com.google.protobuf.GeneratedMessage implements\n"
-      "    $extra_interfaces$\n"
-      "    $classname$OrBuilder {\n");
-    builder_type = "com.google.protobuf.GeneratedMessage.Builder<?>";
+        "com.google.protobuf.GeneratedMessage$0.Builder<?>",
+        GeneratedCodeVersionSuffix());
   }
+  printer->Print(
+    "private static final long serialVersionUID = 0L;\n");
+
   printer->Indent();
   // Using builder_type, instead of Builder, prevents the Builder class from
   // being loaded into PermGen space when the default instance is created.
@@ -328,22 +368,19 @@
     "}\n"
     "\n");
 
+
   printer->Print(
     "@java.lang.Override\n"
     "public final com.google.protobuf.UnknownFieldSet\n"
-    "getUnknownFields() {\n");
-  if (PreserveUnknownFields(descriptor_)) {
-    printer->Print(
-      "  return this.unknownFields;\n");
-  } else {
-    printer->Print(
-      "  return com.google.protobuf.UnknownFieldSet.getDefaultInstance();\n");
-  }
-  printer->Print(
+    "getUnknownFields() {\n"
+    "  return this.unknownFields;\n"
     "}\n");
 
-  if (HasGeneratedMethods(descriptor_)) {
-    GenerateParsingConstructor(printer);
+  if (context_->HasGeneratedMethods(descriptor_)) {
+    if (!EnableExperimentalRuntime(context_) ||
+        IsDescriptorProto(descriptor_)) {
+      GenerateParsingConstructor(printer);
+    }
   }
 
   GenerateDescriptorMethods(printer);
@@ -378,7 +415,7 @@
   }
 
   // oneof
-  map<string, string> vars;
+  std::map<string, string> vars;
   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
     vars["oneof_name"] = context_->GetOneofGeneratorInfo(
         descriptor_->oneof_decl(i))->name;
@@ -397,23 +434,31 @@
     for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
       const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
       printer->Print(
-        "$field_name$($field_number$),\n",
-        "field_name",
-        ToUpper(field->name()),
-        "field_number",
-        SimpleItoa(field->number()));
+        "$deprecation$$field_name$($field_number$),\n",
+        "deprecation",
+        field->options().deprecated() ? "@java.lang.Deprecated " : "",
+        "field_name", ToUpper(field->name()),
+        "field_number", SimpleItoa(field->number()));
     }
     printer->Print(
       "$cap_oneof_name$_NOT_SET(0);\n",
       "cap_oneof_name",
       ToUpper(vars["oneof_name"]));
     printer->Print(vars,
-      "private int value = 0;\n"
+      "private final int value;\n"
       "private $oneof_capitalized_name$Case(int value) {\n"
       "  this.value = value;\n"
       "}\n");
     printer->Print(vars,
+      "/**\n"
+      " * @deprecated Use {@link #forNumber(int)} instead.\n"
+      " */\n"
+      "@java.lang.Deprecated\n"
       "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
+      "  return forNumber(value);\n"
+      "}\n"
+      "\n"
+      "public static $oneof_capitalized_name$Case forNumber(int value) {\n"
       "  switch (value) {\n");
     for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
       const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
@@ -426,8 +471,7 @@
     }
     printer->Print(
       "    case 0: return $cap_oneof_name$_NOT_SET;\n"
-      "    default: throw new java.lang.IllegalArgumentException(\n"
-      "      \"Value is undefined for this oneof enum.\");\n"
+      "    default: return null;\n"
       "  }\n"
       "}\n"
       "public int getNumber() {\n"
@@ -440,7 +484,7 @@
     printer->Print(vars,
       "public $oneof_capitalized_name$Case\n"
       "get$oneof_capitalized_name$Case() {\n"
-      "  return $oneof_capitalized_name$Case.valueOf(\n"
+      "  return $oneof_capitalized_name$Case.forNumber(\n"
       "      $oneof_name$Case_);\n"
       "}\n"
       "\n");
@@ -459,12 +503,9 @@
     printer->Print("\n");
   }
 
-  if (HasGeneratedMethods(descriptor_)) {
+  if (context_->HasGeneratedMethods(descriptor_)) {
     GenerateIsInitialized(printer);
     GenerateMessageSerializationMethods(printer);
-  }
-
-  if (HasEqualsAndHashCode(descriptor_)) {
     GenerateEqualsAndHashCode(printer);
   }
 
@@ -497,9 +538,21 @@
       "\n",
       "classname", name_resolver_->GetImmutableClassName(descriptor_));
 
+  // 'of' method for Wrappers
+  if (IsWrappersProtoFile(descriptor_->file())) {
+    printer->Print(
+        "public static $classname$ of($field_type$ value) {\n"
+        "  return newBuilder().setValue(value).build();\n"
+        "}\n"
+        "\n",
+        "classname", name_resolver_->GetImmutableClassName(descriptor_),
+        "field_type", PrimitiveTypeName(GetJavaType(descriptor_->field(0))));
+  }
+
   GenerateParser(printer);
 
   printer->Print(
+    "@java.lang.Override\n"
     "public $classname$ getDefaultInstanceForType() {\n"
     "  return DEFAULT_INSTANCE;\n"
     "}\n"
@@ -523,116 +576,120 @@
 
 void ImmutableMessageGenerator::
 GenerateMessageSerializationMethods(io::Printer* printer) {
-  google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
+  std::unique_ptr<const FieldDescriptor * []> sorted_fields(
       SortFieldsByNumber(descriptor_));
 
-  vector<const Descriptor::ExtensionRange*> sorted_extensions;
+  std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
   for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
     sorted_extensions.push_back(descriptor_->extension_range(i));
   }
   std::sort(sorted_extensions.begin(), sorted_extensions.end(),
             ExtensionRangeOrdering());
-
   printer->Print(
+    "@java.lang.Override\n"
     "public void writeTo(com.google.protobuf.CodedOutputStream output)\n"
     "                    throws java.io.IOException {\n");
   printer->Indent();
-  if (HasPackedFields(descriptor_)) {
-    // writeTo(CodedOutputStream output) might be invoked without
-    // getSerializedSize() ever being called, but we need the memoized
-    // sizes in case this message has packed fields. Rather than emit checks for
-    // each packed field, just call getSerializedSize() up front.
-    // In most cases, getSerializedSize() will have already been called anyway
-    // by one of the wrapper writeTo() methods, making this call cheap.
-    printer->Print(
-      "getSerializedSize();\n");
-  }
 
-  if (descriptor_->extension_range_count() > 0) {
-    if (descriptor_->options().message_set_wire_format()) {
-      printer->Print(
-        "com.google.protobuf.GeneratedMessage\n"
-        "  .ExtendableMessage<$classname$>.ExtensionWriter\n"
-        "    extensionWriter = newMessageSetExtensionWriter();\n",
-        "classname", name_resolver_->GetImmutableClassName(descriptor_));
-    } else {
-      printer->Print(
-        "com.google.protobuf.GeneratedMessage\n"
-        "  .ExtendableMessage<$classname$>.ExtensionWriter\n"
-        "    extensionWriter = newExtensionWriter();\n",
-        "classname", name_resolver_->GetImmutableClassName(descriptor_));
+  if (EnableExperimentalRuntime(context_) && !IsDescriptorProto(descriptor_)) {
+    printer->Print("writeToInternal(output);\n");
+  } else {
+    if (HasPackedFields(descriptor_)) {
+      // writeTo(CodedOutputStream output) might be invoked without
+      // getSerializedSize() ever being called, but we need the memoized
+      // sizes in case this message has packed fields. Rather than emit checks
+      // for each packed field, just call getSerializedSize() up front. In most
+      // cases, getSerializedSize() will have already been called anyway by one
+      // of the wrapper writeTo() methods, making this call cheap.
+      printer->Print("getSerializedSize();\n");
     }
-  }
 
-  // Merge the fields and the extension ranges, both sorted by field number.
-  for (int i = 0, j = 0;
-       i < descriptor_->field_count() || j < sorted_extensions.size();
-       ) {
-    if (i == descriptor_->field_count()) {
-      GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
-    } else if (j == sorted_extensions.size()) {
-      GenerateSerializeOneField(printer, sorted_fields[i++]);
-    } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) {
-      GenerateSerializeOneField(printer, sorted_fields[i++]);
-    } else {
-      GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+    if (descriptor_->extension_range_count() > 0) {
+      if (descriptor_->options().message_set_wire_format()) {
+        printer->Print(
+            "com.google.protobuf.GeneratedMessage$ver$\n"
+            "  .ExtendableMessage<$classname$>.ExtensionWriter\n"
+            "    extensionWriter = newMessageSetExtensionWriter();\n",
+            "classname", name_resolver_->GetImmutableClassName(descriptor_),
+            "ver", GeneratedCodeVersionSuffix());
+      } else {
+        printer->Print(
+            "com.google.protobuf.GeneratedMessage$ver$\n"
+            "  .ExtendableMessage<$classname$>.ExtensionWriter\n"
+            "    extensionWriter = newExtensionWriter();\n",
+            "classname", name_resolver_->GetImmutableClassName(descriptor_),
+            "ver", GeneratedCodeVersionSuffix());
+      }
     }
-  }
 
-  if (PreserveUnknownFields(descriptor_)) {
+    // Merge the fields and the extension ranges, both sorted by field number.
+    for (int i = 0, j = 0;
+         i < descriptor_->field_count() || j < sorted_extensions.size();) {
+      if (i == descriptor_->field_count()) {
+        GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+      } else if (j == sorted_extensions.size()) {
+        GenerateSerializeOneField(printer, sorted_fields[i++]);
+      } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) {
+        GenerateSerializeOneField(printer, sorted_fields[i++]);
+      } else {
+        GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+      }
+    }
+
     if (descriptor_->options().message_set_wire_format()) {
-      printer->Print(
-        "unknownFields.writeAsMessageSetTo(output);\n");
+      printer->Print("unknownFields.writeAsMessageSetTo(output);\n");
     } else {
-      printer->Print(
-        "unknownFields.writeTo(output);\n");
+      printer->Print("unknownFields.writeTo(output);\n");
     }
   }
 
   printer->Outdent();
   printer->Print(
-    "}\n"
-    "\n"
-    "public int getSerializedSize() {\n"
-    "  int size = memoizedSize;\n"
-    "  if (size != -1) return size;\n"
-    "\n"
-    "  size = 0;\n");
+      "}\n"
+      "\n"
+      "@java.lang.Override\n"
+      "public int getSerializedSize() {\n"
+      "  int size = memoizedSize;\n"
+      "  if (size != -1) return size;\n"
+      "\n");
   printer->Indent();
+  if (EnableExperimentalRuntime(context_) && !IsDescriptorProto(descriptor_)) {
+    printer->Print(
+        "memoizedSize = getSerializedSizeInternal();\n"
+        "return memoizedSize;\n");
+  } else {
 
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
-  }
+    printer->Print("size = 0;\n");
 
-  if (descriptor_->extension_range_count() > 0) {
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      field_generators_.get(sorted_fields[i])
+          .GenerateSerializedSizeCode(printer);
+    }
+
+    if (descriptor_->extension_range_count() > 0) {
+      if (descriptor_->options().message_set_wire_format()) {
+        printer->Print("size += extensionsSerializedSizeAsMessageSet();\n");
+      } else {
+        printer->Print("size += extensionsSerializedSize();\n");
+      }
+    }
+
     if (descriptor_->options().message_set_wire_format()) {
       printer->Print(
-        "size += extensionsSerializedSizeAsMessageSet();\n");
+          "size += unknownFields.getSerializedSizeAsMessageSet();\n");
     } else {
-      printer->Print(
-        "size += extensionsSerializedSize();\n");
+      printer->Print("size += unknownFields.getSerializedSize();\n");
     }
-  }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    if (descriptor_->options().message_set_wire_format()) {
-      printer->Print(
-        "size += unknownFields.getSerializedSizeAsMessageSet();\n");
-    } else {
-      printer->Print(
-        "size += unknownFields.getSerializedSize();\n");
-    }
+    printer->Print(
+        "memoizedSize = size;\n"
+        "return size;\n");
   }
 
   printer->Outdent();
   printer->Print(
-    "  memoizedSize = size;\n"
-    "  return size;\n"
     "}\n"
     "\n");
-
-  printer->Print(
-    "private static final long serialVersionUID = 0L;\n");
 }
 
 void ImmutableMessageGenerator::
@@ -642,6 +699,17 @@
   //   for code size.
   printer->Print(
     "public static $classname$ parseFrom(\n"
+    "    java.nio.ByteBuffer data)\n"
+    "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
+    "  return PARSER.parseFrom(data);\n"
+    "}\n"
+    "public static $classname$ parseFrom(\n"
+    "    java.nio.ByteBuffer data,\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+    "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
+    "  return PARSER.parseFrom(data, extensionRegistry);\n"
+    "}\n"
+    "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.ByteString data)\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
     "  return PARSER.parseFrom(data);\n"
@@ -664,37 +732,44 @@
     "}\n"
     "public static $classname$ parseFrom(java.io.InputStream input)\n"
     "    throws java.io.IOException {\n"
-    "  return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input);"
+    "  return com.google.protobuf.GeneratedMessage$ver$\n"
+    "      .parseWithIOException(PARSER, input);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    java.io.InputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
-    "  return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input, extensionRegistry);"
+    "  return com.google.protobuf.GeneratedMessage$ver$\n"
+    "      .parseWithIOException(PARSER, input, extensionRegistry);\n"
     "}\n"
     "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
     "    throws java.io.IOException {\n"
-    "  return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input);"
+    "  return com.google.protobuf.GeneratedMessage$ver$\n"
+    "      .parseDelimitedWithIOException(PARSER, input);\n"
     "}\n"
     "public static $classname$ parseDelimitedFrom(\n"
     "    java.io.InputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
-    "  return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input, extensionRegistry);"
+    "  return com.google.protobuf.GeneratedMessage$ver$\n"
+    "      .parseDelimitedWithIOException(PARSER, input, extensionRegistry);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.CodedInputStream input)\n"
     "    throws java.io.IOException {\n"
-    "  return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input);"
+    "  return com.google.protobuf.GeneratedMessage$ver$\n"
+    "      .parseWithIOException(PARSER, input);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.CodedInputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
-    "  return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input, extensionRegistry);"
+    "  return com.google.protobuf.GeneratedMessage$ver$\n"
+    "      .parseWithIOException(PARSER, input, extensionRegistry);\n"
     "}\n"
     "\n",
-    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+    "classname", name_resolver_->GetImmutableClassName(descriptor_),
+    "ver", GeneratedCodeVersionSuffix());
 }
 
 void ImmutableMessageGenerator::GenerateSerializeOneField(
@@ -714,6 +789,7 @@
 void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
   // LITE_RUNTIME implements this at the GeneratedMessageLite level.
   printer->Print(
+    "@java.lang.Override\n"
     "public Builder newBuilderForType() { return newBuilder(); }\n");
 
   printer->Print(
@@ -723,6 +799,7 @@
     "public static Builder newBuilder($classname$ prototype) {\n"
     "  return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n"
     "}\n"
+    "@java.lang.Override\n"
     "public Builder toBuilder() {\n"
     "  return this == DEFAULT_INSTANCE\n"
     "      ? new Builder() : new Builder().mergeFrom(this);\n"
@@ -733,10 +810,11 @@
   printer->Print(
     "@java.lang.Override\n"
     "protected Builder newBuilderForType(\n"
-    "    com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
+    "    com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n"
     "  Builder builder = new Builder(parent);\n"
     "  return builder;\n"
-    "}\n");
+    "}\n",
+    "ver", GeneratedCodeVersionSuffix());
 
   MessageBuilderGenerator builderGenerator(descriptor_, context_);
   builderGenerator.Generate(printer);
@@ -754,7 +832,7 @@
       "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
       "identifier", UniqueFileScopeIdentifier(descriptor_));
   }
-  vector<const FieldDescriptor*> map_fields;
+  std::vector<const FieldDescriptor*> map_fields;
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
     if (GetJavaType(field) == JAVATYPE_MESSAGE &&
@@ -765,6 +843,7 @@
   if (!map_fields.empty()) {
     printer->Print(
       "@SuppressWarnings({\"rawtypes\"})\n"
+      "@java.lang.Override\n"
       "protected com.google.protobuf.MapField internalGetMapField(\n"
       "    int number) {\n"
       "  switch (number) {\n");
@@ -790,7 +869,8 @@
         "}\n");
   }
   printer->Print(
-    "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+    "@java.lang.Override\n"
+    "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
     "    internalGetFieldAccessorTable() {\n"
     "  return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
     "      .ensureFieldAccessorsInitialized(\n"
@@ -799,7 +879,8 @@
     "\n",
     "classname", name_resolver_->GetImmutableClassName(descriptor_),
     "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
-    "identifier", UniqueFileScopeIdentifier(descriptor_));
+    "identifier", UniqueFileScopeIdentifier(descriptor_),
+    "ver", GeneratedCodeVersionSuffix());
 }
 
 // ===================================================================
@@ -812,6 +893,7 @@
   printer->Print(
     "private byte memoizedIsInitialized = -1;\n");
   printer->Print(
+    "@java.lang.Override\n"
     "public final boolean isInitialized() {\n");
   printer->Indent();
 
@@ -882,7 +964,7 @@
         case FieldDescriptor::LABEL_REPEATED:
           if (IsMapEntry(field->message_type())) {
             printer->Print(
-              "for ($type$ item : get$name$().values()) {\n"
+              "for ($type$ item : get$name$Map().values()) {\n"
               "  if (!item.isInitialized()) {\n"
               "    memoizedIsInitialized = 0;\n"
               "    return false;\n"
@@ -1014,13 +1096,11 @@
     printer->Print("}\n");
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    // Always consider unknown fields for equality. This will sometimes return
-    // false for non-canonical ordering when running in LITE_RUNTIME but it's
-    // the best we can do.
-    printer->Print(
+  // Always consider unknown fields for equality. This will sometimes return
+  // false for non-canonical ordering when running in LITE_RUNTIME but it's
+  // the best we can do.
+  printer->Print(
       "result = result && unknownFields.equals(other.unknownFields);\n");
-  }
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(
       "result = result &&\n"
@@ -1047,24 +1127,59 @@
     "}\n"
     "int hash = 41;\n");
 
-  printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n");
+  // If we output a getDescriptor() method, use that as it is more efficient.
+  if (descriptor_->options().no_standard_descriptor_accessor()) {
+    printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n");
+  } else {
+    printer->Print("hash = (19 * hash) + getDescriptor().hashCode();\n");
+  }
 
+  // hashCode non-oneofs.
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
-    const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
-    bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
-    if (check_has_bits) {
-      printer->Print(
-        "if (has$name$()) {\n",
-        "name", info->capitalized_name);
-      printer->Indent();
-    }
-    field_generators_.get(field).GenerateHashCode(printer);
-    if (check_has_bits) {
-      printer->Outdent();
-      printer->Print("}\n");
+    if (field->containing_oneof() == NULL) {
+      const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+      bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
+      if (check_has_bits) {
+        printer->Print(
+          "if (has$name$()) {\n",
+          "name", info->capitalized_name);
+        printer->Indent();
+      }
+      field_generators_.get(field).GenerateHashCode(printer);
+      if (check_has_bits) {
+        printer->Outdent();
+        printer->Print("}\n");
+      }
     }
   }
+
+  // hashCode oneofs.
+  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+    printer->Print(
+      "switch ($oneof_name$Case_) {\n",
+      "oneof_name",
+      context_->GetOneofGeneratorInfo(
+          descriptor_->oneof_decl(i))->name);
+    printer->Indent();
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+      printer->Print(
+        "case $field_number$:\n",
+        "field_number",
+        SimpleItoa(field->number()));
+      printer->Indent();
+      field_generators_.get(field).GenerateHashCode(printer);
+      printer->Print("break;\n");
+      printer->Outdent();
+    }
+    printer->Print(
+      "case 0:\n"
+      "default:\n");
+    printer->Outdent();
+    printer->Print("}\n");
+  }
+
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(
       "hash = hashFields(hash, getExtensionFields());\n");
@@ -1099,19 +1214,23 @@
 // ===================================================================
 void ImmutableMessageGenerator::
 GenerateParsingConstructor(io::Printer* printer) {
-  google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
+  std::unique_ptr<const FieldDescriptor * []> sorted_fields(
       SortFieldsByNumber(descriptor_));
 
   printer->Print(
       "private $classname$(\n"
       "    com.google.protobuf.CodedInputStream input,\n"
-      "    com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n",
+      "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+      "    throws com.google.protobuf.InvalidProtocolBufferException {\n",
       "classname", descriptor_->name());
   printer->Indent();
 
   // Initialize all fields to default.
   printer->Print(
-      "this();\n");
+      "this();\n"
+      "if (extensionRegistry == null) {\n"
+      "  throw new java.lang.NullPointerException();\n"
+      "}\n");
 
   // Use builder bits to track mutable repeated fields.
   int totalBuilderBits = 0;
@@ -1126,11 +1245,9 @@
       "bit_field_name", GetBitFieldName(i));
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    printer->Print(
+  printer->Print(
       "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
       "    com.google.protobuf.UnknownFieldSet.newBuilder();\n");
-  }
 
   printer->Print(
       "try {\n");
@@ -1147,28 +1264,9 @@
   printer->Indent();
 
   printer->Print(
-    "case 0:\n"          // zero signals EOF / limit reached
-    "  done = true;\n"
-    "  break;\n");
-
-  if (PreserveUnknownFields(descriptor_)) {
-    printer->Print(
-      "default: {\n"
-      "  if (!parseUnknownField(input, unknownFields,\n"
-      "                         extensionRegistry, tag)) {\n"
-      "    done = true;\n"  // it's an endgroup tag
-      "  }\n"
-      "  break;\n"
-      "}\n");
-  } else {
-    printer->Print(
-      "default: {\n"
-      "  if (!input.skipField(tag)) {\n"
-      "    done = true;\n"  // it's an endgroup tag
-      "  }\n"
-      "  break;\n"
-      "}\n");
-  }
+      "case 0:\n"  // zero signals EOF / limit reached
+      "  done = true;\n"
+      "  break;\n");
 
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = sorted_fields[i];
@@ -1177,7 +1275,7 @@
 
     printer->Print(
       "case $tag$: {\n",
-      "tag", SimpleItoa(tag));
+      "tag", SimpleItoa(static_cast<int32>(tag)));
     printer->Indent();
 
     field_generators_.get(field).GenerateParsingCode(printer);
@@ -1194,7 +1292,7 @@
         WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
       printer->Print(
         "case $tag$: {\n",
-        "tag", SimpleItoa(packed_tag));
+        "tag", SimpleItoa(static_cast<int32>(packed_tag)));
       printer->Indent();
 
       field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
@@ -1206,6 +1304,18 @@
     }
   }
 
+  printer->Print(
+      "default: {\n"
+      "  if (!parseUnknownField$suffix$(\n"
+      "      input, unknownFields, extensionRegistry, tag)) {\n"
+      "    done = true;\n"  // it's an endgroup tag
+      "  }\n"
+      "  break;\n"
+      "}\n",
+      "suffix",
+      descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ? "Proto3"
+                                                                     : "");
+
   printer->Outdent();
   printer->Outdent();
   printer->Print(
@@ -1215,10 +1325,10 @@
   printer->Outdent();
   printer->Print(
       "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
-      "  throw new RuntimeException(e.setUnfinishedMessage(this));\n"
+      "  throw e.setUnfinishedMessage(this);\n"
       "} catch (java.io.IOException e) {\n"
-      "  throw new RuntimeException(new com.google.protobuf.InvalidProtocolBufferException(e)\n"
-      "      .setUnfinishedMessage(this));\n"
+      "  throw new com.google.protobuf.InvalidProtocolBufferException(\n"
+      "      e).setUnfinishedMessage(this);\n"
       "} finally {\n");
   printer->Indent();
 
@@ -1228,10 +1338,8 @@
     field_generators_.get(field).GenerateParsingDoneCode(printer);
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    // Make unknown fields immutable.
-    printer->Print("this.unknownFields = unknownFields.build();\n");
-  }
+  // Make unknown fields immutable.
+  printer->Print("this.unknownFields = unknownFields.build();\n");
 
   // Make extensions immutable.
   printer->Print(
@@ -1255,26 +1363,24 @@
       "classname", descriptor_->name());
   printer->Indent();
   printer->Print(
+      "@java.lang.Override\n"
       "public $classname$ parsePartialFrom(\n"
       "    com.google.protobuf.CodedInputStream input,\n"
       "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
       "    throws com.google.protobuf.InvalidProtocolBufferException {\n",
       "classname", descriptor_->name());
-  if (HasGeneratedMethods(descriptor_)) {
-    // The parsing constructor throws an InvalidProtocolBufferException via a
-    // RuntimeException to aid in method pruning. We unwrap it here.
+  if (EnableExperimentalRuntime(context_) && !IsDescriptorProto(descriptor_)) {
+    printer->Indent();
     printer->Print(
-        "  try {\n"
-        "    return new $classname$(input, extensionRegistry);\n"
-        "  } catch (RuntimeException e) {\n"
-        "    if (e.getCause() instanceof\n"
-        "        com.google.protobuf.InvalidProtocolBufferException) {\n"
-        "      throw (com.google.protobuf.InvalidProtocolBufferException)\n"
-        "          e.getCause();\n"
-        "    }\n"
-        "    throw e;\n"
-        "  }\n",
+        "$classname$ msg = new $classname$();\n"
+        "msg.mergeFromInternal(input, extensionRegistry);\n"
+        "msg.makeImmutableInternal();\n"
+        "return msg;\n",
         "classname", descriptor_->name());
+    printer->Outdent();
+  } else if (context_->HasGeneratedMethods(descriptor_)) {
+    printer->Print("  return new $classname$(input, extensionRegistry);\n",
+                   "classname", descriptor_->name());
   } else {
     // When parsing constructor isn't generated, use builder to parse
     // messages. Note, will fallback to use reflection based mergeFieldFrom()
@@ -1328,14 +1434,39 @@
 void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) {
   printer->Print(
     "private static String getTypeUrl(\n"
+    "    java.lang.String typeUrlPrefix,\n"
     "    com.google.protobuf.Descriptors.Descriptor descriptor) {\n"
-    "  return \"type.googleapis.com/\" + descriptor.getFullName();\n"
+    "  return typeUrlPrefix.endsWith(\"/\")\n"
+    "      ? typeUrlPrefix + descriptor.getFullName()\n"
+    "      : typeUrlPrefix + \"/\" + descriptor.getFullName();\n"
+    "}\n"
+    "\n"
+    "private static String getTypeNameFromTypeUrl(\n"
+    "    java.lang.String typeUrl) {\n"
+    "  int pos = typeUrl.lastIndexOf('/');\n"
+    "  return pos == -1 ? \"\" : typeUrl.substring(pos + 1);\n"
     "}\n"
     "\n"
     "public static <T extends com.google.protobuf.Message> Any pack(\n"
     "    T message) {\n"
     "  return Any.newBuilder()\n"
-    "      .setTypeUrl(getTypeUrl(message.getDescriptorForType()))\n"
+    "      .setTypeUrl(getTypeUrl(\"type.googleapis.com\",\n"
+    "                             message.getDescriptorForType()))\n"
+    "      .setValue(message.toByteString())\n"
+    "      .build();\n"
+    "}\n"
+    "\n"
+    "/**\n"
+    " * Packs a message using the given type URL prefix. The type URL will\n"
+    " * be constructed by concatenating the message type's full name to the\n"
+    " * prefix with an optional \"/\" separator if the prefix doesn't end\n"
+    " * with \"/\" already.\n"
+    " */\n"
+    "public static <T extends com.google.protobuf.Message> Any pack(\n"
+    "    T message, java.lang.String typeUrlPrefix) {\n"
+    "  return Any.newBuilder()\n"
+    "      .setTypeUrl(getTypeUrl(typeUrlPrefix,\n"
+    "                             message.getDescriptorForType()))\n"
     "      .setValue(message.toByteString())\n"
     "      .build();\n"
     "}\n"
@@ -1344,12 +1475,13 @@
     "    java.lang.Class<T> clazz) {\n"
     "  T defaultInstance =\n"
     "      com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
-    "  return getTypeUrl().equals(\n"
-    "      getTypeUrl(defaultInstance.getDescriptorForType()));\n"
+    "  return getTypeNameFromTypeUrl(getTypeUrl()).equals(\n"
+    "      defaultInstance.getDescriptorForType().getFullName());\n"
     "}\n"
     "\n"
     "private volatile com.google.protobuf.Message cachedUnpackValue;\n"
     "\n"
+    "@java.lang.SuppressWarnings(\"unchecked\")\n"
     "public <T extends com.google.protobuf.Message> T unpack(\n"
     "    java.lang.Class<T> clazz)\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h
index be5bfb0..da1447c 100644
--- a/src/google/protobuf/compiler/java/java_message.h
+++ b/src/google/protobuf/compiler/java/java_message.h
@@ -56,6 +56,8 @@
 namespace compiler {
 namespace java {
 
+static const int kMaxStaticSize = 1 << 15;  // aka 32k
+
 class MessageGenerator {
  public:
   explicit MessageGenerator(const Descriptor* descriptor);
@@ -64,7 +66,8 @@
   // All static variables have to be declared at the top-level of the file
   // so that we can control initialization order, which is important for
   // DescriptorProto bootstrapping to work.
-  virtual void GenerateStaticVariables(io::Printer* printer) = 0;
+  virtual void GenerateStaticVariables(
+      io::Printer* printer, int* bytecode_estimate) = 0;
 
   // Output code which initializes the static variables generated by
   // GenerateStaticVariables(). Returns an estimate of bytecode size.
@@ -89,21 +92,21 @@
 
 class ImmutableMessageGenerator : public MessageGenerator {
  public:
-  explicit ImmutableMessageGenerator(const Descriptor* descriptor,
-                                     Context* context);
+  ImmutableMessageGenerator(const Descriptor* descriptor, Context* context);
   virtual ~ImmutableMessageGenerator();
 
   virtual void Generate(io::Printer* printer);
   virtual void GenerateInterface(io::Printer* printer);
   virtual void GenerateExtensionRegistrationCode(io::Printer* printer);
-  virtual void GenerateStaticVariables(io::Printer* printer);
+  virtual void GenerateStaticVariables(
+      io::Printer* printer, int* bytecode_estimate);
 
   // Returns an estimate of the number of bytes the printed code will compile to
   virtual int GenerateStaticVariableInitializers(io::Printer* printer);
 
  private:
 
-  void GenerateFieldAccessorTable(io::Printer* printer);
+  void GenerateFieldAccessorTable(io::Printer* printer, int* bytecode_estimate);
 
   // Returns an estimate of the number of bytes the printed code will compile to
   int GenerateFieldAccessorTableInitializer(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/java/java_message_builder.cc b/src/google/protobuf/compiler/java/java_message_builder.cc
index 5d53503..4c67e80 100644
--- a/src/google/protobuf/compiler/java/java_message_builder.cc
+++ b/src/google/protobuf/compiler/java/java_message_builder.cc
@@ -38,9 +38,6 @@
 #include <google/protobuf/stubs/hash.h>
 #include <map>
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 #include <vector>
 
 #include <google/protobuf/compiler/java/java_context.h>
@@ -50,12 +47,13 @@
 #include <google/protobuf/compiler/java/java_generator_factory.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/printer.h>
-#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/strutil.h>
+
 
 namespace google {
 namespace protobuf {
@@ -81,8 +79,9 @@
   : descriptor_(descriptor), context_(context),
     name_resolver_(context->GetNameResolver()),
     field_generators_(descriptor, context_) {
-  GOOGLE_CHECK_NE(
-      FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+  GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+      << "Generator factory error: A non-lite message generator is used to "
+         "generate lite messages.";
 }
 
 MessageBuilderGenerator::~MessageBuilderGenerator() {}
@@ -93,33 +92,35 @@
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(
       "public static final class Builder extends\n"
-      "    com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
+      "    com.google.protobuf.GeneratedMessage$ver$.ExtendableBuilder<\n"
       "      $classname$, Builder> implements\n"
       "    $extra_interfaces$\n"
       "    $classname$OrBuilder {\n",
       "classname", name_resolver_->GetImmutableClassName(descriptor_),
-      "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
+      "extra_interfaces", ExtraBuilderInterfaces(descriptor_),
+      "ver", GeneratedCodeVersionSuffix());
   } else {
     printer->Print(
       "public static final class Builder extends\n"
-      "    com.google.protobuf.GeneratedMessage.Builder<Builder> implements\n"
+      "    com.google.protobuf.GeneratedMessage$ver$.Builder<Builder> implements\n"
       "    $extra_interfaces$\n"
       "    $classname$OrBuilder {\n",
       "classname", name_resolver_->GetImmutableClassName(descriptor_),
-      "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
+      "extra_interfaces", ExtraBuilderInterfaces(descriptor_),
+      "ver", GeneratedCodeVersionSuffix());
   }
   printer->Indent();
 
   GenerateDescriptorMethods(printer);
   GenerateCommonBuilderMethods(printer);
 
-  if (HasGeneratedMethods(descriptor_)) {
+  if (context_->HasGeneratedMethods(descriptor_)) {
     GenerateIsInitialized(printer);
     GenerateBuilderParsingMethods(printer);
   }
 
   // oneof
-  map<string, string> vars;
+  std::map<string, string> vars;
   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
     vars["oneof_name"] = context_->GetOneofGeneratorInfo(
         descriptor_->oneof_decl(i))->name;
@@ -134,7 +135,7 @@
     printer->Print(vars,
       "public $oneof_capitalized_name$Case\n"
       "    get$oneof_capitalized_name$Case() {\n"
-      "  return $oneof_capitalized_name$Case.valueOf(\n"
+      "  return $oneof_capitalized_name$Case.forNumber(\n"
       "      $oneof_name$Case_);\n"
       "}\n"
       "\n"
@@ -168,19 +169,27 @@
                      .GenerateBuilderMembers(printer);
   }
 
-  if (!PreserveUnknownFields(descriptor_)) {
-    printer->Print(
-      "public final Builder setUnknownFields(\n"
-      "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
-      "  return this;\n"
-      "}\n"
-      "\n"
-      "public final Builder mergeUnknownFields(\n"
-      "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
-      "  return this;\n"
-      "}\n"
-      "\n");
-  }
+  bool is_proto3 =
+      descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
+    // Override methods declared in GeneratedMessage to return the concrete
+    // generated type so callsites won't depend on GeneratedMessage. This
+    // is needed to keep binary compatibility when we change generated code
+    // to subclass a different GeneratedMessage class (e.g., in v3.0.0 release
+    // we changed all generated code to subclass GeneratedMessageV3).
+  printer->Print(
+    "@java.lang.Override\n"
+    "public final Builder setUnknownFields(\n"
+    "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
+    "  return super.setUnknownFields$suffix$(unknownFields);\n"
+    "}\n"
+    "\n"
+    "@java.lang.Override\n"
+    "public final Builder mergeUnknownFields(\n"
+    "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
+    "  return super.mergeUnknownFields(unknownFields);\n"
+    "}\n"
+    "\n",
+    "suffix", is_proto3 ? "Proto3" : "");
 
   printer->Print(
     "\n"
@@ -205,7 +214,7 @@
       "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
       "identifier", UniqueFileScopeIdentifier(descriptor_));
   }
-  vector<const FieldDescriptor*> map_fields;
+  std::vector<const FieldDescriptor*> map_fields;
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
     if (GetJavaType(field) == JAVATYPE_MESSAGE &&
@@ -267,7 +276,8 @@
         "}\n");
   }
   printer->Print(
-    "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+    "@java.lang.Override\n"
+    "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
     "    internalGetFieldAccessorTable() {\n"
     "  return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
     "      .ensureFieldAccessorsInitialized(\n"
@@ -276,7 +286,8 @@
     "\n",
     "classname", name_resolver_->GetImmutableClassName(descriptor_),
     "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
-    "identifier", UniqueFileScopeIdentifier(descriptor_));
+    "identifier", UniqueFileScopeIdentifier(descriptor_),
+    "ver", GeneratedCodeVersionSuffix());
 }
 
 // ===================================================================
@@ -293,15 +304,18 @@
 
   printer->Print(
     "private Builder(\n"
-    "    com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
+    "    com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n"
     "  super(parent);\n"
     "  maybeForceBuilderInitialization();\n"
     "}\n",
-    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+    "classname", name_resolver_->GetImmutableClassName(descriptor_),
+    "ver", GeneratedCodeVersionSuffix());
 
   printer->Print(
     "private void maybeForceBuilderInitialization() {\n"
-    "  if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n");
+    "  if (com.google.protobuf.GeneratedMessage$ver$\n"
+    "          .alwaysUseFieldBuilders) {\n",
+    "ver", GeneratedCodeVersionSuffix());
 
   printer->Indent();
   printer->Indent();
@@ -319,6 +333,7 @@
     "}\n");
 
   printer->Print(
+    "@java.lang.Override\n"
     "public Builder clear() {\n"
     "  super.clear();\n");
 
@@ -347,6 +362,7 @@
     "\n");
 
   printer->Print(
+    "@java.lang.Override\n"
     "public com.google.protobuf.Descriptors.Descriptor\n"
     "    getDescriptorForType() {\n"
     "  return $fileclass$.internal_$identifier$_descriptor;\n"
@@ -357,6 +373,7 @@
 
   // LITE runtime implements this in GeneratedMessageLite.
   printer->Print(
+    "@java.lang.Override\n"
     "public $classname$ getDefaultInstanceForType() {\n"
     "  return $classname$.getDefaultInstance();\n"
     "}\n"
@@ -364,6 +381,7 @@
     "classname", name_resolver_->GetImmutableClassName(descriptor_));
 
   printer->Print(
+    "@java.lang.Override\n"
     "public $classname$ build() {\n"
     "  $classname$ result = buildPartial();\n"
     "  if (!result.isInitialized()) {\n"
@@ -375,6 +393,7 @@
     "classname", name_resolver_->GetImmutableClassName(descriptor_));
 
   printer->Print(
+    "@java.lang.Override\n"
     "public $classname$ buildPartial() {\n"
     "  $classname$ result = new $classname$(this);\n",
     "classname", name_resolver_->GetImmutableClassName(descriptor_));
@@ -437,10 +456,82 @@
     "\n",
     "classname", name_resolver_->GetImmutableClassName(descriptor_));
 
+  // Override methods declared in GeneratedMessage to return the concrete
+  // generated type so callsites won't depend on GeneratedMessage. This
+  // is needed to keep binary compatibility when we change generated code
+  // to subclass a different GeneratedMessage class (e.g., in v3.0.0 release
+  // we changed all generated code to subclass GeneratedMessageV3).
+  printer->Print(
+    "@java.lang.Override\n"
+    "public Builder clone() {\n"
+    "  return (Builder) super.clone();\n"
+    "}\n"
+    "@java.lang.Override\n"
+    "public Builder setField(\n"
+    "    com.google.protobuf.Descriptors.FieldDescriptor field,\n"
+    "    java.lang.Object value) {\n"
+    "  return (Builder) super.setField(field, value);\n"
+    "}\n"
+    "@java.lang.Override\n"
+    "public Builder clearField(\n"
+    "    com.google.protobuf.Descriptors.FieldDescriptor field) {\n"
+    "  return (Builder) super.clearField(field);\n"
+    "}\n"
+    "@java.lang.Override\n"
+    "public Builder clearOneof(\n"
+    "    com.google.protobuf.Descriptors.OneofDescriptor oneof) {\n"
+    "  return (Builder) super.clearOneof(oneof);\n"
+    "}\n"
+    "@java.lang.Override\n"
+    "public Builder setRepeatedField(\n"
+    "    com.google.protobuf.Descriptors.FieldDescriptor field,\n"
+    "    int index, java.lang.Object value) {\n"
+    "  return (Builder) super.setRepeatedField(field, index, value);\n"
+    "}\n"
+    "@java.lang.Override\n"
+    "public Builder addRepeatedField(\n"
+    "    com.google.protobuf.Descriptors.FieldDescriptor field,\n"
+    "    java.lang.Object value) {\n"
+    "  return (Builder) super.addRepeatedField(field, value);\n"
+    "}\n");
+
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(
+      "@java.lang.Override\n"
+      "public <Type> Builder setExtension(\n"
+      "    com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+      "        $classname$, Type> extension,\n"
+      "    Type value) {\n"
+      "  return (Builder) super.setExtension(extension, value);\n"
+      "}\n"
+      "@java.lang.Override\n"
+      "public <Type> Builder setExtension(\n"
+      "    com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+      "        $classname$, java.util.List<Type>> extension,\n"
+      "    int index, Type value) {\n"
+      "  return (Builder) super.setExtension(extension, index, value);\n"
+      "}\n"
+      "@java.lang.Override\n"
+      "public <Type> Builder addExtension(\n"
+      "    com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+      "        $classname$, java.util.List<Type>> extension,\n"
+      "    Type value) {\n"
+      "  return (Builder) super.addExtension(extension, value);\n"
+      "}\n"
+      "@java.lang.Override\n"
+      "public <Type> Builder clearExtension(\n"
+      "    com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
+      "        $classname$, ?> extension) {\n"
+      "  return (Builder) super.clearExtension(extension);\n"
+      "}\n",
+      "classname", name_resolver_->GetImmutableClassName(descriptor_));
+  }
+
   // -----------------------------------------------------------------
 
-  if (HasGeneratedMethods(descriptor_)) {
+  if (context_->HasGeneratedMethods(descriptor_)) {
     printer->Print(
+      "@java.lang.Override\n"
       "public Builder mergeFrom(com.google.protobuf.Message other) {\n"
       "  if (other instanceof $classname$) {\n"
       "    return mergeFrom(($classname$)other);\n"
@@ -509,10 +600,8 @@
         "  this.mergeExtensionFields(other);\n");
     }
 
-    if (PreserveUnknownFields(descriptor_)) {
-      printer->Print(
-        "  this.mergeUnknownFields(other.unknownFields);\n");
-    }
+    printer->Print(
+      "  this.mergeUnknownFields(other.unknownFields);\n");
 
     printer->Print(
       "  onChanged();\n");
@@ -529,6 +618,7 @@
 void MessageBuilderGenerator::
 GenerateBuilderParsingMethods(io::Printer* printer) {
   printer->Print(
+    "@java.lang.Override\n"
     "public Builder mergeFrom(\n"
     "    com.google.protobuf.CodedInputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
@@ -554,6 +644,7 @@
 void MessageBuilderGenerator::GenerateIsInitialized(
     io::Printer* printer) {
   printer->Print(
+    "@java.lang.Override\n"
     "public final boolean isInitialized() {\n");
   printer->Indent();
 
@@ -614,7 +705,7 @@
         case FieldDescriptor::LABEL_REPEATED:
           if (IsMapEntry(field->message_type())) {
             printer->Print(
-              "for ($type$ item : get$name$().values()) {\n"
+              "for ($type$ item : get$name$Map().values()) {\n"
               "  if (!item.isInitialized()) {\n"
               "    return false;\n"
               "  }\n"
diff --git a/src/google/protobuf/compiler/java/java_message_builder_lite.cc b/src/google/protobuf/compiler/java/java_message_builder_lite.cc
index 8719d00..f04d394 100644
--- a/src/google/protobuf/compiler/java/java_message_builder_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_builder_lite.cc
@@ -38,9 +38,6 @@
 #include <google/protobuf/stubs/hash.h>
 #include <map>
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 #include <vector>
 
 #include <google/protobuf/compiler/java/java_context.h>
@@ -50,12 +47,12 @@
 #include <google/protobuf/compiler/java/java_generator_factory.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/printer.h>
-#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/strutil.h>
 
 namespace google {
 namespace protobuf {
@@ -67,13 +64,6 @@
   return SupportFieldPresence(descriptor->file()) ||
       HasRepeatedFields(descriptor);
 }
-
-string MapValueImmutableClassdName(const Descriptor* descriptor,
-                                   ClassNameResolver* name_resolver) {
-  const FieldDescriptor* value_field = descriptor->FindFieldByName("value");
-  GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
-  return name_resolver->GetImmutableClassName(value_field->message_type());
-}
 }  // namespace
 
 MessageBuilderLiteGenerator::MessageBuilderLiteGenerator(
@@ -81,8 +71,9 @@
   : descriptor_(descriptor), context_(context),
     name_resolver_(context->GetNameResolver()),
     field_generators_(descriptor, context_) {
-  GOOGLE_CHECK_EQ(
-      FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+  GOOGLE_CHECK(!HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+      << "Generator factory error: A lite message generator is used to "
+         "generate non-lite messages.";
 }
 
 MessageBuilderLiteGenerator::~MessageBuilderLiteGenerator() {}
@@ -105,7 +96,7 @@
   GenerateCommonBuilderMethods(printer);
 
   // oneof
-  map<string, string> vars;
+  std::map<string, string> vars;
   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
     vars["oneof_name"] = context_->GetOneofGeneratorInfo(
         descriptor_->oneof_decl(i))->name;
@@ -115,6 +106,7 @@
 
     // oneofCase() and clearOneof()
     printer->Print(vars,
+      "@java.lang.Override\n"
       "public $oneof_capitalized_name$Case\n"
       "    get$oneof_capitalized_name$Case() {\n"
       "  return instance.get$oneof_capitalized_name$Case();\n"
@@ -148,20 +140,6 @@
                      .GenerateBuilderMembers(printer);
   }
 
-  if (!PreserveUnknownFields(descriptor_)) {
-    printer->Print(
-      "public final Builder setUnknownFields(\n"
-      "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
-      "  return this;\n"
-      "}\n"
-      "\n"
-      "public final Builder mergeUnknownFields(\n"
-      "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
-      "  return this;\n"
-      "}\n"
-      "\n");
-  }
-
   printer->Print(
     "\n"
     "// @@protoc_insertion_point(builder_scope:$full_name$)\n",
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index b5f8e62..baa7f87 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -56,7 +56,7 @@
                          int builderBitIndex,
                          const FieldGeneratorInfo* info,
                          ClassNameResolver* name_resolver,
-                         map<string, string>* variables) {
+                         std::map<string, string>* variables) {
   SetCommonFieldVariables(descriptor, info, variables);
 
   (*variables)["type"] =
@@ -70,8 +70,11 @@
   // by the proto compiler
   (*variables)["deprecation"] = descriptor->options().deprecated()
       ? "@java.lang.Deprecated " : "";
-  (*variables)["on_changed"] =
-      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+  (*variables)["on_changed"] = "onChanged();";
+  (*variables)["ver"] = GeneratedCodeVersionSuffix();
+  (*variables)["get_parser"] =
+      ExposePublicParser(descriptor->message_type()->file())
+          ? "PARSER" : "parser()";
 
   if (SupportFieldPresence(descriptor->file())) {
     // For singular messages and builders, one bit is used for the hasField bit.
@@ -147,12 +150,9 @@
   // 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.
-  if (SupportFieldPresence(descriptor_->file()) ||
-      descriptor_->containing_oneof() == NULL) {
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(variables_,
-      "$deprecation$boolean has$capitalized_name$();\n");
-  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$boolean has$capitalized_name$();\n");
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$$type$ get$capitalized_name$();\n");
@@ -171,39 +171,45 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public $type$ get$capitalized_name$() {\n"
+      "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
       "  return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
 
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
       "$deprecation$public $type$OrBuilder "
-      "get$capitalized_name$OrBuilder() {\n"
+      "${$get$capitalized_name$OrBuilder$}$() {\n"
       "  return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   } else {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $name$_ != null;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public $type$ get$capitalized_name$() {\n"
+      "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
       "  return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
 
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
       "$deprecation$public $type$OrBuilder "
-      "get$capitalized_name$OrBuilder() {\n"
+      "${$get$capitalized_name$OrBuilder$}$() {\n"
       "  return get$capitalized_name$();\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 }
 
@@ -229,6 +235,7 @@
     const char* nested_builder_case,
     const char* trailing_code) const {
   printer->Print(variables_, method_prototype);
+  printer->Annotate("{", "}", descriptor_);
   printer->Print(" {\n");
   printer->Indent();
   PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
@@ -253,7 +260,7 @@
   printer->Print(variables_,
       // If this builder is non-null, it is used and the other fields are
       // ignored.
-      "private com.google.protobuf.SingleFieldBuilder<\n"
+      "private com.google.protobuf.SingleFieldBuilder$ver$<\n"
       "    $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
       "\n");
 
@@ -264,20 +271,22 @@
   WriteFieldDocComment(printer, descriptor_);
   if (support_field_presence) {
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_builder$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   } else {
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $name$Builder_ != null || $name$_ != null;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   // Field getField()
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public $type$ get$capitalized_name$()",
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$()",
     "return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n",
     "return $name$Builder_.getMessage();\n",
     NULL);
@@ -285,7 +294,7 @@
   // Field.Builder setField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder set$capitalized_name$($type$ value)",
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value)",
 
     "if (value == null) {\n"
     "  throw new NullPointerException();\n"
@@ -301,7 +310,7 @@
   // Field.Builder setField(Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    $type$.Builder builderForValue)",
 
     "$name$_ = builderForValue.build();\n"
@@ -315,7 +324,7 @@
   // Field.Builder mergeField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder merge$capitalized_name$($type$ value)",
+    "$deprecation$public Builder ${$merge$capitalized_name$$}$($type$ value)",
 
     support_field_presence
         ? "if ($get_has_field_bit_builder$ &&\n"
@@ -343,7 +352,7 @@
   // Field.Builder clearField()
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder clear$capitalized_name$()",
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$()",
 
     "$name$_ = null;\n"
     "$on_changed$\n",
@@ -358,14 +367,17 @@
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
+    "$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");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+    "$deprecation$public $type$OrBuilder "
+    "${$get$capitalized_name$OrBuilder$}$() {\n"
     "  if ($name$Builder_ != null) {\n"
     "    return $name$Builder_.getMessageOrBuilder();\n"
     "  } else {\n"
@@ -373,13 +385,14 @@
     "        $type$.getDefaultInstance() : $name$_;\n"
     "  }\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "private com.google.protobuf.SingleFieldBuilder<\n"
+    "private com.google.protobuf.SingleFieldBuilder$ver$<\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"
+    "    $name$Builder_ = new com.google.protobuf.SingleFieldBuilder$ver$<\n"
     "        $type$, $type$.Builder, $type$OrBuilder>(\n"
     "            get$capitalized_name$(),\n"
     "            getParentForChildren(),\n"
@@ -452,11 +465,11 @@
 
   if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
     printer->Print(variables_,
-      "$name$_ = input.readGroup($number$, $type$.parser(),\n"
+      "$name$_ = input.readGroup($number$, $type$.$get_parser$,\n"
       "    extensionRegistry);\n");
   } else {
     printer->Print(variables_,
-      "$name$_ = input.readMessage($type$.parser(), extensionRegistry);\n");
+      "$name$_ = input.readMessage($type$.$get_parser$, extensionRegistry);\n");
   }
 
   printer->Print(variables_,
@@ -527,30 +540,32 @@
 void ImmutableMessageOneofFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_->file())) {
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
-      "  return $has_oneof_case_message$;\n"
-      "}\n");
-  }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+    "  return $has_oneof_case_message$;\n"
+    "}\n");
+  printer->Annotate("{", "}", descriptor_);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "     return ($type$) $oneof_name$_;\n"
     "  }\n"
     "  return $type$.getDefaultInstance();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+    "$deprecation$public $type$OrBuilder "
+    "${$get$capitalized_name$OrBuilder$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "     return ($type$) $oneof_name$_;\n"
     "  }\n"
     "  return $type$.getDefaultInstance();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableMessageOneofFieldGenerator::
@@ -561,26 +576,25 @@
   printer->Print(variables_,
     // If this builder is non-null, it is used and the other fields are
     // ignored.
-    "private com.google.protobuf.SingleFieldBuilder<\n"
+    "private com.google.protobuf.SingleFieldBuilder$ver$<\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".
 
-  if (SupportFieldPresence(descriptor_->file())) {
-    // boolean hasField()
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
-      "  return $has_oneof_case_message$;\n"
-      "}\n");
-  }
+  // boolean hasField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+    "  return $has_oneof_case_message$;\n"
+    "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field getField()
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public $type$ get$capitalized_name$()",
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$()",
 
     "if ($has_oneof_case_message$) {\n"
     "  return ($type$) $oneof_name$_;\n"
@@ -597,7 +611,7 @@
   // Field.Builder setField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder set$capitalized_name$($type$ value)",
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value)",
 
     "if (value == null) {\n"
     "  throw new NullPointerException();\n"
@@ -613,7 +627,7 @@
   // Field.Builder setField(Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    $type$.Builder builderForValue)",
 
     "$oneof_name$_ = builderForValue.build();\n"
@@ -627,7 +641,7 @@
   // Field.Builder mergeField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder merge$capitalized_name$($type$ value)",
+    "$deprecation$public Builder ${$merge$capitalized_name$$}$($type$ value)",
 
     "if ($has_oneof_case_message$ &&\n"
     "    $oneof_name$_ != $type$.getDefaultInstance()) {\n"
@@ -649,7 +663,7 @@
   // Field.Builder clearField()
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder clear$capitalized_name$()",
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$()",
 
     "if ($has_oneof_case_message$) {\n"
     "  $clear_oneof_case_message$;\n"
@@ -667,12 +681,15 @@
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
+    "$deprecation$public $type$.Builder "
+    "${$get$capitalized_name$Builder$}$() {\n"
     "  return get$capitalized_name$FieldBuilder().getBuilder();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+    "$deprecation$public $type$OrBuilder "
+    "${$get$capitalized_name$OrBuilder$}$() {\n"
     "  if (($has_oneof_case_message$) && ($name$Builder_ != null)) {\n"
     "    return $name$Builder_.getMessageOrBuilder();\n"
     "  } else {\n"
@@ -682,16 +699,17 @@
     "    return $type$.getDefaultInstance();\n"
     "  }\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "private com.google.protobuf.SingleFieldBuilder<\n"
+    "private com.google.protobuf.SingleFieldBuilder$ver$<\n"
     "    $type$, $type$.Builder, $type$OrBuilder> \n"
-    "    get$capitalized_name$FieldBuilder() {\n"
+    "    ${$get$capitalized_name$FieldBuilder$}$() {\n"
     "  if ($name$Builder_ == null) {\n"
     "    if (!($has_oneof_case_message$)) {\n"
     "      $oneof_name$_ = $type$.getDefaultInstance();\n"
     "    }\n"
-    "    $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
+    "    $name$Builder_ = new com.google.protobuf.SingleFieldBuilder$ver$<\n"
     "        $type$, $type$.Builder, $type$OrBuilder>(\n"
     "            ($type$) $oneof_name$_,\n"
     "            getParentForChildren(),\n"
@@ -702,6 +720,7 @@
     "  $on_changed$;\n"
     "  return $name$Builder_;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableMessageOneofFieldGenerator::
@@ -736,12 +755,12 @@
 
   if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
     printer->Print(variables_,
-      "$oneof_name$_ = input.readGroup($number$, $type$.parser(),\n"
+      "$oneof_name$_ = input.readGroup($number$, $type$.$get_parser$,\n"
       "    extensionRegistry);\n");
   } else {
     printer->Print(variables_,
       "$oneof_name$_ =\n"
-      "    input.readMessage($type$.parser(), extensionRegistry);\n");
+      "    input.readMessage($type$.$get_parser$, extensionRegistry);\n");
   }
 
   printer->Print(variables_,
@@ -830,31 +849,38 @@
   PrintExtraFieldInfo(variables_, printer);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "$deprecation$public java.util.List<$type$> "
+    "${$get$capitalized_name$List$}$() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
-    "    get$capitalized_name$OrBuilderList() {\n"
+    "    ${$get$capitalized_name$OrBuilderList$}$() {\n"
     "  return $name$_;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+    "$deprecation$public $type$OrBuilder "
+    "${$get$capitalized_name$OrBuilder$}$(\n"
     "    int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
 }
 
@@ -880,6 +906,7 @@
     const char* nested_builder_case,
     const char* trailing_code) const {
   printer->Print(variables_, method_prototype);
+  printer->Annotate("{", "}", descriptor_);
   printer->Print(" {\n");
   printer->Indent();
   PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
@@ -921,7 +948,7 @@
   printer->Print(variables_,
     // If this builder is non-null, it is used and the other fields are
     // ignored.
-    "private com.google.protobuf.RepeatedFieldBuilder<\n"
+    "private com.google.protobuf.RepeatedFieldBuilder$ver$<\n"
     "    $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
     "\n");
 
@@ -931,7 +958,8 @@
   // List<Field> getRepeatedFieldList()
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public java.util.List<$type$> get$capitalized_name$List()",
+    "$deprecation$public java.util.List<$type$> "
+    "${$get$capitalized_name$List$}$()",
 
     "return java.util.Collections.unmodifiableList($name$_);\n",
     "return $name$Builder_.getMessageList();\n",
@@ -941,7 +969,7 @@
   // int getRepeatedFieldCount()
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public int get$capitalized_name$Count()",
+    "$deprecation$public int ${$get$capitalized_name$Count$}$()",
 
     "return $name$_.size();\n",
     "return $name$Builder_.getCount();\n",
@@ -951,7 +979,7 @@
   // Field getRepeatedField(int index)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public $type$ get$capitalized_name$(int index)",
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index)",
 
     "return $name$_.get(index);\n",
 
@@ -962,7 +990,7 @@
   // Builder setRepeatedField(int index, Field value)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, $type$ value)",
     "if (value == null) {\n"
     "  throw new NullPointerException();\n"
@@ -976,7 +1004,7 @@
   // Builder setRepeatedField(int index, Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, $type$.Builder builderForValue)",
 
     "ensure$capitalized_name$IsMutable();\n"
@@ -990,7 +1018,7 @@
   // Builder addRepeatedField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder add$capitalized_name$($type$ value)",
+    "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value)",
 
     "if (value == null) {\n"
     "  throw new NullPointerException();\n"
@@ -1007,7 +1035,7 @@
   // Builder addRepeatedField(int index, Field value)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder add$capitalized_name$(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
     "    int index, $type$ value)",
 
     "if (value == null) {\n"
@@ -1024,7 +1052,7 @@
   // Builder addRepeatedField(Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder add$capitalized_name$(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
     "    $type$.Builder builderForValue)",
 
     "ensure$capitalized_name$IsMutable();\n"
@@ -1038,7 +1066,7 @@
   // Builder addRepeatedField(int index, Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder add$capitalized_name$(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
     "    int index, $type$.Builder builderForValue)",
 
     "ensure$capitalized_name$IsMutable();\n"
@@ -1052,7 +1080,7 @@
   // Builder addAllRepeatedField(Iterable<Field> values)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
     "    java.lang.Iterable<? extends $type$> values)",
 
     "ensure$capitalized_name$IsMutable();\n"
@@ -1067,7 +1095,7 @@
   // Builder clearAllRepeatedField()
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder clear$capitalized_name$()",
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$()",
 
     "$name$_ = java.util.Collections.emptyList();\n"
     "$clear_mutable_bit_builder$;\n"
@@ -1080,7 +1108,7 @@
   // Builder removeRepeatedField(int index)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder remove$capitalized_name$(int index)",
+    "$deprecation$public Builder ${$remove$capitalized_name$$}$(int index)",
 
     "ensure$capitalized_name$IsMutable();\n"
     "$name$_.remove(index);\n"
@@ -1092,14 +1120,16 @@
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
+    "$deprecation$public $type$.Builder ${$get$capitalized_name$Builder$}$(\n"
     "    int index) {\n"
     "  return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
       printer->Print(variables_,
-    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+    "$deprecation$public $type$OrBuilder "
+    "${$get$capitalized_name$OrBuilder$}$(\n"
     "    int index) {\n"
     "  if ($name$Builder_ == null) {\n"
     "    return $name$_.get(index);"
@@ -1107,42 +1137,47 @@
     "    return $name$Builder_.getMessageOrBuilder(index);\n"
     "  }\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
       printer->Print(variables_,
     "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
-    "     get$capitalized_name$OrBuilderList() {\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");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
       printer->Print(variables_,
-    "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
+    "$deprecation$public $type$.Builder "
+    "${$add$capitalized_name$Builder$}$() {\n"
     "  return get$capitalized_name$FieldBuilder().addBuilder(\n"
     "      $type$.getDefaultInstance());\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
       printer->Print(variables_,
-    "$deprecation$public $type$.Builder add$capitalized_name$Builder(\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");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
       printer->Print(variables_,
     "$deprecation$public java.util.List<$type$.Builder> \n"
-    "     get$capitalized_name$BuilderList() {\n"
+    "     ${$get$capitalized_name$BuilderList$}$() {\n"
     "  return get$capitalized_name$FieldBuilder().getBuilderList();\n"
     "}\n"
-    "private com.google.protobuf.RepeatedFieldBuilder<\n"
+    "private com.google.protobuf.RepeatedFieldBuilder$ver$<\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"
+    "    $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder$ver$<\n"
     "        $type$, $type$.Builder, $type$OrBuilder>(\n"
     "            $name$_,\n"
     "            $get_mutable_bit_builder$,\n"
@@ -1152,6 +1187,7 @@
     "  }\n"
     "  return $name$Builder_;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedImmutableMessageFieldGenerator::
@@ -1200,7 +1236,7 @@
     "    $name$_ = other.$name$_;\n"
     "    $clear_mutable_bit_builder$;\n"
     "    $name$Builder_ = \n"
-    "      com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?\n"
+    "      com.google.protobuf.GeneratedMessage$ver$.alwaysUseFieldBuilders ?\n"
     "         get$capitalized_name$FieldBuilder() : null;\n"
     "  } else {\n"
     "    $name$Builder_.addAllMessages(other.$name$_);\n"
@@ -1233,11 +1269,12 @@
 
   if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
     printer->Print(variables_,
-      "$name$_.add(input.readGroup($number$, $type$.parser(),\n"
+      "$name$_.add(input.readGroup($number$, $type$.$get_parser$,\n"
       "    extensionRegistry));\n");
   } else {
     printer->Print(variables_,
-      "$name$_.add(input.readMessage($type$.parser(), extensionRegistry));\n");
+      "$name$_.add(\n"
+      "    input.readMessage($type$.$get_parser$, extensionRegistry));\n");
   }
 }
 
diff --git a/src/google/protobuf/compiler/java/java_message_field.h b/src/google/protobuf/compiler/java/java_message_field.h
index ea8225a..7ee0edb 100644
--- a/src/google/protobuf/compiler/java/java_message_field.h
+++ b/src/google/protobuf/compiler/java/java_message_field.h
@@ -82,7 +82,7 @@
 
  protected:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   const int messageBitIndex_;
   const int builderBitIndex_;
   Context* context_;
@@ -148,7 +148,7 @@
 
  protected:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   const int messageBitIndex_;
   const int builderBitIndex_;
   Context* context_;
diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.cc b/src/google/protobuf/compiler/java/java_message_field_lite.cc
index 356520e..9cf6f36 100644
--- a/src/google/protobuf/compiler/java/java_message_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_field_lite.cc
@@ -56,7 +56,7 @@
                          int builderBitIndex,
                          const FieldGeneratorInfo* info,
                          ClassNameResolver* name_resolver,
-                         map<string, string>* variables) {
+                         std::map<string, string>* variables) {
   SetCommonFieldVariables(descriptor, info, variables);
 
   (*variables)["type"] =
@@ -70,8 +70,7 @@
   // by the proto compiler
   (*variables)["deprecation"] = descriptor->options().deprecated()
       ? "@java.lang.Deprecated " : "";
-  (*variables)["on_changed"] =
-      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+  (*variables)["required"] = descriptor->is_required() ? "true" : "false";
 
   if (SupportFieldPresence(descriptor->file())) {
     // For singular messages and builders, one bit is used for the hasField bit.
@@ -130,16 +129,9 @@
 
 void ImmutableMessageFieldLiteGenerator::
 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.
-  if (SupportFieldPresence(descriptor_->file()) ||
-      descriptor_->containing_oneof() == NULL) {
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(variables_,
-      "$deprecation$boolean has$capitalized_name$();\n");
-  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$boolean has$capitalized_name$();\n");
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$$type$ get$capitalized_name$();\n");
@@ -147,6 +139,7 @@
 
 void ImmutableMessageFieldLiteGenerator::
 GenerateMembers(io::Printer* printer) const {
+
   printer->Print(variables_,
     "private $type$ $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
@@ -154,25 +147,33 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public $type$ get$capitalized_name$() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
       "  return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   } else {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $name$_ != null;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public $type$ get$capitalized_name$() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
       "  return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   // Field.Builder setField(Field value)
@@ -198,7 +199,11 @@
   // Field.Builder mergeField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
+    "@java.lang.SuppressWarnings({\"ReferenceEquality\"})\n"
     "private void merge$capitalized_name$($type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
     "  if ($name$_ != null &&\n"
     "      $name$_ != $type$.getDefaultInstance()) {\n"
     "    $name$_ =\n"
@@ -226,53 +231,62 @@
   // boolean hasField()
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
     "  return instance.has$capitalized_name$();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field getField()
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  return instance.get$capitalized_name$();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field.Builder setField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(value);\n"
     "  return this;\n"
     "  }\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field.Builder setField(Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    $type$.Builder builderForValue) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(builderForValue);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field.Builder mergeField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder "
+    "${$merge$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.merge$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field.Builder clearField()
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableMessageFieldLiteGenerator::
@@ -288,11 +302,9 @@
 GenerateInitializationCode(io::Printer* printer) const {}
 
 void ImmutableMessageFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
+GenerateVisitCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (other.has$capitalized_name$()) {\n"
-    "  merge$capitalized_name$(other.get$capitalized_name$());\n"
-    "}\n");
+    "$name$_ = visitor.visitMessage($name$_, other.$name$_);\n");
 }
 
 void ImmutableMessageFieldLiteGenerator::
@@ -302,11 +314,18 @@
 
 void ImmutableMessageFieldLiteGenerator::
 GenerateParsingCode(io::Printer* printer) const {
+  // TODO(dweis): Update this code to avoid the builder allocation and instead
+  // only allocate a submessage that isn't made immutable. Rely on the top
+  // message calling makeImmutable once done to actually traverse the tree and
+  // finalize state. This will avoid:
+  // - transitive builder allocations
+  // - the extra transitive iteration for streamed fields
+  // - reallocations for copying repeated fields
   printer->Print(variables_,
-    "$type$.Builder subBuilder = null;\n"
-    "if ($is_field_present_message$) {\n"
-    "  subBuilder = $name$_.toBuilder();\n"
-    "}\n");
+      "$type$.Builder subBuilder = null;\n"
+      "if ($is_field_present_message$) {\n"
+      "  subBuilder = $name$_.toBuilder();\n"
+      "}\n");
 
     if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
       printer->Print(variables_,
@@ -385,21 +404,23 @@
 void ImmutableMessageOneofFieldLiteGenerator::
 GenerateMembers(io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_->file())) {
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
-      "  return $has_oneof_case_message$;\n"
-      "}\n");
-  }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+    "  return $has_oneof_case_message$;\n"
+    "}\n");
+  printer->Annotate("{", "}", descriptor_);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "@java.lang.Override\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "     return ($type$) $oneof_name$_;\n"
     "  }\n"
     "  return $type$.getDefaultInstance();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field.Builder setField(Field value)
   WriteFieldDocComment(printer, descriptor_);
@@ -425,6 +446,9 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "private void merge$capitalized_name$($type$ value) {\n"
+    "  if (value == null) {\n"
+    "    throw new NullPointerException();\n"
+    "  }\n"
     "  if ($has_oneof_case_message$ &&\n"
     "      $oneof_name$_ != $type$.getDefaultInstance()) {\n"
     "    $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n"
@@ -446,69 +470,80 @@
     "}\n");
 }
 
+
 void ImmutableMessageOneofFieldLiteGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
   // The comments above the methods below are based on a hypothetical
   // field of type "Field" called "Field".
 
-  if (SupportFieldPresence(descriptor_->file())) {
-    // boolean hasField()
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
-      "  return instance.has$capitalized_name$();\n"
-      "}\n");
-  }
+  // boolean hasField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "@java.lang.Override\n"
+    "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+    "  return instance.has$capitalized_name$();\n"
+    "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field getField()
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  return instance.get$capitalized_name$();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field.Builder setField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field.Builder setField(Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    $type$.Builder builderForValue) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(builderForValue);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field.Builder mergeField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder "
+    "${$merge$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.merge$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field.Builder clearField()
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableMessageOneofFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
+GenerateVisitCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "merge$capitalized_name$(other.get$capitalized_name$());\n");
+    "$oneof_name$_ = visitor.visitOneofMessage(\n"
+    "    $has_oneof_case_message$,\n"
+    "    $oneof_name$_,\n"
+    "    other.$oneof_name$_);\n");
 }
 
 void ImmutableMessageOneofFieldLiteGenerator::
@@ -606,36 +641,47 @@
   PrintExtraFieldInfo(variables_, printer);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public java.util.List<$type$> "
+    "${$get$capitalized_name$List$}$() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
-    "    get$capitalized_name$OrBuilderList() {\n"
+    "    ${$get$capitalized_name$OrBuilderList$}$() {\n"
     "  return $name$_;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+    "$deprecation$public $type$OrBuilder "
+    "${$get$capitalized_name$OrBuilder$}$(\n"
     "    int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   printer->Print(variables_,
     "private void ensure$capitalized_name$IsMutable() {\n"
     "  if (!$is_mutable$) {\n"
-    "    $name$_ = newProtobufList($name$_);\n"
+    "    $name$_ =\n"
+    "        com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
     "   }\n"
     "}\n"
     "\n");
@@ -735,110 +781,126 @@
   // List<Field> getRepeatedFieldList()
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public java.util.List<$type$> "
+    "${$get$capitalized_name$List$}$() {\n"
     "  return java.util.Collections.unmodifiableList(\n"
     "      instance.get$capitalized_name$List());\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // int getRepeatedFieldCount()
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return instance.get$capitalized_name$Count();\n"
     "}");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field getRepeatedField(int index)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return instance.get$capitalized_name$(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Builder setRepeatedField(int index, Field value)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, $type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(index, value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Builder setRepeatedField(int index, Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, $type$.Builder builderForValue) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(index, builderForValue);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Builder addRepeatedField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.add$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Builder addRepeatedField(int index, Field value)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
     "    int index, $type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.add$capitalized_name$(index, value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   // Builder addRepeatedField(Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
     "    $type$.Builder builderForValue) {\n"
     "  copyOnWrite();\n"
     "  instance.add$capitalized_name$(builderForValue);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Builder addRepeatedField(int index, Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
     "    int index, $type$.Builder builderForValue) {\n"
     "  copyOnWrite();\n"
     "  instance.add$capitalized_name$(index, builderForValue);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Builder addAllRepeatedField(Iterable<Field> values)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
     "    java.lang.Iterable<? extends $type$> values) {\n"
     "  copyOnWrite();\n"
     "  instance.addAll$capitalized_name$(values);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Builder clearAllRepeatedField()
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Builder removeRepeatedField(int index)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder remove$capitalized_name$(int index) {\n"
+    "$deprecation$public Builder ${$remove$capitalized_name$$}$(int index) {\n"
     "  copyOnWrite();\n"
     "  instance.remove$capitalized_name$(index);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedImmutableMessageFieldLiteGenerator::
@@ -847,28 +909,16 @@
     "get$capitalized_name$FieldBuilder();\n");
 }
 
+
 void RepeatedImmutableMessageFieldLiteGenerator::
 GenerateInitializationCode(io::Printer* printer) const {
   printer->Print(variables_, "$name$_ = emptyProtobufList();\n");
 }
 
 void RepeatedImmutableMessageFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
-  // 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.
+GenerateVisitCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (!other.$name$_.isEmpty()) {\n"
-    "  if ($name$_.isEmpty()) {\n"
-    "    $name$_ = other.$name$_;\n"
-    "  } else {\n"
-    "    ensure$capitalized_name$IsMutable();\n"
-    "    $name$_.addAll(other.$name$_);\n"
-    "  }\n"
-    "  $on_changed$\n"
-    "}\n");
+      "$name$_= visitor.visitList($name$_, other.$name$_);\n");
 }
 
 void RepeatedImmutableMessageFieldLiteGenerator::
@@ -881,7 +931,8 @@
 GenerateParsingCode(io::Printer* printer) const {
   printer->Print(variables_,
     "if (!$is_mutable$) {\n"
-    "  $name$_ = newProtobufList();\n"
+    "  $name$_ =\n"
+    "      com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
     "}\n");
 
     if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.h b/src/google/protobuf/compiler/java/java_message_field_lite.h
index ae26c06..7c814c6 100644
--- a/src/google/protobuf/compiler/java/java_message_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_message_field_lite.h
@@ -67,7 +67,7 @@
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
   void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateParsingDoneCode(io::Printer* printer) const;
@@ -81,7 +81,7 @@
 
  protected:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   const int messageBitIndex_;
   const int builderBitIndex_;
   Context* context_;
@@ -101,11 +101,12 @@
 
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
 
+
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldLiteGenerator);
 };
@@ -125,7 +126,7 @@
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
   void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateParsingDoneCode(io::Printer* printer) const;
@@ -135,11 +136,12 @@
   void GenerateEqualsCode(io::Printer* printer) const;
   void GenerateHashCode(io::Printer* printer) const;
 
+
   string GetBoxedType() const;
 
  protected:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   const int messageBitIndex_;
   const int builderBitIndex_;
   Context* context_;
diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc
index 94ed2c3..3a512e8 100644
--- a/src/google/protobuf/compiler/java/java_message_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_lite.cc
@@ -38,26 +38,24 @@
 #include <google/protobuf/stubs/hash.h>
 #include <map>
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 #include <vector>
 
 #include <google/protobuf/compiler/java/java_context.h>
 #include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/compiler/java/java_enum_lite.h>
-#include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_extension_lite.h>
 #include <google/protobuf/compiler/java/java_generator_factory.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_message_builder.h>
 #include <google/protobuf/compiler/java/java_message_builder_lite.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/printer.h>
-#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/strutil.h>
+
 
 namespace google {
 namespace protobuf {
@@ -68,6 +66,14 @@
 using internal::WireFormatLite;
 
 namespace {
+bool EnableExperimentalRuntimeForLite() {
+#ifdef PROTOBUF_EXPERIMENT
+  return PROTOBUF_EXPERIMENT;
+#else   // PROTOBUF_EXPERIMENT
+  return false;
+#endif  // !PROTOBUF_EXPERIMENT
+}
+
 bool GenerateHasBits(const Descriptor* descriptor) {
   return SupportFieldPresence(descriptor->file()) ||
       HasRepeatedFields(descriptor);
@@ -87,19 +93,20 @@
   : MessageGenerator(descriptor), context_(context),
     name_resolver_(context->GetNameResolver()),
     field_generators_(descriptor, context_) {
-  GOOGLE_CHECK_EQ(
-      FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+  GOOGLE_CHECK(!HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
+      << "Generator factory error: A lite message generator is used to "
+         "generate non-lite messages.";
 }
 
 ImmutableMessageLiteGenerator::~ImmutableMessageLiteGenerator() {}
 
 void ImmutableMessageLiteGenerator::GenerateStaticVariables(
-    io::Printer* printer) {
+    io::Printer* printer, int* bytecode_estimate) {
   // Generate static members for all nested types.
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     // TODO(kenton):  Reuse MessageGenerator objects?
     ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
-      .GenerateStaticVariables(printer);
+        .GenerateStaticVariables(printer, bytecode_estimate);
   }
 }
 
@@ -119,23 +126,32 @@
 // ===================================================================
 
 void ImmutableMessageLiteGenerator::GenerateInterface(io::Printer* printer) {
+  MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
+                                /* immutable = */ true, "OrBuilder");
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(
-      "public interface $classname$OrBuilder extends \n"
-      "    $extra_interfaces$\n"
-      "     com.google.protobuf.GeneratedMessageLite.\n"
-      "          ExtendableMessageOrBuilder<\n"
-      "              $classname$, $classname$.Builder> {\n",
-      "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
-      "classname", descriptor_->name());
+        "$deprecation$public interface ${$$classname$OrBuilder$}$ extends \n"
+        "    $extra_interfaces$\n"
+        "     com.google.protobuf.GeneratedMessageLite.\n"
+        "          ExtendableMessageOrBuilder<\n"
+        "              $classname$, $classname$.Builder> {\n",
+        "deprecation", descriptor_->options().deprecated() ?
+            "@java.lang.Deprecated " : "",
+        "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+        "classname", descriptor_->name(),
+        "{", "", "}", "");
   } else {
     printer->Print(
-      "public interface $classname$OrBuilder extends\n"
-      "    $extra_interfaces$\n"
-      "    com.google.protobuf.MessageLiteOrBuilder {\n",
-      "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
-      "classname", descriptor_->name());
+        "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
+        "    $extra_interfaces$\n"
+        "    com.google.protobuf.MessageLiteOrBuilder {\n",
+        "deprecation", descriptor_->options().deprecated() ?
+            "@java.lang.Deprecated " : "",
+        "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+        "classname", descriptor_->name(),
+        "{", "", "}", "");
   }
+  printer->Annotate("{", "}", descriptor_);
 
   printer->Indent();
     for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -162,22 +178,25 @@
 // ===================================================================
 
 void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
-  bool is_own_file =
-    descriptor_->containing_type() == NULL &&
-    MultipleJavaFiles(descriptor_->file(), /* immutable = */ true);
+  bool is_own_file = IsOwnFile(descriptor_, /* immutable = */ true);
 
-  map<string, string> variables;
+  std::map<string, string> variables;
   variables["static"] = is_own_file ? " " : " static ";
   variables["classname"] = descriptor_->name();
   variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
+  variables["deprecation"] = descriptor_->options().deprecated()
+      ? "@java.lang.Deprecated " : "";
 
   WriteMessageDocComment(printer, descriptor_);
+  MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
+                                /* immutable = */ true);
+
 
   // The builder_type stores the super type name of the nested Builder class.
   string builder_type;
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(variables,
-      "public $static$final class $classname$ extends\n"
+      "$deprecation$public $static$final class $classname$ extends\n"
       "    com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n"
       "      $classname$, $classname$.Builder> implements\n"
       "    $extra_interfaces$\n"
@@ -187,7 +206,7 @@
         name_resolver_->GetImmutableClassName(descriptor_));
   } else {
     printer->Print(variables,
-        "public $static$final class $classname$ extends\n"
+        "$deprecation$public $static$final class $classname$ extends\n"
         "    com.google.protobuf.GeneratedMessageLite<\n"
         "        $classname$, $classname$.Builder> implements\n"
         "    $extra_interfaces$\n"
@@ -197,7 +216,7 @@
   }
   printer->Indent();
 
-  GenerateParsingConstructor(printer);
+  GenerateConstructor(printer);
 
   // Nested types
   for (int i = 0; i < descriptor_->enum_type_count(); i++) {
@@ -229,13 +248,13 @@
   }
 
   // oneof
-  map<string, string> vars;
+  std::map<string, string> vars;
   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
-    vars["oneof_name"] = context_->GetOneofGeneratorInfo(
-        descriptor_->oneof_decl(i))->name;
+    const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
+    vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name;
     vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(
-        descriptor_->oneof_decl(i))->capitalized_name;
-    vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
+        oneof)->capitalized_name;
+    vars["oneof_index"] = SimpleItoa(oneof->index());
     // oneofCase_ and oneof_
     printer->Print(vars,
       "private int $oneof_name$Case_ = 0;\n"
@@ -245,8 +264,8 @@
       "public enum $oneof_capitalized_name$Case\n"
       "    implements com.google.protobuf.Internal.EnumLite {\n");
     printer->Indent();
-    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
-      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+    for (int j = 0; j < oneof->field_count(); j++) {
+      const FieldDescriptor* field = oneof->field(j);
       printer->Print(
         "$field_name$($field_number$),\n",
         "field_name",
@@ -259,15 +278,23 @@
       "cap_oneof_name",
       ToUpper(vars["oneof_name"]));
     printer->Print(vars,
-      "private int value = 0;\n"
+      "private final int value;\n"
       "private $oneof_capitalized_name$Case(int value) {\n"
       "  this.value = value;\n"
       "}\n");
     printer->Print(vars,
+      "/**\n"
+      " * @deprecated Use {@link #forNumber(int)} instead.\n"
+      " */\n"
+      "@java.lang.Deprecated\n"
       "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
+      "  return forNumber(value);\n"
+      "}\n"
+      "\n"
+      "public static $oneof_capitalized_name$Case forNumber(int value) {\n"
       "  switch (value) {\n");
-    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
-      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+    for (int j = 0; j < oneof->field_count(); j++) {
+      const FieldDescriptor* field = oneof->field(j);
       printer->Print(
         "    case $field_number$: return $field_name$;\n",
         "field_number",
@@ -277,10 +304,10 @@
     }
     printer->Print(
       "    case 0: return $cap_oneof_name$_NOT_SET;\n"
-      "    default: throw new java.lang.IllegalArgumentException(\n"
-      "      \"Value is undefined for this oneof enum.\");\n"
+      "    default: return null;\n"
       "  }\n"
       "}\n"
+      "@java.lang.Override\n"
       "public int getNumber() {\n"
       "  return this.value;\n"
       "}\n",
@@ -289,9 +316,10 @@
     printer->Print("};\n\n");
     // oneofCase()
     printer->Print(vars,
+      "@java.lang.Override\n"
       "public $oneof_capitalized_name$Case\n"
       "get$oneof_capitalized_name$Case() {\n"
-      "  return $oneof_capitalized_name$Case.valueOf(\n"
+      "  return $oneof_capitalized_name$Case.forNumber(\n"
       "      $oneof_name$Case_);\n"
       "}\n"
       "\n"
@@ -311,77 +339,81 @@
     printer->Print("\n");
   }
 
-  GenerateMessageSerializationMethods(printer);
-
-  if (HasEqualsAndHashCode(descriptor_)) {
-    GenerateEqualsAndHashCode(printer);
+  if (!EnableExperimentalRuntime(context_)) {
+    GenerateMessageSerializationMethods(printer);
   }
 
-
   GenerateParseFromMethods(printer);
   GenerateBuilder(printer);
 
   if (HasRequiredFields(descriptor_)) {
     // Memoizes whether the protocol buffer is fully initialized (has all
-    // required fields). -1 means not yet computed. 0 means false and 1 means
-    // true.
+    // required fields). 0 means false, 1 means true, and all other values
+    // mean not yet computed.
     printer->Print(
-      "private byte memoizedIsInitialized = -1;\n");
+      "private byte memoizedIsInitialized = 2;\n");
   }
 
   printer->Print(
-    "protected final Object dynamicMethod(\n"
-    "    com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n"
-    "    Object arg0, Object arg1) {\n"
-    "  switch (method) {\n"
-    "    case PARSE_PARTIAL_FROM: {\n"
-    "      return new $classname$("
-    "          (com.google.protobuf.CodedInputStream) arg0,\n"
-    "          (com.google.protobuf.ExtensionRegistryLite) arg1);\n"
-    "    }\n"
-    "    case NEW_INSTANCE: {\n"
-    "      return new $classname$(\n"
-    "          com.google.protobuf.Internal.EMPTY_CODED_INPUT_STREAM,\n"
-    "          com.google.protobuf.ExtensionRegistryLite\n"
-    "              .getEmptyRegistry());\n"
-    "    }\n",
-    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+      "@java.lang.Override\n"
+      "@java.lang.SuppressWarnings({\"unchecked\", \"fallthrough\"})\n"
+      "protected final java.lang.Object dynamicMethod(\n"
+      "    com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n"
+      "    java.lang.Object arg0, java.lang.Object arg1) {\n"
+      "  switch (method) {\n"
+      "    case NEW_MUTABLE_INSTANCE: {\n"
+      "      return new $classname$();\n"
+      "    }\n",
+      "classname", name_resolver_->GetImmutableClassName(descriptor_));
 
   printer->Indent();
   printer->Indent();
 
   printer->Print(
-    "case IS_INITIALIZED: {\n");
-  printer->Indent();
-  GenerateDynamicMethodIsInitialized(printer);
-  printer->Outdent();
-
-  printer->Print(
-    "}\n"
-    "case MAKE_IMMUTABLE: {\n");
-
-  printer->Indent();
-  GenerateDynamicMethodMakeImmutable(printer);
-  printer->Outdent();
-
-  printer->Print(
-    "}\n"
     "case NEW_BUILDER: {\n");
 
   printer->Indent();
   GenerateDynamicMethodNewBuilder(printer);
   printer->Outdent();
 
-  printer->Print(
-    "}\n"
-    "case MERGE_FROM: {\n");
+  if (!EnableExperimentalRuntimeForLite()) {
+    printer->Print(
+      "}\n"
+      "case IS_INITIALIZED: {\n");
+    printer->Indent();
+    GenerateDynamicMethodIsInitialized(printer);
+    printer->Outdent();
 
-  printer->Indent();
-  GenerateDynamicMethodMergeFrom(printer);
-  printer->Outdent();
+    printer->Print("}\n");
+
+    printer->Print(
+      "case MAKE_IMMUTABLE: {\n");
+
+    printer->Indent();
+    GenerateDynamicMethodMakeImmutable(printer);
+    printer->Outdent();
+
+    printer->Print(
+        "}\n"
+        "case VISIT: {\n");
+
+    printer->Indent();
+    GenerateDynamicMethodVisit(printer);
+    printer->Outdent();
+
+    printer->Print(
+        "}\n"
+        "case MERGE_FROM_STREAM: {\n");
+
+    printer->Indent();
+    GenerateDynamicMethodMergeFromStream(printer);
+    printer->Outdent();
+  }
+
 
   printer->Print(
     "}\n"
+    "// fall through\n"
     "case GET_DEFAULT_INSTANCE: {\n"
     "  return DEFAULT_INSTANCE;\n"
     "}\n"
@@ -390,20 +422,46 @@
     // manipulating static fields but that has exceptional cost on Android as
     // it will generate an extra class for every message. Instead, use the
     // double-check locking pattern which works just as well.
-    "  if (PARSER == null) {"
+    //
+    // The "parser" temporary mirrors the "PARSER" field to eliminate a read
+    // at the final return statement.
+    "  com.google.protobuf.Parser<$classname$> parser = PARSER;\n"
+    "  if (parser == null) {\n"
     "    synchronized ($classname$.class) {\n"
-    "      if (PARSER == null) {\n"
-    "        PARSER = new DefaultInstanceBasedParser(DEFAULT_INSTANCE);\n"
+    "      parser = PARSER;\n"
+    "      if (parser == null) {\n"
+    "        parser = new DefaultInstanceBasedParser(DEFAULT_INSTANCE);\n"
+    "        PARSER = parser;\n"
     "      }\n"
     "    }\n"
     "  }\n"
-    "  return PARSER;\n"
-    "}\n",
+    "  return parser;\n",
     "classname", name_resolver_->GetImmutableClassName(descriptor_));
 
   printer->Outdent();
-  printer->Outdent();
 
+  if (HasRequiredFields(descriptor_)) {
+    printer->Print(
+        "}\n"
+        "case GET_MEMOIZED_IS_INITIALIZED: {\n"
+        "  return memoizedIsInitialized;\n"
+        "}\n"
+        "case SET_MEMOIZED_IS_INITIALIZED: {\n"
+        "  memoizedIsInitialized = (byte) (arg0 == null ? 0 : 1);\n"
+        "  return null;\n"
+        "}\n");
+  } else {
+    printer->Print(
+        "}\n"
+        "case GET_MEMOIZED_IS_INITIALIZED: {\n"
+        "  return (byte) 1;\n"
+        "}\n"
+        "case SET_MEMOIZED_IS_INITIALIZED: {\n"
+        "  return null;\n"
+        "}\n");
+  }
+
+  printer->Outdent();
   printer->Print(
     "  }\n"
     "  throw new UnsupportedOperationException();\n"
@@ -425,14 +483,24 @@
 
   printer->Print(
     "static {\n"
-    "  DEFAULT_INSTANCE = new $classname$(\n"
-    "      com.google.protobuf.Internal\n"
-    "          .EMPTY_CODED_INPUT_STREAM,\n"
-    "      com.google.protobuf.ExtensionRegistryLite\n"
-    "          .getEmptyRegistry());\n"
+    "  // New instances are implicitly immutable so no need to make\n"
+    "  // immutable.\n"
+    "  DEFAULT_INSTANCE = new $classname$();\n"
     "}\n"
     "\n",
     "classname", descriptor_->name());
+  if (EnableExperimentalRuntimeForLite()) {
+    // Register the default instance in a map. This map will be used by
+    // experimental runtime to lookup default instance given a class instance
+    // without using Java reflection.
+    printer->Print(
+        "static {\n"
+        "  com.google.protobuf.GeneratedMessageLite.registerDefaultInstance(\n"
+        "    $classname$.class, DEFAULT_INSTANCE);\n"
+        "}\n",
+        "classname", descriptor_->name());
+  }
+
   printer->Print(
       "public static $classname$ getDefaultInstance() {\n"
       "  return DEFAULT_INSTANCE;\n"
@@ -440,28 +508,45 @@
       "\n",
       "classname", name_resolver_->GetImmutableClassName(descriptor_));
 
+  // 'of' method for Wrappers
+  if (IsWrappersProtoFile(descriptor_->file())) {
+    printer->Print(
+        "public static $classname$ of($field_type$ value) {\n"
+        "  return newBuilder().setValue(value).build();\n"
+        "}\n"
+        "\n",
+        "classname", name_resolver_->GetImmutableClassName(descriptor_),
+        "field_type", PrimitiveTypeName(GetJavaType(descriptor_->field(0))));
+  }
+
   GenerateParser(printer);
 
   // Extensions must be declared after the DEFAULT_INSTANCE is initialized
   // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve
   // the outer class's FileDescriptor.
   for (int i = 0; i < descriptor_->extension_count(); i++) {
-    ImmutableExtensionGenerator(descriptor_->extension(i), context_)
+    ImmutableExtensionLiteGenerator(descriptor_->extension(i), context_)
         .Generate(printer);
   }
 
+
   printer->Outdent();
   printer->Print("}\n\n");
 }
 
+
 // ===================================================================
 
 void ImmutableMessageLiteGenerator::
 GenerateMessageSerializationMethods(io::Printer* printer) {
-  google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
+  if (EnableExperimentalRuntimeForLite()) {
+    return;
+  }
+
+  std::unique_ptr<const FieldDescriptor * []> sorted_fields(
       SortFieldsByNumber(descriptor_));
 
-  vector<const Descriptor::ExtensionRange*> sorted_extensions;
+  std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
   for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
     sorted_extensions.push_back(descriptor_->extension_range(i));
   }
@@ -469,42 +554,41 @@
             ExtensionRangeOrdering());
 
   printer->Print(
+    "@java.lang.Override\n"
     "public void writeTo(com.google.protobuf.CodedOutputStream output)\n"
     "                    throws java.io.IOException {\n");
   printer->Indent();
   if (HasPackedFields(descriptor_)) {
     // writeTo(CodedOutputStream output) might be invoked without
     // getSerializedSize() ever being called, but we need the memoized
-    // sizes in case this message has packed fields. Rather than emit checks for
-    // each packed field, just call getSerializedSize() up front.
-    // In most cases, getSerializedSize() will have already been called anyway
-    // by one of the wrapper writeTo() methods, making this call cheap.
-    printer->Print(
-      "getSerializedSize();\n");
+    // sizes in case this message has packed fields. Rather than emit checks
+    // for each packed field, just call getSerializedSize() up front. In most
+    // cases, getSerializedSize() will have already been called anyway by one
+    // of the wrapper writeTo() methods, making this call cheap.
+    printer->Print("getSerializedSize();\n");
   }
 
   if (descriptor_->extension_range_count() > 0) {
     if (descriptor_->options().message_set_wire_format()) {
       printer->Print(
-        "com.google.protobuf.GeneratedMessageLite\n"
-        "  .ExtendableMessage<$classname$, $classname$.Builder>\n"
-        "    .ExtensionWriter extensionWriter =\n"
-        "      newMessageSetExtensionWriter();\n",
-        "classname", name_resolver_->GetImmutableClassName(descriptor_));
+          "com.google.protobuf.GeneratedMessageLite\n"
+          "  .ExtendableMessage<$classname$, $classname$.Builder>\n"
+          "    .ExtensionWriter extensionWriter =\n"
+          "      newMessageSetExtensionWriter();\n",
+          "classname", name_resolver_->GetImmutableClassName(descriptor_));
     } else {
       printer->Print(
-        "com.google.protobuf.GeneratedMessageLite\n"
-        "  .ExtendableMessage<$classname$, $classname$.Builder>\n"
-        "    .ExtensionWriter extensionWriter =\n"
-        "      newExtensionWriter();\n",
-        "classname", name_resolver_->GetImmutableClassName(descriptor_));
+          "com.google.protobuf.GeneratedMessageLite\n"
+          "  .ExtendableMessage<$classname$, $classname$.Builder>\n"
+          "    .ExtensionWriter extensionWriter =\n"
+          "      newExtensionWriter();\n",
+          "classname", name_resolver_->GetImmutableClassName(descriptor_));
     }
   }
 
   // Merge the fields and the extension ranges, both sorted by field number.
   for (int i = 0, j = 0;
-       i < descriptor_->field_count() || j < sorted_extensions.size();
-       ) {
+       i < descriptor_->field_count() || j < sorted_extensions.size();) {
     if (i == descriptor_->field_count()) {
       GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
     } else if (j == sorted_extensions.size()) {
@@ -516,21 +600,24 @@
     }
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    printer->Print(
-      "unknownFields.writeTo(output);\n");
+  if (descriptor_->options().message_set_wire_format()) {
+    printer->Print("unknownFields.writeAsMessageSetTo(output);\n");
+  } else {
+    printer->Print("unknownFields.writeTo(output);\n");
   }
 
   printer->Outdent();
   printer->Print(
-    "}\n"
-    "\n"
-    "public int getSerializedSize() {\n"
-    "  int size = memoizedSerializedSize;\n"
-    "  if (size != -1) return size;\n"
-    "\n"
-    "  size = 0;\n");
+      "}\n"
+      "\n"
+      "@java.lang.Override\n"
+      "public int getSerializedSize() {\n"
+      "  int size = memoizedSerializedSize;\n"
+      "  if (size != -1) return size;\n"
+      "\n");
   printer->Indent();
+  printer->Print(
+      "size = 0;\n");
 
   for (int i = 0; i < descriptor_->field_count(); i++) {
     field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
@@ -538,28 +625,26 @@
 
   if (descriptor_->extension_range_count() > 0) {
     if (descriptor_->options().message_set_wire_format()) {
-      printer->Print(
-        "size += extensionsSerializedSizeAsMessageSet();\n");
+      printer->Print("size += extensionsSerializedSizeAsMessageSet();\n");
     } else {
-      printer->Print(
-        "size += extensionsSerializedSize();\n");
+      printer->Print("size += extensionsSerializedSize();\n");
     }
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    printer->Print(
-      "size += unknownFields.getSerializedSize();\n");
+  if (descriptor_->options().message_set_wire_format()) {
+    printer->Print("size += unknownFields.getSerializedSizeAsMessageSet();\n");
+  } else {
+    printer->Print("size += unknownFields.getSerializedSize();\n");
   }
 
+  printer->Print(
+      "memoizedSerializedSize = size;\n"
+      "return size;\n");
+
   printer->Outdent();
   printer->Print(
-    "  memoizedSerializedSize = size;\n"
-    "  return size;\n"
     "}\n"
     "\n");
-
-  printer->Print(
-    "private static final long serialVersionUID = 0L;\n");
 }
 
 void ImmutableMessageLiteGenerator::
@@ -569,56 +654,77 @@
   //   for code size.
   printer->Print(
     "public static $classname$ parseFrom(\n"
+    "    java.nio.ByteBuffer data)\n"
+    "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, data);\n"
+    "}\n"
+    "public static $classname$ parseFrom(\n"
+    "    java.nio.ByteBuffer data,\n"
+    "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+    "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, data, extensionRegistry);\n"
+    "}\n"
+    "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.ByteString data)\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
-    "  return parser().parseFrom(data);\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, data);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.ByteString data,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
-    "  return parser().parseFrom(data, extensionRegistry);\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, data, extensionRegistry);\n"
     "}\n"
     "public static $classname$ parseFrom(byte[] data)\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
-    "  return parser().parseFrom(data);\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, data);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    byte[] data,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
-    "  return parser().parseFrom(data, extensionRegistry);\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, data, extensionRegistry);\n"
     "}\n"
     "public static $classname$ parseFrom(java.io.InputStream input)\n"
     "    throws java.io.IOException {\n"
-    "  return parser().parseFrom(input);\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, input);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    java.io.InputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
-    "  return parser().parseFrom(input, extensionRegistry);\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, input, extensionRegistry);\n"
     "}\n"
     "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
     "    throws java.io.IOException {\n"
-    "  return parser().parseDelimitedFrom(input);\n"
+    "  return parseDelimitedFrom(DEFAULT_INSTANCE, input);\n"
     "}\n"
     "public static $classname$ parseDelimitedFrom(\n"
     "    java.io.InputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
-    "  return parser().parseDelimitedFrom(input, extensionRegistry);\n"
+    "  return parseDelimitedFrom(DEFAULT_INSTANCE, input, extensionRegistry);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.CodedInputStream input)\n"
     "    throws java.io.IOException {\n"
-    "  return parser().parseFrom(input);\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, input);\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.CodedInputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
-    "  return parser().parseFrom(input, extensionRegistry);\n"
+    "  return com.google.protobuf.GeneratedMessageLite.parseFrom(\n"
+    "      DEFAULT_INSTANCE, input, extensionRegistry);\n"
     "}\n"
     "\n",
     "classname", name_resolver_->GetImmutableClassName(descriptor_));
@@ -641,10 +747,10 @@
 void ImmutableMessageLiteGenerator::GenerateBuilder(io::Printer* printer) {
   printer->Print(
     "public static Builder newBuilder() {\n"
-    "  return DEFAULT_INSTANCE.toBuilder();\n"
+    "  return (Builder) DEFAULT_INSTANCE.createBuilder();\n"
     "}\n"
     "public static Builder newBuilder($classname$ prototype) {\n"
-    "  return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n"
+    "  return (Builder) DEFAULT_INSTANCE.createBuilder(prototype);\n"
     "}\n"
     "\n",
     "classname", name_resolver_->GetImmutableClassName(descriptor_));
@@ -663,7 +769,10 @@
     return;
   }
 
-  // Don't directly compare to -1 to avoid an Android x86 JIT bug.
+  // TODO(xiaofeng): Remove this when b/64445758 is fixed. We don't need to
+  // check memoizedIsInitialized here because the caller does that already,
+  // but right now proguard proto shrinker asserts on the bytecode layout of
+  // this code so it can't be removed until proguard is updated.
   printer->Print(
     "byte isInitialized = memoizedIsInitialized;\n"
     "if (isInitialized == 1) return DEFAULT_INSTANCE;\n"
@@ -681,9 +790,6 @@
     if (field->is_required()) {
       printer->Print(
         "if (!has$name$()) {\n"
-        "  if (shouldMemoize) {\n"
-        "    memoizedIsInitialized = 0;\n"
-        "  }\n"
         "  return null;\n"
         "}\n",
         "name", info->capitalized_name);
@@ -700,9 +806,6 @@
         case FieldDescriptor::LABEL_REQUIRED:
           printer->Print(
             "if (!get$name$().isInitialized()) {\n"
-            "  if (shouldMemoize) {\n"
-            "    memoizedIsInitialized = 0;\n"
-            "  }\n"
             "  return null;\n"
             "}\n",
             "type", name_resolver_->GetImmutableClassName(
@@ -726,9 +829,6 @@
           }
           printer->Print(
             "  if (!get$name$().isInitialized()) {\n"
-            "    if (shouldMemoize) {\n"
-            "      memoizedIsInitialized = 0;\n"
-            "    }\n"
             "    return null;\n"
             "  }\n"
             "}\n",
@@ -737,11 +837,8 @@
         case FieldDescriptor::LABEL_REPEATED:
           if (IsMapEntry(field->message_type())) {
             printer->Print(
-              "for ($type$ item : get$name$().values()) {\n"
+              "for ($type$ item : get$name$Map().values()) {\n"
               "  if (!item.isInitialized()) {\n"
-              "    if (shouldMemoize) {\n"
-              "      memoizedIsInitialized = 0;\n"
-              "    }\n"
               "    return null;\n"
               "  }\n"
               "}\n",
@@ -752,9 +849,6 @@
             printer->Print(
               "for (int i = 0; i < get$name$Count(); i++) {\n"
               "  if (!get$name$(i).isInitialized()) {\n"
-              "    if (shouldMemoize) {\n"
-              "      memoizedIsInitialized = 0;\n"
-              "    }\n"
               "    return null;\n"
               "  }\n"
               "}\n",
@@ -770,17 +864,11 @@
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(
       "if (!extensionsAreInitialized()) {\n"
-      "  if (shouldMemoize) {\n"
-      "    memoizedIsInitialized = 0;\n"
-      "  }\n"
       "  return null;\n"
       "}\n");
   }
 
   printer->Print(
-    "if (shouldMemoize) memoizedIsInitialized = 1;\n");
-
-  printer->Print(
     "return DEFAULT_INSTANCE;\n"
     "\n");
 }
@@ -789,11 +877,13 @@
 
 void ImmutableMessageLiteGenerator::GenerateDynamicMethodMakeImmutable(
     io::Printer* printer) {
+
   // Output generation code for each field.
   for (int i = 0; i < descriptor_->field_count(); i++) {
     field_generators_.get(descriptor_->field(i))
         .GenerateDynamicMethodMakeImmutableCode(printer);
   }
+
   printer->Print(
     "return null;\n");
 }
@@ -808,19 +898,17 @@
 
 // ===================================================================
 
-void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom(
+void ImmutableMessageLiteGenerator::GenerateDynamicMethodVisit(
     io::Printer* printer) {
   printer->Print(
-    // Optimization:  If other is the default instance, we know none of its
-    //   fields are set so we can skip the merge.
-    "if (arg0 == $classname$.getDefaultInstance()) return this;\n"
-    "$classname$ other = ($classname$) arg0;\n",
+    "Visitor visitor = (Visitor) arg0;\n"
+    "$classname$ other = ($classname$) arg1;\n",
     "classname", name_resolver_->GetImmutableClassName(descriptor_));
 
   for (int i = 0; i < descriptor_->field_count(); i++) {
     if (!descriptor_->field(i)->containing_oneof()) {
       field_generators_.get(
-          descriptor_->field(i)).GenerateMergingCode(printer);
+          descriptor_->field(i)).GenerateVisitCode(printer);
     }
   }
 
@@ -839,7 +927,7 @@
         "field_name",
         ToUpper(field->name()));
       printer->Indent();
-      field_generators_.get(field).GenerateMergingCode(printer);
+      field_generators_.get(field).GenerateVisitCode(printer);
       printer->Print(
           "break;\n");
       printer->Outdent();
@@ -848,26 +936,52 @@
     }
     printer->Print(
       "case $cap_oneof_name$_NOT_SET: {\n"
+      "  visitor.visitOneofNotSet($oneof_name$Case_ != 0);\n"
       "  break;\n"
       "}\n",
       "cap_oneof_name",
       ToUpper(context_->GetOneofGeneratorInfo(
-          descriptor_->oneof_decl(i))->name));
+          descriptor_->oneof_decl(i))->name),
+      "oneof_name",
+      context_->GetOneofGeneratorInfo(
+          descriptor_->oneof_decl(i))->name);
     printer->Outdent();
     printer->Print(
       "}\n");
   }
 
-  // if message type has extensions
-  if (descriptor_->extension_range_count() > 0) {
+  printer->Print(
+    "if (visitor == com.google.protobuf.GeneratedMessageLite.MergeFromVisitor\n"
+    "    .INSTANCE) {\n");
+  printer->Indent();
+  for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
+    const OneofDescriptor* field = descriptor_->oneof_decl(i);
     printer->Print(
-      "this.mergeExtensionFields(other);\n");
+      "if (other.$oneof_name$Case_ != 0) {\n"
+      "  $oneof_name$Case_ = other.$oneof_name$Case_;\n"
+      "}\n",
+      "oneof_name", context_->GetOneofGeneratorInfo(field)->name);
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    printer->Print(
-      "this.mergeUnknownFields(other.unknownFields);\n");
+  if (GenerateHasBits(descriptor_)) {
+    // 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(
+        "$bit_field_name$ |= other.$bit_field_name$;\n",
+        "bit_field_name", GetBitFieldName(i));
+    }
   }
+  printer->Outdent();
+  printer->Print(
+    "}\n");
+
 
   printer->Print(
     "return this;\n");
@@ -875,249 +989,113 @@
 
 // ===================================================================
 
-namespace {
-bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) {
-  if (field->is_repeated()) {
-    return false;
-  }
-  if (SupportFieldPresence(field->file())) {
-    return true;
-  }
-  return GetJavaType(field) == JAVATYPE_MESSAGE &&
-      field->containing_oneof() == NULL;
-}
-}  // namespace
-
-void ImmutableMessageLiteGenerator::
-GenerateEqualsAndHashCode(io::Printer* printer) {
+void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFromStream(
+    io::Printer* printer) {
   printer->Print(
-    "@java.lang.Override\n"
-    "public boolean equals(final java.lang.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", name_resolver_->GetImmutableClassName(descriptor_));
-
-  printer->Print("boolean result = true;\n");
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = descriptor_->field(i);
-    const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
-    bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
-    if (check_has_bits) {
-      printer->Print(
-        "result = result && (has$name$() == other.has$name$());\n"
-        "if (has$name$()) {\n",
-        "name", info->capitalized_name);
-      printer->Indent();
-    }
-    field_generators_.get(field).GenerateEqualsCode(printer);
-    if (check_has_bits) {
-      printer->Outdent();
-      printer->Print(
-        "}\n");
-    }
-  }
-  if (PreserveUnknownFields(descriptor_)) {
-    // Always consider unknown fields for equality. This will sometimes return
-    // false for non-canonical ordering when running in LITE_RUNTIME but it's
-    // the best we can do.
-    printer->Print(
-      "result = result && unknownFields.equals(other.unknownFields);\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(
-    "if (memoizedHashCode != 0) {\n");
-  printer->Indent();
-  printer->Print(
-    "return memoizedHashCode;\n");
-  printer->Outdent();
-  printer->Print(
-    "}\n"
-    "int hash = 41;\n");
-
-  // Include the hash of the class so that two objects with different types
-  // but the same field values will probably have different hashes.
-  printer->Print("hash = (19 * hash) + $classname$.class.hashCode();\n",
-    "classname", name_resolver_->GetImmutableClassName(descriptor_));
-
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = descriptor_->field(i);
-    const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
-    bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
-    if (check_has_bits) {
-      printer->Print(
-        "if (has$name$()) {\n",
-        "name", info->capitalized_name);
-      printer->Indent();
-    }
-    field_generators_.get(field).GenerateHashCode(printer);
-    if (check_has_bits) {
-      printer->Outdent();
-      printer->Print("}\n");
-    }
-  }
-
-  printer->Print(
-    "hash = (29 * hash) + unknownFields.hashCode();\n");
-  printer->Print(
-    "memoizedHashCode = hash;\n"
-    "return hash;\n");
-  printer->Outdent();
-  printer->Print(
-    "}\n"
-    "\n");
-}
-
-// ===================================================================
-
-void ImmutableMessageLiteGenerator::
-GenerateExtensionRegistrationCode(io::Printer* printer) {
-  for (int i = 0; i < descriptor_->extension_count(); i++) {
-    ImmutableExtensionGenerator(descriptor_->extension(i), context_)
-      .GenerateRegistrationCode(printer);
-  }
-
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
-      .GenerateExtensionRegistrationCode(printer);
-  }
-}
-
-// ===================================================================
-void ImmutableMessageLiteGenerator::
-GenerateParsingConstructor(io::Printer* printer) {
-  google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
-      SortFieldsByNumber(descriptor_));
-
-  printer->Print(
-      "private $classname$(\n"
-      "    com.google.protobuf.CodedInputStream input,\n"
-      "    com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n",
-      "classname", descriptor_->name());
-  printer->Indent();
-
-  // Initialize all fields to default.
-  GenerateInitializers(printer);
-
-  // Use builder bits to track mutable repeated fields.
-  int totalBuilderBits = 0;
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const ImmutableFieldLiteGenerator& field =
-        field_generators_.get(descriptor_->field(i));
-    totalBuilderBits += field.GetNumBitsForBuilder();
-  }
-  int totalBuilderInts = (totalBuilderBits + 31) / 32;
-  for (int i = 0; i < totalBuilderInts; i++) {
-    printer->Print("int mutable_$bit_field_name$ = 0;\n",
-      "bit_field_name", GetBitFieldName(i));
-  }
-
+      "com.google.protobuf.CodedInputStream input =\n"
+      "    (com.google.protobuf.CodedInputStream) arg0;\n"
+      "com.google.protobuf.ExtensionRegistryLite extensionRegistry =\n"
+      "    (com.google.protobuf.ExtensionRegistryLite) arg1;\n"
+      "if (extensionRegistry == null) {\n"
+      "  throw new java.lang.NullPointerException();\n"
+      "}\n");
   printer->Print(
       "try {\n");
   printer->Indent();
-
-  printer->Print(
-    "boolean done = false;\n"
-    "while (!done) {\n");
-  printer->Indent();
-
-  printer->Print(
-    "int tag = input.readTag();\n"
-    "switch (tag) {\n");
-  printer->Indent();
-
-  printer->Print(
-    "case 0:\n"          // zero signals EOF / limit reached
-    "  done = true;\n"
-    "  break;\n");
-
-  if (PreserveUnknownFields(descriptor_)) {
-    if (descriptor_->extension_range_count() > 0) {
-      printer->Print(
-        "default: {\n"
-        "  if (!parseUnknownField(getDefaultInstanceForType(),\n"
-        "                         input, extensionRegistry, tag)) {\n"
-        "    done = true;\n"  // it's an endgroup tag
-        "  }\n"
-        "  break;\n"
-        "}\n");
-    } else {
-      printer->Print(
-        "default: {\n"
-        "  if (!parseUnknownField(tag, input)) {\n"
-        "    done = true;\n"  // it's an endgroup tag
-        "  }\n"
-        "  break;\n"
-        "}\n");
-    }
+  if (EnableExperimentalRuntime(context_)) {
+    printer->Print(
+        "mergeFromInternal(input, extensionRegistry);\n"
+        "return DEFAULT_INSTANCE;\n");
   } else {
     printer->Print(
-      "default: {\n"
-      "  if (!input.skipField(tag)) {\n"
-      "    done = true;\n"  // it's an endgroup tag
-      "  }\n"
-      "  break;\n"
-      "}\n");
-  }
-
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = sorted_fields[i];
-    uint32 tag = WireFormatLite::MakeTag(field->number(),
-      WireFormat::WireTypeForFieldType(field->type()));
-
-    printer->Print(
-      "case $tag$: {\n",
-      "tag", SimpleItoa(tag));
+        "boolean done = false;\n"
+        "while (!done) {\n");
     printer->Indent();
 
-    field_generators_.get(field).GenerateParsingCode(printer);
-
-    printer->Outdent();
     printer->Print(
-      "  break;\n"
-      "}\n");
+        "int tag = input.readTag();\n"
+        "switch (tag) {\n");
+    printer->Indent();
 
-    if (field->is_packable()) {
-      // To make packed = true wire compatible, we generate parsing code from a
-      // packed version of this field regardless of field->options().packed().
-      uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
-        WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
-      printer->Print(
-        "case $tag$: {\n",
-        "tag", SimpleItoa(packed_tag));
+    printer->Print(
+        "case 0:\n"  // zero signals EOF / limit reached
+        "  done = true;\n"
+        "  break;\n");
+
+    std::unique_ptr<const FieldDescriptor* []> sorted_fields(
+        SortFieldsByNumber(descriptor_));
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      const FieldDescriptor* field = sorted_fields[i];
+      uint32 tag = WireFormatLite::MakeTag(
+          field->number(), WireFormat::WireTypeForFieldType(field->type()));
+
+      printer->Print("case $tag$: {\n", "tag",
+                     SimpleItoa(static_cast<int32>(tag)));
       printer->Indent();
 
-      field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
+      field_generators_.get(field).GenerateParsingCode(printer);
 
       printer->Outdent();
       printer->Print(
         "  break;\n"
         "}\n");
-    }
-  }
 
-  printer->Outdent();
-  printer->Outdent();
-  printer->Print(
-      "  }\n"     // switch (tag)
-      "}\n");     // while (!done)
+      if (field->is_packable()) {
+        // To make packed = true wire compatible, we generate parsing code from
+        // a packed version of this field regardless of
+        // field->options().packed().
+        uint32 packed_tag = WireFormatLite::MakeTag(
+            field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+        printer->Print("case $tag$: {\n", "tag",
+                       SimpleItoa(static_cast<int32>(packed_tag)));
+        printer->Indent();
+
+        field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
+
+        printer->Outdent();
+        printer->Print(
+            "  break;\n"
+            "}\n");
+      }
+    }
+
+    if (descriptor_->extension_range_count() > 0) {
+      if (descriptor_->options().message_set_wire_format()) {
+        printer->Print(
+            "default: {\n"
+            "  if (!parseUnknownFieldAsMessageSet(\n"
+            "      getDefaultInstanceForType(), input, extensionRegistry,\n"
+            "      tag)) {\n"
+            "    done = true;\n"  // it's an endgroup tag
+            "  }\n"
+            "  break;\n"
+            "}\n");
+      } else {
+        printer->Print(
+            "default: {\n"
+            "  if (!parseUnknownField(getDefaultInstanceForType(),\n"
+            "      input, extensionRegistry, tag)) {\n"
+            "    done = true;\n"  // it's an endgroup tag
+            "  }\n"
+            "  break;\n"
+            "}\n");
+      }
+    } else {
+      printer->Print(
+          "default: {\n"
+          "  if (!parseUnknownField(tag, input)) {\n"
+          "    done = true;\n"  // it's an endgroup tag
+          "  }\n"
+          "  break;\n"
+          "}\n");
+    }
+
+    printer->Outdent();
+    printer->Outdent();
+    printer->Print(
+        "  }\n"  // switch (tag)
+        "}\n");  // while (!done)
+  }
 
   printer->Outdent();
   printer->Print(
@@ -1130,19 +1108,39 @@
       "} finally {\n");
   printer->Indent();
 
-  // Make repeated field list immutable.
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = sorted_fields[i];
-    field_generators_.get(field).GenerateParsingDoneCode(printer);
+  printer->Outdent();
+  printer->Print(
+      "}\n");     // finally
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::
+GenerateExtensionRegistrationCode(io::Printer* printer) {
+  for (int i = 0; i < descriptor_->extension_count(); i++) {
+    ImmutableExtensionLiteGenerator(descriptor_->extension(i), context_)
+      .GenerateRegistrationCode(printer);
   }
 
+  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+    ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
+      .GenerateExtensionRegistrationCode(printer);
+  }
+}
+
+// ===================================================================
+void ImmutableMessageLiteGenerator::
+GenerateConstructor(io::Printer* printer) {
   printer->Print(
-      "doneParsing();\n");
+      "private $classname$() {\n",
+      "classname", descriptor_->name());
+  printer->Indent();
+
+  // Initialize all fields to default.
+  GenerateInitializers(printer);
 
   printer->Outdent();
-  printer->Outdent();
   printer->Print(
-      "  }\n"     // finally
       "}\n");
 }
 
@@ -1167,7 +1165,6 @@
   }
 }
 
-
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_message_lite.h b/src/google/protobuf/compiler/java/java_message_lite.h
index 2bd3cdd..1e319c6 100644
--- a/src/google/protobuf/compiler/java/java_message_lite.h
+++ b/src/google/protobuf/compiler/java/java_message_lite.h
@@ -47,14 +47,14 @@
 
 class ImmutableMessageLiteGenerator : public MessageGenerator {
  public:
-  explicit ImmutableMessageLiteGenerator(const Descriptor* descriptor,
-                                     Context* context);
+  ImmutableMessageLiteGenerator(const Descriptor* descriptor, Context* context);
   virtual ~ImmutableMessageLiteGenerator();
 
   virtual void Generate(io::Printer* printer);
   virtual void GenerateInterface(io::Printer* printer);
   virtual void GenerateExtensionRegistrationCode(io::Printer* printer);
-  virtual void GenerateStaticVariables(io::Printer* printer);
+  virtual void GenerateStaticVariables(
+      io::Printer* printer, int* bytecode_estimate);
   virtual int GenerateStaticVariableInitializers(io::Printer* printer);
 
  private:
@@ -69,12 +69,13 @@
   void GenerateBuilder(io::Printer* printer);
   void GenerateDynamicMethodIsInitialized(io::Printer* printer);
   void GenerateDynamicMethodMakeImmutable(io::Printer* printer);
-  void GenerateDynamicMethodMergeFrom(io::Printer* printer);
+  void GenerateDynamicMethodVisit(io::Printer* printer);
+  void GenerateDynamicMethodMergeFromStream(io::Printer* printer);
   void GenerateDynamicMethodNewBuilder(io::Printer* printer);
   void GenerateInitializers(io::Printer* printer);
   void GenerateEqualsAndHashCode(io::Printer* printer);
   void GenerateParser(io::Printer* printer);
-  void GenerateParsingConstructor(io::Printer* printer);
+  void GenerateConstructor(io::Printer* printer);
 
   Context* context_;
   ClassNameResolver* name_resolver_;
diff --git a/src/google/protobuf/compiler/java/java_name_resolver.cc b/src/google/protobuf/compiler/java/java_name_resolver.cc
index 0c363f9..1673b4e 100644
--- a/src/google/protobuf/compiler/java/java_name_resolver.cc
+++ b/src/google/protobuf/compiler/java/java_name_resolver.cc
@@ -33,6 +33,7 @@
 #include <map>
 #include <string>
 
+
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/stubs/substitute.h>
 
@@ -259,6 +260,13 @@
       descriptor->file(), true);
 }
 
+string ClassNameResolver::GetJavaImmutableClassName(
+    const EnumDescriptor* descriptor) {
+  return GetJavaClassFullName(
+      ClassNameWithoutPackage(descriptor, true),
+      descriptor->file(), true);
+}
+
 
 }  // namespace java
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/java/java_name_resolver.h b/src/google/protobuf/compiler/java/java_name_resolver.h
index ab60b0a..28b049d 100644
--- a/src/google/protobuf/compiler/java/java_name_resolver.h
+++ b/src/google/protobuf/compiler/java/java_name_resolver.h
@@ -98,6 +98,7 @@
   // For example:
   //   com.package.OuterClass$OuterMessage$InnerMessage
   string GetJavaImmutableClassName(const Descriptor* descriptor);
+  string GetJavaImmutableClassName(const EnumDescriptor* descriptor);
  private:
   // Get the full name of a Java class by prepending the Java package name
   // or outer class name.
@@ -111,7 +112,7 @@
       const FileDescriptor* file,
       bool immutable);
   // Caches the result to provide better performance.
-  map<const FileDescriptor*, string> file_immutable_outer_class_names_;
+  std::map<const FileDescriptor*, string> file_immutable_outer_class_names_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ClassNameResolver);
 };
diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.h b/src/google/protobuf/compiler/java/java_options.h
similarity index 61%
copy from src/google/protobuf/compiler/javanano/javanano_extension.h
copy to src/google/protobuf/compiler/java/java_options.h
index 4843e29..e4e7d5e 100644
--- a/src/google/protobuf/compiler/javanano/javanano_extension.h
+++ b/src/google/protobuf/compiler/java/java_options.h
@@ -1,6 +1,6 @@
 // Protocol Buffers - Google's data interchange format
 // Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
+// https://developers.google.com/protocol-buffers/
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -28,47 +28,46 @@
 // (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: bduff@google.com (Brian Duff)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_OPTIONS_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_OPTIONS_H__
 
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
-#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/javanano/javanano_params.h>
-#include <google/protobuf/descriptor.pb.h>
-
+#include <string>
 
 namespace google {
 namespace protobuf {
-  namespace io {
-    class Printer;             // printer.h
-  }
-}
-
-namespace protobuf {
 namespace compiler {
-namespace javanano {
+namespace java {
 
-class ExtensionGenerator {
- public:
-  explicit ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params);
-  ~ExtensionGenerator();
+// Generator options
+struct Options {
+  Options()
+      : generate_immutable_code(false),
+        generate_mutable_code(false),
+        generate_shared_code(false),
+        enforce_lite(false),
+        annotate_code(false) {
+  }
 
-  void Generate(io::Printer* printer) const;
-
- private:
-  const Params& params_;
-  const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
+  bool generate_immutable_code;
+  bool generate_mutable_code;
+  bool generate_shared_code;
+  // When set, the protoc will generate the current files and all the transitive
+  // dependencies as lite runtime.
+  bool enforce_lite;
+  // If true, we should build .meta files and emit @Generated annotations into
+  // generated code.
+  bool annotate_code;
+  // Name of a file where we will write a list of generated .meta file names,
+  // one per line.
+  std::string annotation_list_file;
+  // Name of a file where we will write a list of generated file names, one
+  // per line.
+  std::string output_list_file;
 };
 
-}  // namespace javanano
+}  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
-}  // namespace google
 
-#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_OPTIONS_H__
diff --git a/src/google/protobuf/compiler/java/java_plugin_unittest.cc b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
index fe52762..87f687d 100644
--- a/src/google/protobuf/compiler/java/java_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
@@ -35,18 +35,16 @@
 //   worth.
 
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 
 #include <google/protobuf/compiler/java/java_generator.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/io/printer.h>
 
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
-#include <google/protobuf/testing/file.h>
 
 namespace google {
 namespace protobuf {
@@ -75,7 +73,7 @@
 
   void TryInsert(const string& filename, const string& insertion_point,
                  GeneratorContext* context) const {
-    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+    std::unique_ptr<io::ZeroCopyOutputStream> output(
         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 178bbe1..71ee099 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -61,7 +61,7 @@
                            int builderBitIndex,
                            const FieldGeneratorInfo* info,
                            ClassNameResolver* name_resolver,
-                           map<string, string>* variables) {
+                           std::map<string, string>* variables) {
   SetCommonFieldVariables(descriptor, info, variables);
 
   (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
@@ -75,12 +75,8 @@
       "" : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
   (*variables)["capitalized_type"] =
       GetCapitalizedType(descriptor, /* immutable = */ true);
-  if (descriptor->is_packed()) {
-    (*variables)["tag"] = SimpleItoa(WireFormatLite::MakeTag(
-        descriptor->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
-  } else {
-    (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
-  }
+  (*variables)["tag"] =
+      SimpleItoa(static_cast<int32>(WireFormat::MakeTag(descriptor)));
   (*variables)["tag_size"] = SimpleItoa(
       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   if (IsReferenceType(GetJavaType(descriptor))) {
@@ -99,8 +95,7 @@
   if (fixed_size != -1) {
     (*variables)["fixed_size"] = SimpleItoa(fixed_size);
   }
-  (*variables)["on_changed"] =
-      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+  (*variables)["on_changed"] = "onChanged();";
 
   if (SupportFieldPresence(descriptor->file())) {
     // For singular messages and builders, one bit is used for the hasField bit.
@@ -195,16 +190,18 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  return $name$_;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutablePrimitiveFieldGenerator::
@@ -215,31 +212,35 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_builder$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  return $name$_;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n"
     "$null_check$"
     "  $set_has_field_bit_builder$\n"
     "  $name$_ = value;\n"
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  $clear_has_field_bit_builder$\n");
+  printer->Annotate("{", "}", descriptor_);
   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
@@ -446,19 +447,21 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $has_oneof_case_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "    return ($boxed_type$) $oneof_name$_;\n"
     "  }\n"
     "  return $default$;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 
@@ -467,33 +470,36 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $has_oneof_case_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "    return ($boxed_type$) $oneof_name$_;\n"
     "  }\n"
     "  return $default$;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n"
     "$null_check$"
     "  $set_oneof_case_message$;\n"
     "  $oneof_name$_ = value;\n"
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "    $clear_oneof_case_message$;\n"
     "    $oneof_name$_ = null;\n"
@@ -501,6 +507,7 @@
     "  }\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutablePrimitiveOneofFieldGenerator::
@@ -528,8 +535,17 @@
 GenerateSerializationCode(io::Printer* printer) const {
   printer->Print(variables_,
     "if ($has_oneof_case_message$) {\n"
-    "  output.write$capitalized_type$(\n"
-    "      $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"
+    "  output.write$capitalized_type$(\n");
+  // $type$ and $boxed_type$ is the same for bytes fields so we don't need to
+  // do redundant casts.
+  if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
+    printer->Print(variables_,
+      "      $number$, ($type$) $oneof_name$_);\n");
+  } else {
+    printer->Print(variables_,
+      "      $number$, ($type$)(($boxed_type$) $oneof_name$_));\n");
+  }
+  printer->Print(
     "}\n");
 }
 
@@ -538,8 +554,17 @@
   printer->Print(variables_,
     "if ($has_oneof_case_message$) {\n"
     "  size += com.google.protobuf.CodedOutputStream\n"
-    "    .compute$capitalized_type$Size(\n"
-    "        $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"
+    "    .compute$capitalized_type$Size(\n");
+  // $type$ and $boxed_type$ is the same for bytes fields so we don't need to
+  // do redundant casts.
+  if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
+    printer->Print(variables_,
+      "        $number$, ($type$) $oneof_name$_);\n");
+  } else {
+    printer->Print(variables_,
+      "        $number$, ($type$)(($boxed_type$) $oneof_name$_));\n");
+  }
+  printer->Print(
     "}\n");
 }
 
@@ -591,22 +616,24 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public java.util.List<$boxed_type$>\n"
-    "    get$capitalized_name$List() {\n"
+    "    ${$get$capitalized_name$List$}$() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
-  if (descriptor_->is_packed() &&
-      HasGeneratedMethods(descriptor_->containing_type())) {
+  if (descriptor_->is_packed()) {
     printer->Print(variables_,
       "private int $name$MemoizedSerializedSize = -1;\n");
   }
@@ -641,22 +668,25 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public java.util.List<$boxed_type$>\n"
-    "    get$capitalized_name$List() {\n"
+    "    ${$get$capitalized_name$List$}$() {\n"
     "  return java.util.Collections.unmodifiableList($name$_);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, $type$ value) {\n"
     "$null_check$"
     "  ensure$capitalized_name$IsMutable();\n"
@@ -664,18 +694,20 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value) {\n"
     "$null_check$"
     "  ensure$capitalized_name$IsMutable();\n"
     "  $name$_.add(value);\n"
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
     "    java.lang.Iterable<? extends $boxed_type$> values) {\n"
     "  ensure$capitalized_name$IsMutable();\n"
     "  com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
@@ -683,14 +715,16 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\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->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedImmutablePrimitiveFieldGenerator::
@@ -783,8 +817,8 @@
     // That makes it safe to rely on the memoized size here.
     printer->Print(variables_,
       "if (get$capitalized_name$List().size() > 0) {\n"
-      "  output.writeRawVarint32($tag$);\n"
-      "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+      "  output.writeUInt32NoTag($tag$);\n"
+      "  output.writeUInt32NoTag($name$MemoizedSerializedSize);\n"
       "}\n"
       "for (int i = 0; i < $name$_.size(); i++) {\n"
       "  output.write$capitalized_type$NoTag($name$_.get(i));\n"
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.h b/src/google/protobuf/compiler/java/java_primitive_field.h
index d0cd12d..7ac9bbf 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.h
+++ b/src/google/protobuf/compiler/java/java_primitive_field.h
@@ -82,7 +82,7 @@
 
  protected:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   const int messageBitIndex_;
   const int builderBitIndex_;
   Context* context_;
@@ -143,7 +143,7 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   const int messageBitIndex_;
   const int builderBitIndex_;
   Context* context_;
diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
index 5a7bf82..d2ebc56 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
@@ -61,24 +61,24 @@
                            int builderBitIndex,
                            const FieldGeneratorInfo* info,
                            ClassNameResolver* name_resolver,
-                           map<string, string>* variables) {
+                           std::map<string, string>* variables) {
   SetCommonFieldVariables(descriptor, info, variables);
-
-  (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
-  (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
+  JavaType javaType = GetJavaType(descriptor);
+  (*variables)["type"] = PrimitiveTypeName(javaType);
+  (*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType);
   (*variables)["field_type"] = (*variables)["type"];
   (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
-  (*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ?
-      "" : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
   (*variables)["capitalized_type"] =
       GetCapitalizedType(descriptor, /* immutable = */ true);
-  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+  (*variables)["tag"] =
+      SimpleItoa(static_cast<int32>(WireFormat::MakeTag(descriptor)));
   (*variables)["tag_size"] = SimpleItoa(
       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+  (*variables)["required"] = descriptor->is_required() ? "true" : "false";
 
-  string capitalized_type = UnderscoresToCamelCase(PrimitiveTypeName(
-        GetJavaType(descriptor)), true /* cap_next_letter */);
-  switch (GetJavaType(descriptor)) {
+  string capitalized_type = UnderscoresToCamelCase(PrimitiveTypeName(javaType),
+                                                   true /* cap_next_letter */);
+  switch (javaType) {
     case JAVATYPE_INT:
     case JAVATYPE_LONG:
     case JAVATYPE_FLOAT:
@@ -86,9 +86,6 @@
     case JAVATYPE_BOOLEAN:
       (*variables)["field_list_type"] =
           "com.google.protobuf.Internal." + capitalized_type + "List";
-      (*variables)["new_list"] = "new" + capitalized_type + "List";
-      (*variables)["new_list_with_capacity"] =
-          "new" + capitalized_type + "ListWithCapacity";
       (*variables)["empty_list"] = "empty" + capitalized_type + "List()";
       (*variables)["make_name_unmodifiable"] =
           (*variables)["name"] + "_.makeImmutable()";
@@ -98,22 +95,29 @@
           (*variables)["name"] + "_.add" + capitalized_type;
       (*variables)["repeated_set"] =
           (*variables)["name"] + "_.set" + capitalized_type;
+      (*variables)["visit_type"] = capitalized_type;
+      (*variables)["visit_type_list"] = "visit" + capitalized_type + "List";
       break;
     default:
       (*variables)["field_list_type"] =
           "com.google.protobuf.Internal.ProtobufList<" +
           (*variables)["boxed_type"] + ">";
-      (*variables)["new_list"] = "newProtobufList";
-      (*variables)["new_list_with_capacity"] = "newProtobufListWithCapacity";
       (*variables)["empty_list"] = "emptyProtobufList()";
       (*variables)["make_name_unmodifiable"] =
           (*variables)["name"] + "_.makeImmutable()";
       (*variables)["repeated_get"] = (*variables)["name"] + "_.get";
       (*variables)["repeated_add"] = (*variables)["name"] + "_.add";
       (*variables)["repeated_set"] = (*variables)["name"] + "_.set";
+      (*variables)["visit_type"] = "ByteString";
+      (*variables)["visit_type_list"] = "visitList";
   }
 
-  if (IsReferenceType(GetJavaType(descriptor))) {
+  if (javaType == JAVATYPE_BYTES) {
+    (*variables)["bytes_default"] =
+        ToUpper((*variables)["name"]) + "_DEFAULT_VALUE";
+  }
+
+  if (IsReferenceType(javaType)) {
     (*variables)["null_check"] =
         "  if (value == null) {\n"
         "    throw new NullPointerException();\n"
@@ -129,8 +133,6 @@
   if (fixed_size != -1) {
     (*variables)["fixed_size"] = SimpleItoa(fixed_size);
   }
-  (*variables)["on_changed"] =
-      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
 
   if (SupportFieldPresence(descriptor->file())) {
     // For singular messages and builders, one bit is used for the hasField bit.
@@ -207,22 +209,33 @@
 
 void ImmutablePrimitiveFieldLiteGenerator::
 GenerateMembers(io::Printer* printer) const {
+  if (IsByteStringWithCustomDefaultValue(descriptor_)) {
+    // allocate this once statically since we know ByteStrings are immutable
+    // values that can be reused.
+    printer->Print(
+        variables_,
+        "private static final $field_type$ $bytes_default$ = $default$;\n");
+  }
   printer->Print(variables_,
     "private $field_type$ $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  return $name$_;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
@@ -255,32 +268,38 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return instance.has$capitalized_name$();\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  return instance.get$capitalized_name$();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutablePrimitiveFieldLiteGenerator::
@@ -288,9 +307,14 @@
   // noop for primitives
 }
 
+
 void ImmutablePrimitiveFieldLiteGenerator::
 GenerateInitializationCode(io::Printer* printer) const {
-  printer->Print(variables_, "$name$_ = $default$;\n");
+  if (IsByteStringWithCustomDefaultValue(descriptor_)) {
+    printer->Print(variables_, "$name$_ = $bytes_default$;\n");
+  } else if (!IsDefaultValueJavaDefault(descriptor_)) {
+    printer->Print(variables_, "$name$_ = $default$;\n");
+  }
 }
 
 void ImmutablePrimitiveFieldLiteGenerator::
@@ -299,17 +323,16 @@
 }
 
 void ImmutablePrimitiveFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
+GenerateVisitCode(io::Printer* printer) const {
   if (SupportFieldPresence(descriptor_->file())) {
     printer->Print(variables_,
-      "if (other.has$capitalized_name$()) {\n"
-      "  set$capitalized_name$(other.get$capitalized_name$());\n"
-      "}\n");
+      "$name$_ = visitor.visit$visit_type$(\n"
+      "    has$capitalized_name$(), $name$_,\n"
+      "    other.has$capitalized_name$(), other.$name$_);\n");
   } else {
     printer->Print(variables_,
-      "if (other.get$capitalized_name$() != $default$) {\n"
-      "  set$capitalized_name$(other.get$capitalized_name$());\n"
-      "}\n");
+      "$name$_ = visitor.visit$visit_type$($name$_ != $default$, $name$_,\n"
+      "    other.$name$_ != $default$, other.$name$_);\n");
   }
 }
 
@@ -469,19 +492,23 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $has_oneof_case_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "    return ($boxed_type$) $oneof_name$_;\n"
     "  }\n"
     "  return $default$;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
@@ -507,32 +534,38 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return instance.has$capitalized_name$();\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  return instance.get$capitalized_name$();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutablePrimitiveOneofFieldLiteGenerator::
@@ -541,9 +574,10 @@
 }
 
 void ImmutablePrimitiveOneofFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
+GenerateVisitCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "set$capitalized_name$(other.get$capitalized_name$());\n");
+      "$oneof_name$_ = visitor.visitOneof$visit_type$(\n"
+      "    $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n");
 }
 
 void ImmutablePrimitiveOneofFieldLiteGenerator::
@@ -619,23 +653,29 @@
   PrintExtraFieldInfo(variables_, printer);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
+    "@java.lang.Override\n"
     "$deprecation$public java.util.List<$boxed_type$>\n"
-    "    get$capitalized_name$List() {\n"
+    "    ${$get$capitalized_name$List$}$() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return $repeated_get$(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
-  if (descriptor_->options().packed() &&
-      HasGeneratedMethods(descriptor_->containing_type())) {
+  if (descriptor_->is_packed() &&
+      context_->HasGeneratedMethods(descriptor_->containing_type())) {
     printer->Print(variables_,
       "private int $name$MemoizedSerializedSize = -1;\n");
   }
@@ -643,7 +683,8 @@
   printer->Print(variables_,
     "private void ensure$capitalized_name$IsMutable() {\n"
     "  if (!$is_mutable$) {\n"
-    "    $name$_ = $new_list$($name$_);\n"
+    "    $name$_ =\n"
+    "        com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
     "   }\n"
     "}\n");
 
@@ -681,51 +722,61 @@
 GenerateBuilderMembers(io::Printer* printer) const {
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
+    "@java.lang.Override\n"
     "$deprecation$public java.util.List<$boxed_type$>\n"
-    "    get$capitalized_name$List() {\n"
+    "    ${$get$capitalized_name$List$}$() {\n"
     "  return java.util.Collections.unmodifiableList(\n"
     "      instance.get$capitalized_name$List());\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return instance.get$capitalized_name$Count();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return instance.get$capitalized_name$(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, $type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(index, value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.add$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
     "    java.lang.Iterable<? extends $boxed_type$> values) {\n"
     "  copyOnWrite();\n"
     "  instance.addAll$capitalized_name$(values);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedImmutablePrimitiveFieldLiteGenerator::
@@ -733,6 +784,7 @@
   // noop for primitives
 }
 
+
 void RepeatedImmutablePrimitiveFieldLiteGenerator::
 GenerateInitializationCode(io::Printer* printer) const {
   printer->Print(variables_, "$name$_ = $empty_list$;\n");
@@ -744,22 +796,9 @@
 }
 
 void RepeatedImmutablePrimitiveFieldLiteGenerator::
-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.
+GenerateVisitCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (!other.$name$_.isEmpty()) {\n"
-    "  if ($name$_.isEmpty()) {\n"
-    "    $name$_ = other.$name$_;\n"
-    "  } else {\n"
-    "    ensure$capitalized_name$IsMutable();\n"
-    "    $name$_.addAll(other.$name$_);\n"
-    "  }\n"
-    "  $on_changed$\n"
-    "}\n");
+      "$name$_= visitor.$visit_type_list$($name$_, other.$name$_);\n");
 }
 
 void RepeatedImmutablePrimitiveFieldLiteGenerator::
@@ -780,7 +819,8 @@
   // TODO(dweis): Scan the input buffer to count and ensure capacity.
   printer->Print(variables_,
     "if (!$is_mutable$) {\n"
-    "  $name$_ = $new_list$();\n"
+    "  $name$_ =\n"
+    "      com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
     "}\n"
     "$repeated_add$(input.read$capitalized_type$());\n");
 }
@@ -797,10 +837,13 @@
     // TODO(dweis): Scan the input buffer to count, then initialize
     // appropriately.
     printer->Print(variables_,
-      "  $name$_ = $new_list$();\n");
+      "  $name$_ =\n"
+      "      com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n");
   } else {
     printer->Print(variables_,
-      "  $name$_ = $new_list_with_capacity$(length/$fixed_size$);\n");
+      "  final int currentSize = $name$_.size();\n"
+      "  $name$_ = $name$_.mutableCopyWithCapacity(\n"
+      "      currentSize + (length/$fixed_size$));\n");
   }
 
   // TODO(dweis): Scan the input buffer to count and ensure capacity.
@@ -822,14 +865,14 @@
 
 void RepeatedImmutablePrimitiveFieldLiteGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
-  if (descriptor_->options().packed()) {
+  if (descriptor_->is_packed()) {
     // We invoke getSerializedSize in writeTo for messages that have packed
     // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
     // That makes it safe to rely on the memoized size here.
     printer->Print(variables_,
       "if (get$capitalized_name$List().size() > 0) {\n"
-      "  output.writeRawVarint32($tag$);\n"
-      "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+      "  output.writeUInt32NoTag($tag$);\n"
+      "  output.writeUInt32NoTag($name$MemoizedSerializedSize);\n"
       "}\n"
       "for (int i = 0; i < $name$_.size(); i++) {\n"
       "  output.write$capitalized_type$NoTag($repeated_get$(i));\n"
@@ -863,7 +906,7 @@
   printer->Print(
       "size += dataSize;\n");
 
-  if (descriptor_->options().packed()) {
+  if (descriptor_->is_packed()) {
     printer->Print(variables_,
       "if (!get$capitalized_name$List().isEmpty()) {\n"
       "  size += $tag_size$;\n"
@@ -876,7 +919,7 @@
   }
 
   // cache the data size for packed fields.
-  if (descriptor_->options().packed()) {
+  if (descriptor_->is_packed()) {
     printer->Print(variables_,
       "$name$MemoizedSerializedSize = dataSize;\n");
   }
diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.h b/src/google/protobuf/compiler/java/java_primitive_field_lite.h
index ad603c2..93416f0 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.h
@@ -69,7 +69,7 @@
   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 GenerateVisitCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
@@ -80,11 +80,12 @@
   void GenerateEqualsCode(io::Printer* printer) const;
   void GenerateHashCode(io::Printer* printer) const;
 
+
   string GetBoxedType() const;
 
  protected:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   const int messageBitIndex_;
   const int builderBitIndex_;
   Context* context_;
@@ -105,11 +106,12 @@
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
 
+
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldLiteGenerator);
 };
@@ -130,7 +132,7 @@
   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 GenerateVisitCode(io::Printer* printer) const;
   void GenerateBuildingCode(io::Printer* printer) const;
   void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
@@ -142,11 +144,12 @@
   void GenerateEqualsCode(io::Printer* printer) const;
   void GenerateHashCode(io::Printer* printer) const;
 
+
   string GetBoxedType() const;
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   const int messageBitIndex_;
   const int builderBitIndex_;
   Context* context_;
diff --git a/src/google/protobuf/compiler/java/java_service.cc b/src/google/protobuf/compiler/java/java_service.cc
index 11bfc12..988e194 100644
--- a/src/google/protobuf/compiler/java/java_service.cc
+++ b/src/google/protobuf/compiler/java/java_service.cc
@@ -60,9 +60,10 @@
 ImmutableServiceGenerator::~ImmutableServiceGenerator() {}
 
 void ImmutableServiceGenerator::Generate(io::Printer* printer) {
-  bool is_own_file =
-    MultipleJavaFiles(descriptor_->file(), /* immutable = */ true);
+  bool is_own_file = IsOwnFile(descriptor_, /* immutable = */ true);
   WriteServiceDocComment(printer, descriptor_);
+  MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
+                                /* immutable = */ true);
   printer->Print(
     "public $static$ abstract class $classname$\n"
     "    implements com.google.protobuf.Service {\n",
@@ -183,6 +184,10 @@
   }
 }
 
+string ImmutableServiceGenerator::GetOutput(const MethodDescriptor* method) {
+  return name_resolver_->GetImmutableClassName(method->output_type());
+}
+
 void ImmutableServiceGenerator::GenerateCallMethod(io::Printer* printer) {
   printer->Print(
     "\n"
@@ -203,13 +208,12 @@
 
   for (int i = 0; i < descriptor_->method_count(); i++) {
     const MethodDescriptor* method = descriptor_->method(i);
-    map<string, string> vars;
+    std::map<string, string> vars;
     vars["index"] = SimpleItoa(i);
     vars["method"] = UnderscoresToCamelCase(method);
     vars["input"] = name_resolver_->GetImmutableClassName(
         method->input_type());
-    vars["output"] = name_resolver_->GetImmutableClassName(
-        method->output_type());
+    vars["output"] = GetOutput(method);
     printer->Print(vars,
       "case $index$:\n"
       "  this.$method$(controller, ($input$)request,\n"
@@ -251,13 +255,12 @@
 
   for (int i = 0; i < descriptor_->method_count(); i++) {
     const MethodDescriptor* method = descriptor_->method(i);
-    map<string, string> vars;
+    std::map<string, string> vars;
     vars["index"] = SimpleItoa(i);
     vars["method"] = UnderscoresToCamelCase(method);
     vars["input"] = name_resolver_->GetImmutableClassName(
         method->input_type());
-    vars["output"] = name_resolver_->GetImmutableClassName(
-        method->output_type());
+    vars["output"] = GetOutput(method);
     printer->Print(vars,
       "case $index$:\n"
       "  return impl.$method$(controller, ($input$)request);\n");
@@ -298,7 +301,7 @@
 
   for (int i = 0; i < descriptor_->method_count(); i++) {
     const MethodDescriptor* method = descriptor_->method(i);
-    map<string, string> vars;
+    std::map<string, string> vars;
     vars["index"] = SimpleItoa(i);
     vars["type"] = name_resolver_->GetImmutableClassName(
       (which == REQUEST) ? method->input_type() : method->output_type());
@@ -350,10 +353,9 @@
     printer->Print(" {\n");
     printer->Indent();
 
-    map<string, string> vars;
+    std::map<string, string> vars;
     vars["index"] = SimpleItoa(i);
-    vars["output"] = name_resolver_->GetImmutableClassName(
-        method->output_type());
+    vars["output"] = GetOutput(method);
     printer->Print(vars,
       "channel.callMethod(\n"
       "  getDescriptor().getMethods().get($index$),\n"
@@ -415,10 +417,9 @@
     printer->Print(" {\n");
     printer->Indent();
 
-    map<string, string> vars;
+    std::map<string, string> vars;
     vars["index"] = SimpleItoa(i);
-    vars["output"] = name_resolver_->GetImmutableClassName(
-        method->output_type());
+    vars["output"] = GetOutput(method);
     printer->Print(vars,
       "return ($output$) channel.callBlockingMethod(\n"
       "  getDescriptor().getMethods().get($index$),\n"
@@ -439,10 +440,10 @@
 void ImmutableServiceGenerator::GenerateMethodSignature(io::Printer* printer,
                                                const MethodDescriptor* method,
                                                IsAbstract is_abstract) {
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["name"] = UnderscoresToCamelCase(method);
   vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
-  vars["output"] = name_resolver_->GetImmutableClassName(method->output_type());
+  vars["output"] = GetOutput(method);
   vars["abstract"] = (is_abstract == IS_ABSTRACT) ? "abstract" : "";
   printer->Print(vars,
     "public $abstract$ void $name$(\n"
@@ -454,10 +455,10 @@
 void ImmutableServiceGenerator::GenerateBlockingMethodSignature(
     io::Printer* printer,
     const MethodDescriptor* method) {
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["method"] = UnderscoresToCamelCase(method);
   vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
-  vars["output"] = name_resolver_->GetImmutableClassName(method->output_type());
+  vars["output"] = GetOutput(method);
   printer->Print(vars,
     "\n"
     "public $output$ $method$(\n"
diff --git a/src/google/protobuf/compiler/java/java_service.h b/src/google/protobuf/compiler/java/java_service.h
index 6707e82..12b3f94 100644
--- a/src/google/protobuf/compiler/java/java_service.h
+++ b/src/google/protobuf/compiler/java/java_service.h
@@ -74,8 +74,8 @@
 
 class ImmutableServiceGenerator : public ServiceGenerator {
  public:
-  explicit ImmutableServiceGenerator(const ServiceDescriptor* descriptor,
-                                     Context* context);
+  ImmutableServiceGenerator(const ServiceDescriptor* descriptor,
+                            Context* context);
   virtual ~ImmutableServiceGenerator();
 
   virtual void Generate(io::Printer* printer);
@@ -122,6 +122,9 @@
   void GenerateBlockingMethodSignature(io::Printer* printer,
                                        const MethodDescriptor* method);
 
+  // Return the output type of the method.
+  string GetOutput(const MethodDescriptor* method);
+
   Context* context_;
   ClassNameResolver* name_resolver_;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableServiceGenerator);
diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
index 7017736..0cec20b 100644
--- a/src/google/protobuf/compiler/java/java_shared_code_generator.cc
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
@@ -33,16 +33,13 @@
 #include <google/protobuf/compiler/java/java_shared_code_generator.h>
 
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
 #include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/stubs/strutil.h>
 
@@ -51,43 +48,53 @@
 namespace compiler {
 namespace java {
 
-SharedCodeGenerator::SharedCodeGenerator(const FileDescriptor* file)
-  : name_resolver_(new ClassNameResolver), file_(file) {
-}
+SharedCodeGenerator::SharedCodeGenerator(const FileDescriptor* file,
+                                         const Options& options)
+    : name_resolver_(new ClassNameResolver), file_(file), options_(options) {}
 
 SharedCodeGenerator::~SharedCodeGenerator() {
 }
 
 void SharedCodeGenerator::Generate(GeneratorContext* context,
-                                   vector<string>* file_list) {
+                                   std::vector<string>* file_list,
+                                   std::vector<string>* annotation_file_list) {
   string java_package = FileJavaPackage(file_);
   string package_dir = JavaPackageToDir(java_package);
 
-  if (HasDescriptorMethods(file_)) {
+  if (HasDescriptorMethods(file_, options_.enforce_lite)) {
     // Generate descriptors.
     string classname = name_resolver_->GetDescriptorClassName(file_);
     string filename = package_dir + classname + ".java";
     file_list->push_back(filename);
-    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
-    google::protobuf::scoped_ptr<io::Printer> printer(new io::Printer(output.get(), '$'));
-
+    std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+    GeneratedCodeInfo annotations;
+    io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+        &annotations);
+    std::unique_ptr<io::Printer> printer(
+        new io::Printer(output.get(), '$',
+                        options_.annotate_code ? &annotation_collector : NULL));
+    string info_relative_path = classname + ".java.pb.meta";
+    string info_full_path = filename + ".pb.meta";
     printer->Print(
-      "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
-      "// source: $filename$\n"
-      "\n",
-      "filename", file_->name());
+        "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+        "// source: $filename$\n"
+        "\n",
+        "filename", file_->name());
     if (!java_package.empty()) {
       printer->Print(
         "package $package$;\n"
         "\n",
         "package", java_package);
     }
+    PrintGeneratedAnnotation(printer.get(), '$',
+                             options_.annotate_code ? info_relative_path : "");
     printer->Print(
-      "public final class $classname$ {\n"
-      "  public static com.google.protobuf.Descriptors.FileDescriptor\n"
-      "      descriptor;\n"
-      "  static {\n",
-      "classname", classname);
+        "public final class $classname$ {\n"
+        "  public static com.google.protobuf.Descriptors.FileDescriptor\n"
+        "      descriptor;\n"
+        "  static {\n",
+        "classname", classname);
+    printer->Annotate("classname", file_->name());
     printer->Indent();
     printer->Indent();
     GenerateDescriptors(printer.get());
@@ -97,12 +104,18 @@
       "  }\n"
       "}\n");
 
+    if (options_.annotate_code) {
+      std::unique_ptr<io::ZeroCopyOutputStream> info_output(
+          context->Open(info_full_path));
+      annotations.SerializeToZeroCopyStream(info_output.get());
+      annotation_file_list->push_back(info_full_path);
+    }
+
     printer.reset();
     output.reset();
   }
 }
 
-
 void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) {
   // Embed the descriptor.  We simply serialize the entire FileDescriptorProto
   // and embed it as a string literal, which is parsed and built into real
@@ -117,7 +130,6 @@
   FileDescriptorProto file_proto;
   file_->CopyTo(&file_proto);
 
-
   string file_data;
   file_proto.SerializeToString(&file_data);
 
@@ -125,13 +137,16 @@
     "java.lang.String[] descriptorData = {\n");
   printer->Indent();
 
-  // Only write 40 bytes per line.
+  // Limit the number of bytes per line.
   static const int kBytesPerLine = 40;
+  // Limit the number of lines per string part.
+  static const int kLinesPerPart = 400;
+  // Every block of bytes, start a new string literal, in order to avoid the
+  // 64k length limit. Note that this value needs to be <64k.
+  static const int kBytesPerPart = kBytesPerLine * kLinesPerPart;
   for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
     if (i > 0) {
-      // Every 400 lines, start a new string literal, in order to avoid the
-      // 64k length limit.
-      if (i % 400 == 0) {
+      if (i % kBytesPerPart == 0) {
         printer->Print(",\n");
       } else {
         printer->Print(" +\n");
@@ -164,15 +179,19 @@
 
   // -----------------------------------------------------------------
   // Find out all dependencies.
-  vector<pair<string, string> > dependencies;
+  std::vector<std::pair<string, string> > dependencies;
   for (int i = 0; i < file_->dependency_count(); i++) {
-    if (ShouldIncludeDependency(file_->dependency(i))) {
-      string filename = file_->dependency(i)->name();
-      string classname = FileJavaPackage(file_->dependency(i)) + "." +
-                         name_resolver_->GetDescriptorClassName(
-                             file_->dependency(i));
-      dependencies.push_back(std::make_pair(filename, classname));
+    string filename = file_->dependency(i)->name();
+    string package = FileJavaPackage(file_->dependency(i));
+    string classname = name_resolver_->GetDescriptorClassName(
+        file_->dependency(i));
+    string full_name;
+    if (package.empty()) {
+      full_name = classname;
+    } else {
+      full_name = package + "." + classname;
     }
+    dependencies.push_back(std::make_pair(filename, full_name));
   }
 
   // -----------------------------------------------------------------
@@ -194,11 +213,6 @@
     "    }, assigner);\n");
 }
 
-bool SharedCodeGenerator::ShouldIncludeDependency(
-    const FileDescriptor* descriptor) {
-  return true;
-}
-
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.h b/src/google/protobuf/compiler/java/java_shared_code_generator.h
index 38a32fc..58a31f5 100644
--- a/src/google/protobuf/compiler/java/java_shared_code_generator.h
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.h
@@ -36,13 +36,11 @@
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__
 
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 #include <string>
 #include <vector>
 
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_options.h>
 
 namespace google {
 namespace protobuf {
@@ -66,22 +64,19 @@
 // and mutable API. Currently only descriptors are shared.
 class SharedCodeGenerator {
  public:
-  explicit SharedCodeGenerator(const FileDescriptor* file);
+  SharedCodeGenerator(const FileDescriptor* file, const Options& options);
   ~SharedCodeGenerator();
 
   void Generate(GeneratorContext* generator_context,
-                vector<string>* file_list);
+                std::vector<string>* file_list,
+                std::vector<string>* annotation_file_list);
 
   void GenerateDescriptors(io::Printer* printer);
 
  private:
-  // Returns whether the dependency should be included in the output file.
-  // Always returns true for opensource, but used internally at Google to help
-  // improve compatibility with version 1 of protocol buffers.
-  bool ShouldIncludeDependency(const FileDescriptor* descriptor);
-
-  google::protobuf::scoped_ptr<ClassNameResolver> name_resolver_;
+  std::unique_ptr<ClassNameResolver> name_resolver_;
   const FileDescriptor* file_;
+  const Options options_;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SharedCodeGenerator);
 };
 
diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
index 7f757e4..2b6e938 100644
--- a/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -62,7 +62,7 @@
                            int builderBitIndex,
                            const FieldGeneratorInfo* info,
                            ClassNameResolver* name_resolver,
-                           map<string, string>* variables) {
+                           std::map<string, string>* variables) {
   SetCommonFieldVariables(descriptor, info, variables);
 
   (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY";
@@ -71,7 +71,8 @@
   (*variables)["default_init"] =
       "= " + ImmutableDefaultValue(descriptor, name_resolver);
   (*variables)["capitalized_type"] = "String";
-  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+  (*variables)["tag"] =
+      SimpleItoa(static_cast<int32>(WireFormat::MakeTag(descriptor)));
   (*variables)["tag_size"] = SimpleItoa(
       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   (*variables)["null_check"] =
@@ -79,16 +80,17 @@
       "    throw new NullPointerException();\n"
       "  }\n";
   (*variables)["writeString"] =
-      "com.google.protobuf.GeneratedMessage.writeString";
+      "com.google.protobuf.GeneratedMessage" + GeneratedCodeVersionSuffix() +
+      ".writeString";
   (*variables)["computeStringSize"] =
-      "com.google.protobuf.GeneratedMessage.computeStringSize";
+      "com.google.protobuf.GeneratedMessage" + GeneratedCodeVersionSuffix() +
+      ".computeStringSize";
 
   // 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();" : "";
+  (*variables)["on_changed"] = "onChanged();";
 
   if (SupportFieldPresence(descriptor->file())) {
     // For singular messages and builders, one bit is used for the hasField bit.
@@ -215,14 +217,15 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
     "  java.lang.Object ref = $name$_;\n"
     "  if (ref instanceof java.lang.String) {\n"
     "    return (java.lang.String) ref;\n"
@@ -230,6 +233,7 @@
     "    com.google.protobuf.ByteString bs = \n"
     "        (com.google.protobuf.ByteString) ref;\n"
       "    java.lang.String s = bs.toStringUtf8();\n");
+  printer->Annotate("{", "}", descriptor_);
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
       "    $name$_ = s;\n");
@@ -246,7 +250,7 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes() {\n"
+    "    ${$get$capitalized_name$Bytes$}$() {\n"
     "  java.lang.Object ref = $name$_;\n"
     "  if (ref instanceof java.lang.String) {\n"
     "    com.google.protobuf.ByteString b = \n"
@@ -258,6 +262,7 @@
     "    return (com.google.protobuf.ByteString) ref;\n"
     "  }\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableStringFieldGenerator::
@@ -267,19 +272,21 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_builder$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
     "  java.lang.Object ref = $name$_;\n"
     "  if (!(ref instanceof java.lang.String)) {\n"
     "    com.google.protobuf.ByteString bs =\n"
     "        (com.google.protobuf.ByteString) ref;\n"
     "    java.lang.String s = bs.toStringUtf8();\n");
+  printer->Annotate("{", "}", descriptor_);
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
       "    $name$_ = s;\n");
@@ -299,7 +306,7 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes() {\n"
+    "    ${$get$capitalized_name$Bytes$}$() {\n"
     "  java.lang.Object ref = $name$_;\n"
     "  if (ref instanceof String) {\n"
     "    com.google.protobuf.ByteString b = \n"
@@ -311,10 +318,11 @@
     "    return (com.google.protobuf.ByteString) ref;\n"
     "  }\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    java.lang.String value) {\n"
     "$null_check$"
     "  $set_has_field_bit_builder$\n"
@@ -322,10 +330,12 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  $clear_has_field_bit_builder$\n");
+  printer->Annotate("{", "}", descriptor_);
   // 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_,
@@ -337,9 +347,10 @@
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$Bytes(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
     "    com.google.protobuf.ByteString value) {\n"
     "$null_check$");
+  printer->Annotate("{", "}", descriptor_);
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
       "  checkByteStringIsUtf8(value);\n");
@@ -408,15 +419,6 @@
       "java.lang.String s = input.readStringRequireUtf8();\n"
       "$set_has_field_bit_message$\n"
       "$name$_ = s;\n");
-  } else if (!HasDescriptorMethods(descriptor_->file())) {
-    // Lite runtime should attempt to reduce allocations by attempting to
-    // construct the string directly from the input stream buffer. This avoids
-    // spurious intermediary ByteString allocations, cutting overall allocations
-    // in half.
-    printer->Print(variables_,
-      "java.lang.String s = input.readString();\n"
-      "$set_has_field_bit_message$\n"
-      "$name$_ = s;\n");
   } else {
     printer->Print(variables_,
       "com.google.protobuf.ByteString bs = input.readBytes();\n"
@@ -489,14 +491,15 @@
   if (SupportFieldPresence(descriptor_->file())) {
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
     "  return $has_oneof_case_message$;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
     "  java.lang.Object ref $default_init$;\n"
     "  if ($has_oneof_case_message$) {\n"
     "    ref = $oneof_name$_;\n"
@@ -507,6 +510,7 @@
     "    com.google.protobuf.ByteString bs = \n"
     "        (com.google.protobuf.ByteString) ref;\n"
     "    java.lang.String s = bs.toStringUtf8();\n");
+  printer->Annotate("{", "}", descriptor_);
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
     "    if ($has_oneof_case_message$) {\n"
@@ -526,7 +530,7 @@
 
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes() {\n"
+    "    ${$get$capitalized_name$Bytes$}$() {\n"
     "  java.lang.Object ref $default_init$;\n"
     "  if ($has_oneof_case_message$) {\n"
     "    ref = $oneof_name$_;\n"
@@ -543,6 +547,7 @@
     "    return (com.google.protobuf.ByteString) ref;\n"
     "  }\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableStringOneofFieldGenerator::
@@ -550,14 +555,15 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $has_oneof_case_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
     "  java.lang.Object ref $default_init$;\n"
     "  if ($has_oneof_case_message$) {\n"
     "    ref = $oneof_name$_;\n"
@@ -567,6 +573,7 @@
     "        (com.google.protobuf.ByteString) ref;\n"
     "    java.lang.String s = bs.toStringUtf8();\n"
     "    if ($has_oneof_case_message$) {\n");
+  printer->Annotate("{", "}", descriptor_);
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
       "      $oneof_name$_ = s;\n");
@@ -587,7 +594,7 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes() {\n"
+    "    ${$get$capitalized_name$Bytes$}$() {\n"
     "  java.lang.Object ref $default_init$;\n"
     "  if ($has_oneof_case_message$) {\n"
     "    ref = $oneof_name$_;\n"
@@ -604,10 +611,11 @@
     "    return (com.google.protobuf.ByteString) ref;\n"
     "  }\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    java.lang.String value) {\n"
     "$null_check$"
     "  $set_oneof_case_message$;\n"
@@ -615,9 +623,10 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "    $clear_oneof_case_message$;\n"
     "    $oneof_name$_ = null;\n"
@@ -625,12 +634,14 @@
     "  }\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$Bytes(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
     "    com.google.protobuf.ByteString value) {\n"
     "$null_check$");
+  printer->Annotate("{", "}", descriptor_);
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
       "  checkByteStringIsUtf8(value);\n");
@@ -668,15 +679,6 @@
       "java.lang.String s = input.readStringRequireUtf8();\n"
       "$set_oneof_case_message$;\n"
       "$oneof_name$_ = s;\n");
-  } else if (!HasDescriptorMethods(descriptor_->file())) {
-    // Lite runtime should attempt to reduce allocations by attempting to
-    // construct the string directly from the input stream buffer. This avoids
-    // spurious intermediary ByteString allocations, cutting overall allocations
-    // in half.
-    printer->Print(variables_,
-      "java.lang.String s = input.readString();\n"
-      "$set_oneof_case_message$;\n"
-      "$oneof_name$_ = s;\n");
   } else {
     printer->Print(variables_,
       "com.google.protobuf.ByteString bs = input.readBytes();\n"
@@ -731,7 +733,13 @@
 GenerateInterfaceMembers(io::Printer* printer) const {
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$com.google.protobuf.ProtocolStringList\n"
+    // NOTE: the same method in the implementation class actually returns
+    // com.google.protobuf.ProtocolStringList (a subclass of List). It's
+    // changed between protobuf 2.5.0 release and protobuf 2.6.1 release.
+    // To retain binary compatibility with both 2.5.0 and 2.6.1 generated
+    // code, we make this interface method return List so both methods
+    // with different return types exist in the compiled byte code.
+    "$deprecation$java.util.List<java.lang.String>\n"
     "    get$capitalized_name$List();\n");
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
@@ -754,25 +762,30 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ProtocolStringList\n"
-    "    get$capitalized_name$List() {\n"
+    "    ${$get$capitalized_name$List$}$() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
+    "$deprecation$public java.lang.String "
+    "${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes(int index) {\n"
+    "    ${$get$capitalized_name$Bytes$}$(int index) {\n"
     "  return $name$_.getByteString(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedImmutableStringFieldGenerator::
@@ -804,28 +817,33 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ProtocolStringList\n"
-    "    get$capitalized_name$List() {\n"
+    "    ${$get$capitalized_name$List$}$() {\n"
     "  return $name$_.getUnmodifiableView();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
+    "$deprecation$public java.lang.String "
+    "${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes(int index) {\n"
+    "    ${$get$capitalized_name$Bytes$}$(int index) {\n"
     "  return $name$_.getByteString(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, java.lang.String value) {\n"
     "$null_check$"
     "  ensure$capitalized_name$IsMutable();\n"
@@ -833,9 +851,10 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
     "    java.lang.String value) {\n"
     "$null_check$"
     "  ensure$capitalized_name$IsMutable();\n"
@@ -843,9 +862,10 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
     "    java.lang.Iterable<java.lang.String> values) {\n"
     "  ensure$capitalized_name$IsMutable();\n"
     "  com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
@@ -853,20 +873,23 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\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->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$Bytes(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$Bytes$}$(\n"
     "    com.google.protobuf.ByteString value) {\n"
     "$null_check$");
+  printer->Annotate("{", "}", descriptor_);
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
       "  checkByteStringIsUtf8(value);\n");
@@ -934,13 +957,6 @@
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
     "java.lang.String s = input.readStringRequireUtf8();\n");
-  } else if (!HasDescriptorMethods(descriptor_->file())) {
-    // Lite runtime should attempt to reduce allocations by attempting to
-    // construct the string directly from the input stream buffer. This avoids
-    // spurious intermediary ByteString allocations, cutting overall allocations
-    // in half.
-    printer->Print(variables_,
-    "java.lang.String s = input.readString();\n");
   } else {
     printer->Print(variables_,
     "com.google.protobuf.ByteString bs = input.readBytes();\n");
@@ -950,7 +966,7 @@
     "  $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
     "  $set_mutable_bit_parser$;\n"
     "}\n");
-  if (CheckUtf8(descriptor_) || !HasDescriptorMethods(descriptor_->file())) {
+  if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
       "$name$_.add(s);\n");
   } else {
diff --git a/src/google/protobuf/compiler/java/java_string_field.h b/src/google/protobuf/compiler/java/java_string_field.h
index a3b5735..0f7c705 100644
--- a/src/google/protobuf/compiler/java/java_string_field.h
+++ b/src/google/protobuf/compiler/java/java_string_field.h
@@ -83,7 +83,7 @@
 
  protected:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   const int messageBitIndex_;
   const int builderBitIndex_;
   Context* context_;
@@ -142,7 +142,7 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   const int messageBitIndex_;
   const int builderBitIndex_;
   Context* context_;
diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.cc b/src/google/protobuf/compiler/java/java_string_field_lite.cc
index eb5964b..a238c67 100644
--- a/src/google/protobuf/compiler/java/java_string_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_string_field_lite.cc
@@ -62,7 +62,7 @@
                            int builderBitIndex,
                            const FieldGeneratorInfo* info,
                            ClassNameResolver* name_resolver,
-                           map<string, string>* variables) {
+                           std::map<string, string>* variables) {
   SetCommonFieldVariables(descriptor, info, variables);
 
   (*variables)["empty_list"] =
@@ -71,8 +71,9 @@
   (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
   (*variables)["default_init"] =
       "= " + ImmutableDefaultValue(descriptor, name_resolver);
-  (*variables)["capitalized_type"] = "String";
-  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+  (*variables)["capitalized_type"] = "java.lang.String";
+  (*variables)["tag"] =
+      SimpleItoa(static_cast<int32>(WireFormat::MakeTag(descriptor)));
   (*variables)["tag_size"] = SimpleItoa(
       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   (*variables)["null_check"] =
@@ -84,8 +85,7 @@
   // by the proto compiler
   (*variables)["deprecation"] = descriptor->options().deprecated()
       ? "@java.lang.Deprecated " : "";
-  (*variables)["on_changed"] =
-      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+  (*variables)["required"] = descriptor->is_required() ? "true" : "false";
 
   if (SupportFieldPresence(descriptor->file())) {
     // For singular messages and builders, one bit is used for the hasField bit.
@@ -103,7 +103,7 @@
     (*variables)["clear_has_field_bit_message"] = "";
 
     (*variables)["is_field_present_message"] =
-        "!get" + (*variables)["capitalized_name"] + ".isEmpty()";
+        "!" + (*variables)["name"] + "_.isEmpty()";
   }
 
   // For repeated builders, the underlying list tracks mutability state.
@@ -192,22 +192,28 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
     "  return $name$_;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
+    "@java.lang.Override\n"
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes() {\n"
+    "    ${$get$capitalized_name$Bytes$}$() {\n"
     "  return com.google.protobuf.ByteString.copyFromUtf8($name$_);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
@@ -246,48 +252,57 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return instance.has$capitalized_name$();\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
     "  return instance.get$capitalized_name$();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
+    "@java.lang.Override\n"
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes() {\n"
+    "    ${$get$capitalized_name$Bytes$}$() {\n"
     "  return instance.get$capitalized_name$Bytes();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    java.lang.String value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$Bytes(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
     "    com.google.protobuf.ByteString value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$Bytes(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableStringFieldLiteGenerator::
@@ -295,28 +310,23 @@
   // noop for strings
 }
 
+
 void ImmutableStringFieldLiteGenerator::
 GenerateInitializationCode(io::Printer* printer) const {
   printer->Print(variables_, "$name$_ = $default$;\n");
 }
 
 void ImmutableStringFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
+GenerateVisitCode(io::Printer* printer) const {
   if (SupportFieldPresence(descriptor_->file())) {
-    // Allow a slight breach of abstraction here in order to avoid forcing
-    // all string fields to Strings when copying fields from a Message.
     printer->Print(variables_,
-      "if (other.has$capitalized_name$()) {\n"
-      "  $set_has_field_bit_message$\n"
-      "  $name$_ = other.$name$_;\n"
-      "  $on_changed$\n"
-      "}\n");
+      "$name$_ = visitor.visitString(\n"
+      "    has$capitalized_name$(), $name$_,\n"
+      "    other.has$capitalized_name$(), other.$name$_);\n");
   } else {
     printer->Print(variables_,
-      "if (!other.get$capitalized_name$().isEmpty()) {\n"
-      "  $name$_ = other.$name$_;\n"
-      "  $on_changed$\n"
-      "}\n");
+      "$name$_ = visitor.visitString(!$name$_.isEmpty(), $name$_,\n"
+      "    !other.$name$_.isEmpty(), other.$name$_);\n");
   }
 }
 
@@ -329,7 +339,7 @@
 GenerateParsingCode(io::Printer* printer) const {
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
-      "String s = input.readStringRequireUtf8();\n"
+      "java.lang.String s = input.readStringRequireUtf8();\n"
       "$set_has_field_bit_message$\n"
       "$name$_ = s;\n");
   } else {
@@ -338,7 +348,7 @@
     // spurious intermediary ByteString allocations, cutting overall allocations
     // in half.
     printer->Print(variables_,
-      "String s = input.readString();\n"
+      "java.lang.String s = input.readString();\n"
       "$set_has_field_bit_message$\n"
       "$name$_ = s;\n");
   }
@@ -415,54 +425,63 @@
   if (SupportFieldPresence(descriptor_->file())) {
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
     "  return $has_oneof_case_message$;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
     "  java.lang.String ref $default_init$;\n"
     "  if ($has_oneof_case_message$) {\n"
     "    ref = (java.lang.String) $oneof_name$_;\n"
     "  }\n"
     "  return ref;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
 
   printer->Print(variables_,
+    "@java.lang.Override\n"
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes() {\n"
+    "    ${$get$capitalized_name$Bytes$}$() {\n"
     "  java.lang.String ref $default_init$;\n"
     "  if ($has_oneof_case_message$) {\n"
     "    ref = (java.lang.String) $oneof_name$_;\n"
     "  }\n"
     "  return com.google.protobuf.ByteString.copyFromUtf8(ref);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "private void set$capitalized_name$(\n"
+    "private void ${$set$capitalized_name$$}$(\n"
     "    java.lang.String value) {\n"
     "$null_check$"
     "  $set_oneof_case_message$;\n"
     "  $oneof_name$_ = value;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "private void clear$capitalized_name$() {\n"
+    "private void ${$clear$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "    $clear_oneof_case_message$;\n"
     "    $oneof_name$_ = null;\n"
     "  }\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "private void set$capitalized_name$Bytes(\n"
+    "private void ${$set$capitalized_name$Bytes$}$(\n"
     "    com.google.protobuf.ByteString value) {\n"
     "$null_check$");
+  printer->Annotate("{", "}", descriptor_);
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
       "  checkByteStringIsUtf8(value);\n");
@@ -473,70 +492,77 @@
     "}\n");
 }
 
+
 void ImmutableStringOneofFieldLiteGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "@java.lang.Override\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return instance.has$capitalized_name$();\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
     "  return instance.get$capitalized_name$();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
+    "@java.lang.Override\n"
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes() {\n"
+    "    ${$get$capitalized_name$Bytes$}$() {\n"
     "  return instance.get$capitalized_name$Bytes();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    java.lang.String value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$Bytes(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
     "    com.google.protobuf.ByteString value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$Bytes(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableStringOneofFieldLiteGenerator::
-GenerateMergingCode(io::Printer* printer) const {
-  // Allow a slight breach of abstraction here in order to avoid forcing
-  // all string fields to Strings when copying fields from a Message.
+GenerateVisitCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "$set_oneof_case_message$;\n"
-    "$oneof_name$_ = other.$oneof_name$_;\n"
-    "$on_changed$\n");
+    "$oneof_name$_ = visitor.visitOneofString(\n"
+    "   $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n");
 }
 
 void ImmutableStringOneofFieldLiteGenerator::
 GenerateParsingCode(io::Printer* printer) const {
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
-      "String s = input.readStringRequireUtf8();\n"
+      "java.lang.String s = input.readStringRequireUtf8();\n"
       "$set_oneof_case_message$;\n"
       "$oneof_name$_ = s;\n");
   } else {
@@ -545,7 +571,7 @@
     // spurious intermediary ByteString allocations, cutting overall allocations
     // in half.
     printer->Print(variables_,
-      "String s = input.readString();\n"
+      "java.lang.String s = input.readString();\n"
       "$set_oneof_case_message$;\n"
       "$oneof_name$_ = s;\n");
   }
@@ -604,7 +630,7 @@
 GenerateInterfaceMembers(io::Printer* printer) const {
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$java.util.List<String>\n"
+    "$deprecation$java.util.List<java.lang.String>\n"
     "    get$capitalized_name$List();\n");
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
@@ -622,36 +648,47 @@
 void RepeatedImmutableStringFieldLiteGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private com.google.protobuf.Internal.ProtobufList<String> $name$_;\n");
+    "private com.google.protobuf.Internal.ProtobufList<java.lang.String> "
+    "$name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.util.List<String> get$capitalized_name$List() {\n"
-    "  return $name$_;\n"   // note:  unmodifiable list
+    "@java.lang.Override\n"
+    "$deprecation$public java.util.List<java.lang.String> "
+    "${$get$capitalized_name$List$}$() {\n"
+    "  return $name$_;\n"  // note:  unmodifiable list
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public java.lang.String "
+    "${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
+    "@java.lang.Override\n"
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes(int index) {\n"
+    "    ${$get$capitalized_name$Bytes$}$(int index) {\n"
     "  return com.google.protobuf.ByteString.copyFromUtf8(\n"
     "      $name$_.get(index));\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   printer->Print(variables_,
     "private void ensure$capitalized_name$IsMutable() {\n"
     "  if (!$is_mutable$) {\n"
-    "    $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList(\n"
-    "        $name$_);\n"
+    "    $name$_ =\n"
+    "        com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
     "   }\n"
     "}\n");
 
@@ -704,67 +741,81 @@
 GenerateBuilderMembers(io::Printer* printer) const {
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.util.List<String>\n"
-    "    get$capitalized_name$List() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public java.util.List<java.lang.String>\n"
+    "    ${$get$capitalized_name$List$}$() {\n"
     "  return java.util.Collections.unmodifiableList(\n"
     "      instance.get$capitalized_name$List());\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return instance.get$capitalized_name$Count();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
+    "@java.lang.Override\n"
+    "$deprecation$public java.lang.String "
+    "${$get$capitalized_name$$}$(int index) {\n"
     "  return instance.get$capitalized_name$(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
+    "@java.lang.Override\n"
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes(int index) {\n"
+    "    ${$get$capitalized_name$Bytes$}$(int index) {\n"
     "  return instance.get$capitalized_name$Bytes(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, java.lang.String value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(index, value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
     "    java.lang.String value) {\n"
     "  copyOnWrite();\n"
     "  instance.add$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
     "    java.lang.Iterable<java.lang.String> values) {\n"
     "  copyOnWrite();\n"
     "  instance.addAll$capitalized_name$(values);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$Bytes(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$Bytes$}$(\n"
     "    com.google.protobuf.ByteString value) {\n"
     "  copyOnWrite();\n"
     "  instance.add$capitalized_name$Bytes(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedImmutableStringFieldLiteGenerator::
@@ -772,28 +823,16 @@
   // noop for strings
 }
 
+
 void RepeatedImmutableStringFieldLiteGenerator::
 GenerateInitializationCode(io::Printer* printer) const {
   printer->Print(variables_, "$name$_ = $empty_list$;\n");
 }
 
 void RepeatedImmutableStringFieldLiteGenerator::
-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.
+GenerateVisitCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (!other.$name$_.isEmpty()) {\n"
-    "  if ($name$_.isEmpty()) {\n"
-    "    $name$_ = other.$name$_;\n"
-    "  } else {\n"
-    "    ensure$capitalized_name$IsMutable();\n"
-    "    $name$_.addAll(other.$name$_);\n"
-    "  }\n"
-    "  $on_changed$\n"
-    "}\n");
+      "$name$_= visitor.visitList($name$_, other.$name$_);\n");
 }
 
 void RepeatedImmutableStringFieldLiteGenerator::
@@ -806,26 +845,22 @@
 GenerateParsingCode(io::Printer* printer) const {
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
-    "String s = input.readStringRequireUtf8();\n");
+      "java.lang.String s = input.readStringRequireUtf8();\n");
   } else {
     // Lite runtime should attempt to reduce allocations by attempting to
     // construct the string directly from the input stream buffer. This avoids
     // spurious intermediary ByteString allocations, cutting overall allocations
     // in half.
     printer->Print(variables_,
-    "String s = input.readString();\n");
+      "java.lang.String s = input.readString();\n");
   }
   printer->Print(variables_,
     "if (!$is_mutable$) {\n"
-    "  $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList();\n"
+    "  $name$_ =\n"
+    "      com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
     "}\n");
-  if (CheckUtf8(descriptor_) || !HasDescriptorMethods(descriptor_->file())) {
-    printer->Print(variables_,
-      "$name$_.add(s);\n");
-  } else {
-    printer->Print(variables_,
-      "$name$_.add(bs);\n");
-  }
+  printer->Print(variables_,
+    "$name$_.add(s);\n");
 }
 
 void RepeatedImmutableStringFieldLiteGenerator::
@@ -891,7 +926,7 @@
 }
 
 string RepeatedImmutableStringFieldLiteGenerator::GetBoxedType() const {
-  return "String";
+  return "java.lang.String";
 }
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.h b/src/google/protobuf/compiler/java/java_string_field_lite.h
index 4d9b4bd..b7fb640 100644
--- a/src/google/protobuf/compiler/java/java_string_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_string_field_lite.h
@@ -68,7 +68,7 @@
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
   void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateParsingDoneCode(io::Printer* printer) const;
@@ -78,11 +78,12 @@
   void GenerateEqualsCode(io::Printer* printer) const;
   void GenerateHashCode(io::Printer* printer) const;
 
+
   string GetBoxedType() const;
 
  protected:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   const int messageBitIndex_;
   const int builderBitIndex_;
   Context* context_;
@@ -103,11 +104,12 @@
  private:
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateSerializationCode(io::Printer* printer) const;
   void GenerateSerializedSizeCode(io::Printer* printer) const;
 
+
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldLiteGenerator);
 };
 
@@ -126,7 +128,7 @@
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
+  void GenerateVisitCode(io::Printer* printer) const;
   void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
   void GenerateParsingCode(io::Printer* printer) const;
   void GenerateParsingDoneCode(io::Printer* printer) const;
@@ -136,11 +138,12 @@
   void GenerateEqualsCode(io::Printer* printer) const;
   void GenerateHashCode(io::Printer* printer) const;
 
+
   string GetBoxedType() const;
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   const int messageBitIndex_;
   const int builderBitIndex_;
   Context* context_;
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum.cc b/src/google/protobuf/compiler/javanano/javanano_enum.cc
deleted file mode 100644
index c6e8dfe..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_enum.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-// 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)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-
-#include <map>
-#include <string>
-
-#include <google/protobuf/compiler/javanano/javanano_params.h>
-#include <google/protobuf/compiler/javanano/javanano_enum.h>
-#include <google/protobuf/compiler/javanano/javanano_helpers.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/stubs/strutil.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Params& params)
-  : params_(params), descriptor_(descriptor) {
-  for (int i = 0; i < descriptor_->value_count(); i++) {
-    const EnumValueDescriptor* value = descriptor_->value(i);
-    const EnumValueDescriptor* canonical_value =
-      descriptor_->FindValueByNumber(value->number());
-
-    if (value == canonical_value) {
-      canonical_values_.push_back(value);
-    } else {
-      Alias alias;
-      alias.value = value;
-      alias.canonical_value = canonical_value;
-      aliases_.push_back(alias);
-    }
-  }
-}
-
-EnumGenerator::~EnumGenerator() {}
-
-void EnumGenerator::Generate(io::Printer* printer) {
-  printer->Print(
-      "\n"
-      "// enum $classname$\n",
-      "classname", descriptor_->name());
-
-  const string classname = RenameJavaKeywords(descriptor_->name());
-
-  // Start of container interface
-  // If generating intdefs, we use the container interface as the intdef if
-  // present. Otherwise, we just make an empty @interface parallel to the
-  // constants.
-  bool use_intdef = params_.generate_intdefs();
-  bool use_shell_class = params_.java_enum_style();
-  if (use_intdef) {
-    // @IntDef annotation so tools can enforce correctness
-    // Annotations will be discarded by the compiler
-    printer->Print("@java.lang.annotation.Retention("
-      "java.lang.annotation.RetentionPolicy.SOURCE)\n"
-      "@android.support.annotation.IntDef({\n");
-    printer->Indent();
-    for (int i = 0; i < canonical_values_.size(); i++) {
-      const string constant_name =
-          RenameJavaKeywords(canonical_values_[i]->name());
-      if (use_shell_class) {
-        printer->Print("$classname$.$name$,\n",
-          "classname", classname,
-          "name", constant_name);
-      } else {
-        printer->Print("$name$,\n", "name", constant_name);
-      }
-    }
-    printer->Outdent();
-    printer->Print("})\n");
-  }
-  if (use_shell_class || use_intdef) {
-    printer->Print(
-      "public $at_for_intdef$interface $classname$ {\n",
-      "classname", classname,
-      "at_for_intdef", use_intdef ? "@" : "");
-    if (use_shell_class) {
-        printer->Indent();
-    } else {
-        printer->Print("}\n\n");
-    }
-  }
-
-  // Canonical values
-  for (int i = 0; i < canonical_values_.size(); i++) {
-    printer->Print(
-      "public static final int $name$ = $canonical_value$;\n",
-      "name", RenameJavaKeywords(canonical_values_[i]->name()),
-      "canonical_value", SimpleItoa(canonical_values_[i]->number()));
-  }
-
-  // Aliases
-  for (int i = 0; i < aliases_.size(); i++) {
-    printer->Print(
-      "public static final int $name$ = $canonical_name$;\n",
-      "name", RenameJavaKeywords(aliases_[i].value->name()),
-      "canonical_name", RenameJavaKeywords(aliases_[i].canonical_value->name()));
-  }
-
-  // End of container interface
-  if (use_shell_class) {
-    printer->Outdent();
-    printer->Print("}\n");
-  }
-}
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum.h b/src/google/protobuf/compiler/javanano/javanano_enum.h
deleted file mode 100644
index 10dd364..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_enum.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// 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)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_H__
-
-#include <string>
-#include <vector>
-
-#include <google/protobuf/compiler/javanano/javanano_params.h>
-#include <google/protobuf/descriptor.h>
-
-namespace google {
-namespace protobuf {
-  namespace io {
-    class Printer;             // printer.h
-  }
-}
-
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-class EnumGenerator {
- public:
-  explicit EnumGenerator(const EnumDescriptor* descriptor, const Params& params);
-  ~EnumGenerator();
-
-  void Generate(io::Printer* printer);
-
- private:
-  const Params& params_;
-  const EnumDescriptor* descriptor_;
-
-  // The proto language allows multiple enum constants to have the same numeric
-  // value.  Java, however, does not allow multiple enum constants to be
-  // considered equivalent.  We treat the first defined constant for any
-  // given numeric value as "canonical" and the rest as aliases of that
-  // canonical value.
-  vector<const EnumValueDescriptor*> canonical_values_;
-
-  struct Alias {
-    const EnumValueDescriptor* value;
-    const EnumValueDescriptor* canonical_value;
-  };
-  vector<Alias> aliases_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
-};
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-
-}  // namespace google
-#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
deleted file mode 100644
index 7666db3..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
+++ /dev/null
@@ -1,544 +0,0 @@
-// 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)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-
-#include <map>
-#include <string>
-
-#include <google/protobuf/compiler/javanano/javanano_enum_field.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/javanano/javanano_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 javanano {
-
-namespace {
-
-// TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
-//   repeat code between this and the other field types.
-void SetEnumVariables(const Params& params,
-    const FieldDescriptor* descriptor, map<string, string>* variables) {
-  (*variables)["name"] =
-    RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
-  (*variables)["capitalized_name"] =
-    RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
-  (*variables)["number"] = SimpleItoa(descriptor->number());
-  if (params.use_reference_types_for_primitives()
-      && !params.reftypes_primitive_enums()
-      && !descriptor->is_repeated()) {
-    (*variables)["type"] = "java.lang.Integer";
-    (*variables)["default"] = "null";
-  } else {
-    (*variables)["type"] = "int";
-    (*variables)["default"] = DefaultValue(params, descriptor);
-  }
-  (*variables)["repeated_default"] =
-      "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
-  (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
-  (*variables)["tag_size"] = SimpleItoa(
-      internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
-  (*variables)["non_packed_tag"] = SimpleItoa(
-      internal::WireFormatLite::MakeTag(descriptor->number(),
-          internal::WireFormat::WireTypeForFieldType(descriptor->type())));
-  (*variables)["message_name"] = descriptor->containing_type()->name();
-  const EnumDescriptor* enum_type = descriptor->enum_type();
-  (*variables)["message_type_intdef"] = "@"
-      + ToJavaName(params, enum_type->name(), true,
-          enum_type->containing_type(), enum_type->file());
-}
-
-void LoadEnumValues(const Params& params,
-    const EnumDescriptor* enum_descriptor, vector<string>* canonical_values) {
-  string enum_class_name = ClassName(params, enum_descriptor);
-  for (int i = 0; i < enum_descriptor->value_count(); i++) {
-    const EnumValueDescriptor* value = enum_descriptor->value(i);
-    const EnumValueDescriptor* canonical_value =
-        enum_descriptor->FindValueByNumber(value->number());
-    if (value == canonical_value) {
-      canonical_values->push_back(
-          enum_class_name + "." + RenameJavaKeywords(value->name()));
-    }
-  }
-}
-
-void PrintCaseLabels(
-    io::Printer* printer, const vector<string>& canonical_values) {
-  for (int i = 0; i < canonical_values.size(); i++) {
-    printer->Print(
-      "  case $value$:\n",
-      "value", canonical_values[i]);
-  }
-}
-
-}  // namespace
-
-// ===================================================================
-
-EnumFieldGenerator::
-EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
-  : FieldGenerator(params), descriptor_(descriptor) {
-  SetEnumVariables(params, descriptor, &variables_);
-  LoadEnumValues(params, descriptor->enum_type(), &canonical_values_);
-}
-
-EnumFieldGenerator::~EnumFieldGenerator() {}
-
-void EnumFieldGenerator::
-GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
-  if (params_.generate_intdefs()) {
-    printer->Print(variables_, "$message_type_intdef$\n");
-  }
-  printer->Print(variables_, "public $type$ $name$;\n");
-
-  if (params_.generate_has()) {
-    printer->Print(variables_,
-      "public boolean has$capitalized_name$;\n");
-  }
-}
-
-void EnumFieldGenerator::
-GenerateClearCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "$name$ = $default$;\n");
-
-  if (params_.generate_has()) {
-    printer->Print(variables_,
-      "has$capitalized_name$ = false;\n");
-  }
-}
-
-void EnumFieldGenerator::
-GenerateMergingCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "int value = input.readInt32();\n"
-    "switch (value) {\n");
-  PrintCaseLabels(printer, canonical_values_);
-  printer->Print(variables_,
-    "    this.$name$ = value;\n");
-  if (params_.generate_has()) {
-    printer->Print(variables_,
-      "    has$capitalized_name$ = true;\n");
-  }
-  printer->Print(
-    "    break;\n"
-    "}\n");
-  // No default case: in case of invalid value from the wire, preserve old
-  // field value. Also we are not storing the invalid value into the unknown
-  // fields, because there is no way to get the value out.
-}
-
-void EnumFieldGenerator::
-GenerateSerializationCode(io::Printer* printer) const {
-  if (descriptor_->is_required() && !params_.generate_has()) {
-    // Always serialize a required field if we don't have the 'has' signal.
-    printer->Print(variables_,
-      "output.writeInt32($number$, this.$name$);\n");
-  } else {
-    if (params_.generate_has()) {
-      printer->Print(variables_,
-        "if (this.$name$ != $default$ || has$capitalized_name$) {\n");
-    } else {
-      printer->Print(variables_,
-        "if (this.$name$ != $default$) {\n");
-    }
-    printer->Print(variables_,
-      "  output.writeInt32($number$, this.$name$);\n"
-      "}\n");
-  }
-}
-
-void EnumFieldGenerator::
-GenerateSerializedSizeCode(io::Printer* printer) const {
-  if (descriptor_->is_required() && !params_.generate_has()) {
-    printer->Print(variables_,
-      "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
-      "  .computeInt32Size($number$, this.$name$);\n");
-  } else {
-    if (params_.generate_has()) {
-      printer->Print(variables_,
-        "if (this.$name$ != $default$ || has$capitalized_name$) {\n");
-    } else {
-      printer->Print(variables_,
-        "if (this.$name$ != $default$) {\n");
-    }
-    printer->Print(variables_,
-      "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
-      "    .computeInt32Size($number$, this.$name$);\n"
-      "}\n");
-  }
-}
-
-void EnumFieldGenerator::GenerateEqualsCode(io::Printer* printer) const {
-  if (params_.use_reference_types_for_primitives()
-        && !params_.reftypes_primitive_enums()) {
-    printer->Print(variables_,
-      "if (this.$name$ == null) {\n"
-      "  if (other.$name$ != null) {\n"
-      "    return false;\n"
-      "  }\n"
-      "} else if (!this.$name$.equals(other.$name$)) {\n"
-      "  return false;"
-      "}\n");
-  } else {
-    // We define equality as serialized form equality. If generate_has(),
-    // then if the field value equals the default value in both messages,
-    // but one's 'has' field is set and the other's is not, the serialized
-    // forms are different and we should return false.
-    printer->Print(variables_,
-      "if (this.$name$ != other.$name$");
-    if (params_.generate_has()) {
-      printer->Print(variables_,
-        "\n"
-        "    || (this.$name$ == $default$\n"
-        "        && this.has$capitalized_name$ != other.has$capitalized_name$)");
-    }
-    printer->Print(") {\n"
-      "  return false;\n"
-      "}\n");
-  }
-}
-
-void EnumFieldGenerator::GenerateHashCodeCode(io::Printer* printer) const {
-  printer->Print(
-    "result = 31 * result + ");
-  if (params_.use_reference_types_for_primitives()
-        && !params_.reftypes_primitive_enums()) {
-    printer->Print(variables_,
-      "(this.$name$ == null ? 0 : this.$name$)");
-  } else {
-    printer->Print(variables_,
-      "this.$name$");
-  }
-  printer->Print(";\n");
-}
-
-// ===================================================================
-
-AccessorEnumFieldGenerator::
-AccessorEnumFieldGenerator(const FieldDescriptor* descriptor,
-    const Params& params, int has_bit_index)
-  : FieldGenerator(params), descriptor_(descriptor) {
-  SetEnumVariables(params, descriptor, &variables_);
-  LoadEnumValues(params, descriptor->enum_type(), &canonical_values_);
-  SetBitOperationVariables("has", has_bit_index, &variables_);
-}
-
-AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {}
-
-void AccessorEnumFieldGenerator::
-GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
-  printer->Print(variables_, "private int $name$_;\n");
-  if (params_.generate_intdefs()) {
-    printer->Print(variables_, "$message_type_intdef$\n");
-  }
-  printer->Print(variables_,
-    "public int get$capitalized_name$() {\n"
-    "  return $name$_;\n"
-    "}\n"
-    "public $message_name$ set$capitalized_name$(");
-  if (params_.generate_intdefs()) {
-    printer->Print(variables_,
-      "\n"
-      "    $message_type_intdef$ ");
-  }
-  printer->Print(variables_,
-    "int value) {\n"
-    "  $name$_ = value;\n"
-    "  $set_has$;\n"
-    "  return this;\n"
-    "}\n"
-    "public boolean has$capitalized_name$() {\n"
-    "  return $get_has$;\n"
-    "}\n"
-    "public $message_name$ clear$capitalized_name$() {\n"
-    "  $name$_ = $default$;\n"
-    "  $clear_has$;\n"
-    "  return this;\n"
-    "}\n");
-}
-
-void AccessorEnumFieldGenerator::
-GenerateClearCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "$name$_ = $default$;\n");
-}
-
-void AccessorEnumFieldGenerator::
-GenerateMergingCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "int value = input.readInt32();\n"
-    "switch (value) {\n");
-  PrintCaseLabels(printer, canonical_values_);
-  printer->Print(variables_,
-    "    $name$_ = value;\n"
-    "    $set_has$;\n"
-    "    break;\n"
-    "}\n");
-  // No default case: in case of invalid value from the wire, preserve old
-  // field value. Also we are not storing the invalid value into the unknown
-  // fields, because there is no way to get the value out.
-}
-
-void AccessorEnumFieldGenerator::
-GenerateSerializationCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if ($get_has$) {\n"
-    "  output.writeInt32($number$, $name$_);\n"
-    "}\n");
-}
-
-void AccessorEnumFieldGenerator::
-GenerateSerializedSizeCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if ($get_has$) {\n"
-    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
-    "    .computeInt32Size($number$, $name$_);\n"
-    "}\n");
-}
-
-void AccessorEnumFieldGenerator::
-GenerateEqualsCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if ($different_has$\n"
-    "    || $name$_ != other.$name$_) {\n"
-    "  return false;\n"
-    "}\n");
-}
-
-void AccessorEnumFieldGenerator::
-GenerateHashCodeCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "result = 31 * result + $name$_;\n");
-}
-
-// ===================================================================
-
-RepeatedEnumFieldGenerator::
-RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
-  : FieldGenerator(params), descriptor_(descriptor) {
-  SetEnumVariables(params, descriptor, &variables_);
-  LoadEnumValues(params, descriptor->enum_type(), &canonical_values_);
-}
-
-RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
-
-void RepeatedEnumFieldGenerator::
-GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
-  printer->Print(variables_,
-    "public $type$[] $name$;\n");
-}
-
-void RepeatedEnumFieldGenerator::
-GenerateClearCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "$name$ = $repeated_default$;\n");
-}
-
-void RepeatedEnumFieldGenerator::
-GenerateMergingCode(io::Printer* printer) const {
-  // First, figure out the maximum length of the array, then parse,
-  // and finally copy the valid values to the field.
-  printer->Print(variables_,
-    "int length = com.google.protobuf.nano.WireFormatNano\n"
-    "    .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n"
-    "int[] validValues = new int[length];\n"
-    "int validCount = 0;\n"
-    "for (int i = 0; i < length; i++) {\n"
-    "  if (i != 0) { // tag for first value already consumed.\n"
-    "    input.readTag();\n"
-    "  }\n"
-    "  int value = input.readInt32();\n"
-    "  switch (value) {\n");
-  printer->Indent();
-  PrintCaseLabels(printer, canonical_values_);
-  printer->Outdent();
-  printer->Print(variables_,
-    "      validValues[validCount++] = value;\n"
-    "      break;\n"
-    "  }\n"
-    "}\n"
-    "if (validCount != 0) {\n"
-    "  int i = this.$name$ == null ? 0 : this.$name$.length;\n"
-    "  if (i == 0 && validCount == validValues.length) {\n"
-    "    this.$name$ = validValues;\n"
-    "  } else {\n"
-    "    int[] newArray = new int[i + validCount];\n"
-    "    if (i != 0) {\n"
-    "      java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
-    "    }\n"
-    "    java.lang.System.arraycopy(validValues, 0, newArray, i, validCount);\n"
-    "    this.$name$ = newArray;\n"
-    "  }\n"
-    "}\n");
-}
-
-void RepeatedEnumFieldGenerator::
-GenerateMergingCodeFromPacked(io::Printer* printer) const {
-  printer->Print(variables_,
-    "int bytes = input.readRawVarint32();\n"
-    "int limit = input.pushLimit(bytes);\n"
-    "// First pass to compute array length.\n"
-    "int arrayLength = 0;\n"
-    "int startPos = input.getPosition();\n"
-    "while (input.getBytesUntilLimit() > 0) {\n"
-    "  switch (input.readInt32()) {\n");
-  printer->Indent();
-  PrintCaseLabels(printer, canonical_values_);
-  printer->Outdent();
-  printer->Print(variables_,
-    "      arrayLength++;\n"
-    "      break;\n"
-    "  }\n"
-    "}\n"
-    "if (arrayLength != 0) {\n"
-    "  input.rewindToPosition(startPos);\n"
-    "  int i = this.$name$ == null ? 0 : this.$name$.length;\n"
-    "  int[] newArray = new int[i + arrayLength];\n"
-    "  if (i != 0) {\n"
-    "    java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
-    "  }\n"
-    "  while (input.getBytesUntilLimit() > 0) {\n"
-    "    int value = input.readInt32();\n"
-    "    switch (value) {\n");
-  printer->Indent();
-  printer->Indent();
-  PrintCaseLabels(printer, canonical_values_);
-  printer->Outdent();
-  printer->Outdent();
-  printer->Print(variables_,
-    "        newArray[i++] = value;\n"
-    "        break;\n"
-    "    }\n"
-    "  }\n"
-    "  this.$name$ = newArray;\n"
-    "}\n"
-    "input.popLimit(limit);\n");
-}
-
-void RepeatedEnumFieldGenerator::
-GenerateRepeatedDataSizeCode(io::Printer* printer) const {
-  // Creates a variable dataSize and puts the serialized size in there.
-  printer->Print(variables_,
-    "int dataSize = 0;\n"
-    "for (int i = 0; i < this.$name$.length; i++) {\n"
-    "  int element = this.$name$[i];\n"
-    "  dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
-    "      .computeInt32SizeNoTag(element);\n"
-    "}\n");
-}
-
-void RepeatedEnumFieldGenerator::
-GenerateSerializationCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (this.$name$ != null && this.$name$.length > 0) {\n");
-  printer->Indent();
-
-  if (descriptor_->options().packed()) {
-    GenerateRepeatedDataSizeCode(printer);
-    printer->Print(variables_,
-      "output.writeRawVarint32($tag$);\n"
-      "output.writeRawVarint32(dataSize);\n"
-      "for (int i = 0; i < this.$name$.length; i++) {\n"
-      "  output.writeRawVarint32(this.$name$[i]);\n"
-      "}\n");
-  } else {
-    printer->Print(variables_,
-      "for (int i = 0; i < this.$name$.length; i++) {\n"
-      "  output.writeInt32($number$, this.$name$[i]);\n"
-      "}\n");
-  }
-
-  printer->Outdent();
-  printer->Print(variables_,
-    "}\n");
-}
-
-void RepeatedEnumFieldGenerator::
-GenerateSerializedSizeCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (this.$name$ != null && this.$name$.length > 0) {\n");
-  printer->Indent();
-
-  GenerateRepeatedDataSizeCode(printer);
-
-  printer->Print(
-    "size += dataSize;\n");
-  if (descriptor_->options().packed()) {
-    printer->Print(variables_,
-      "size += $tag_size$;\n"
-      "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
-      "    .computeRawVarint32Size(dataSize);\n");
-  } else {
-    printer->Print(variables_,
-      "size += $tag_size$ * this.$name$.length;\n");
-  }
-
-  printer->Outdent();
-
-  printer->Print(
-    "}\n");
-}
-
-void RepeatedEnumFieldGenerator::
-GenerateFixClonedCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (this.$name$ != null && this.$name$.length > 0) {\n"
-    "  cloned.$name$ = this.$name$.clone();\n"
-    "}\n");
-}
-
-void RepeatedEnumFieldGenerator::
-GenerateEqualsCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (!com.google.protobuf.nano.InternalNano.equals(\n"
-    "    this.$name$, other.$name$)) {\n"
-    "  return false;\n"
-    "}\n");
-}
-
-void RepeatedEnumFieldGenerator::
-GenerateHashCodeCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "result = 31 * result\n"
-    "    + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
-}
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.h b/src/google/protobuf/compiler/javanano/javanano_enum_field.h
deleted file mode 100644
index b94790d..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_enum_field.h
+++ /dev/null
@@ -1,126 +0,0 @@
-// 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)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_FIELD_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_FIELD_H__
-
-#include <map>
-#include <string>
-#include <vector>
-#include <google/protobuf/compiler/javanano/javanano_field.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-class EnumFieldGenerator : public FieldGenerator {
- public:
-  explicit EnumFieldGenerator(
-      const FieldDescriptor* descriptor, const Params& params);
-  ~EnumFieldGenerator();
-
-  // implements FieldGenerator ---------------------------------------
-  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
-  void GenerateClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCodeCode(io::Printer* printer) const;
-
- private:
-  const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
-  vector<string> canonical_values_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
-};
-
-class AccessorEnumFieldGenerator : public FieldGenerator {
- public:
-  explicit AccessorEnumFieldGenerator(const FieldDescriptor* descriptor,
-      const Params& params, int has_bit_index);
-  ~AccessorEnumFieldGenerator();
-
-  // implements FieldGenerator ---------------------------------------
-  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
-  void GenerateClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCodeCode(io::Printer* printer) const;
-
- private:
-  const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
-  vector<string> canonical_values_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorEnumFieldGenerator);
-};
-
-class RepeatedEnumFieldGenerator : public FieldGenerator {
- public:
-  explicit RepeatedEnumFieldGenerator(
-      const FieldDescriptor* descriptor, const Params& params);
-  ~RepeatedEnumFieldGenerator();
-
-  // implements FieldGenerator ---------------------------------------
-  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
-  void GenerateClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateMergingCodeFromPacked(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCodeCode(io::Printer* printer) const;
-  void GenerateFixClonedCode(io::Printer* printer) const;
-
- private:
-  void GenerateRepeatedDataSizeCode(io::Printer* printer) const;
-
-  const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
-  vector<string> canonical_values_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
-};
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-
-}  // namespace google
-#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_FIELD_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.cc b/src/google/protobuf/compiler/javanano/javanano_extension.cc
deleted file mode 100644
index 0b9d1d8..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_extension.cc
+++ /dev/null
@@ -1,150 +0,0 @@
-// 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: bduff@google.com (Brian Duff)
-
-#include <google/protobuf/compiler/javanano/javanano_extension.h>
-#include <google/protobuf/compiler/javanano/javanano_helpers.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/wire_format.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-using internal::WireFormat;
-using internal::WireFormatLite;
-
-namespace {
-
-const char* GetTypeConstantName(const FieldDescriptor::Type type) {
-  switch (type) {
-    case FieldDescriptor::TYPE_INT32   : return "TYPE_INT32"   ;
-    case FieldDescriptor::TYPE_UINT32  : return "TYPE_UINT32"  ;
-    case FieldDescriptor::TYPE_SINT32  : return "TYPE_SINT32"  ;
-    case FieldDescriptor::TYPE_FIXED32 : return "TYPE_FIXED32" ;
-    case FieldDescriptor::TYPE_SFIXED32: return "TYPE_SFIXED32";
-    case FieldDescriptor::TYPE_INT64   : return "TYPE_INT64"   ;
-    case FieldDescriptor::TYPE_UINT64  : return "TYPE_UINT64"  ;
-    case FieldDescriptor::TYPE_SINT64  : return "TYPE_SINT64"  ;
-    case FieldDescriptor::TYPE_FIXED64 : return "TYPE_FIXED64" ;
-    case FieldDescriptor::TYPE_SFIXED64: return "TYPE_SFIXED64";
-    case FieldDescriptor::TYPE_FLOAT   : return "TYPE_FLOAT"   ;
-    case FieldDescriptor::TYPE_DOUBLE  : return "TYPE_DOUBLE"  ;
-    case FieldDescriptor::TYPE_BOOL    : return "TYPE_BOOL"    ;
-    case FieldDescriptor::TYPE_STRING  : return "TYPE_STRING"  ;
-    case FieldDescriptor::TYPE_BYTES   : return "TYPE_BYTES"   ;
-    case FieldDescriptor::TYPE_ENUM    : return "TYPE_ENUM"    ;
-    case FieldDescriptor::TYPE_GROUP   : return "TYPE_GROUP"   ;
-    case FieldDescriptor::TYPE_MESSAGE : return "TYPE_MESSAGE" ;
-
-    // No default because we want the compiler to complain if any new
-    // types are added.
-  }
-
-  GOOGLE_LOG(FATAL) << "Can't get here.";
-  return NULL;
-}
-
-}  // namespace
-
-void SetVariables(const FieldDescriptor* descriptor, const Params params,
-                  map<string, string>* variables) {
-  (*variables)["extends"] = ClassName(params, descriptor->containing_type());
-  (*variables)["name"] = RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
-  bool repeated = descriptor->is_repeated();
-  (*variables)["repeated"] = repeated ? "Repeated" : "";
-  (*variables)["type"] = GetTypeConstantName(descriptor->type());
-  JavaType java_type = GetJavaType(descriptor->type());
-  string tag = SimpleItoa(WireFormat::MakeTag(descriptor));
-  if (java_type == JAVATYPE_MESSAGE) {
-    (*variables)["ext_type"] = "MessageTyped";
-    string message_type = ClassName(params, descriptor->message_type());
-    if (repeated) {
-      message_type += "[]";
-    }
-    (*variables)["class"] = message_type;
-    // For message typed extensions, tags_params contains a single tag
-    // for both singular and repeated cases.
-    (*variables)["tag_params"] = tag;
-  } else {
-    (*variables)["ext_type"] = "PrimitiveTyped";
-    if (!repeated) {
-      (*variables)["class"] = BoxedPrimitiveTypeName(java_type);
-      (*variables)["tag_params"] = tag;
-    } else {
-      (*variables)["class"] = PrimitiveTypeName(java_type) + "[]";
-      if (!descriptor->is_packable()) {
-        // Non-packable: nonPackedTag == tag, packedTag == 0
-        (*variables)["tag_params"] = tag + ", " + tag + ", 0";
-      } else if (descriptor->options().packed()) {
-        // Packable and packed: tag == packedTag
-        string non_packed_tag = SimpleItoa(WireFormatLite::MakeTag(
-            descriptor->number(),
-            WireFormat::WireTypeForFieldType(descriptor->type())));
-        (*variables)["tag_params"] = tag + ", " + non_packed_tag + ", " + tag;
-      } else {
-        // Packable and not packed: tag == nonPackedTag
-        string packed_tag = SimpleItoa(WireFormatLite::MakeTag(
-            descriptor->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
-        (*variables)["tag_params"] = tag + ", " + tag + ", " + packed_tag;
-      }
-    }
-  }
-}
-
-ExtensionGenerator::
-ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params)
-  : params_(params), descriptor_(descriptor) {
-  SetVariables(descriptor, params, &variables_);
-}
-
-ExtensionGenerator::~ExtensionGenerator() {}
-
-void ExtensionGenerator::Generate(io::Printer* printer) const {
-  printer->Print("\n");
-  PrintFieldComment(printer, descriptor_);
-  printer->Print(variables_,
-    "public static final com.google.protobuf.nano.Extension<\n"
-    "    $extends$,\n"
-    "    $class$> $name$ =\n"
-    "        com.google.protobuf.nano.Extension.create$repeated$$ext_type$(\n"
-    "            com.google.protobuf.nano.Extension.$type$,\n"
-    "            $class$.class,\n"
-    "            $tag_params$L);\n");
-}
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
-
diff --git a/src/google/protobuf/compiler/javanano/javanano_field.cc b/src/google/protobuf/compiler/javanano/javanano_field.cc
deleted file mode 100644
index 85257f3..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_field.cc
+++ /dev/null
@@ -1,209 +0,0 @@
-// 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)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-
-#include <google/protobuf/compiler/javanano/javanano_field.h>
-#include <google/protobuf/compiler/javanano/javanano_helpers.h>
-#include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
-#include <google/protobuf/compiler/javanano/javanano_enum_field.h>
-#include <google/protobuf/compiler/javanano/javanano_map_field.h>
-#include <google/protobuf/compiler/javanano/javanano_message_field.h>
-#include <google/protobuf/stubs/common.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-FieldGenerator::~FieldGenerator() {}
-
-bool FieldGenerator::SavedDefaultNeeded() const {
-  // No saved default for this field by default.
-  // Subclasses whose instances may need saved defaults will override this
-  // and return the appropriate value.
-  return false;
-}
-
-void FieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const {
-  // No saved default for this field by default.
-  // Subclasses whose instances may need saved defaults will override this
-  // and generate the appropriate init code to the printer.
-}
-
-void FieldGenerator::GenerateMergingCodeFromPacked(io::Printer* printer) const {
-  // Reaching here indicates a bug. Cases are:
-  //   - This FieldGenerator should support packing, but this method should be
-  //     overridden.
-  //   - This FieldGenerator doesn't support packing, and this method should
-  //     never have been called.
-  GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() "
-             << "called on field generator that does not support packing.";
-}
-
-// =============================================
-
-FieldGeneratorMap::FieldGeneratorMap(
-    const Descriptor* descriptor, const Params &params)
-  : descriptor_(descriptor),
-    field_generators_(
-      new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
-
-  int next_has_bit_index = 0;
-  bool saved_defaults_needed = false;
-  // Construct all the FieldGenerators.
-  for (int i = 0; i < descriptor->field_count(); i++) {
-    FieldGenerator* field_generator = MakeGenerator(
-        descriptor->field(i), params, &next_has_bit_index);
-    saved_defaults_needed = saved_defaults_needed
-        || field_generator->SavedDefaultNeeded();
-    field_generators_[i].reset(field_generator);
-  }
-  total_bits_ = next_has_bit_index;
-  saved_defaults_needed_ = saved_defaults_needed;
-}
-
-FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
-    const Params &params, int* next_has_bit_index) {
-  JavaType java_type = GetJavaType(field);
-  if (field->is_repeated()) {
-    switch (java_type) {
-      case JAVATYPE_MESSAGE:
-        if (IsMapEntry(field->message_type())) {
-          return new MapFieldGenerator(field, params);
-        } else {
-          return new RepeatedMessageFieldGenerator(field, params);
-        }
-      case JAVATYPE_ENUM:
-        return new RepeatedEnumFieldGenerator(field, params);
-      default:
-        return new RepeatedPrimitiveFieldGenerator(field, params);
-    }
-  } else if (field->containing_oneof()) {
-    switch (java_type) {
-      case JAVATYPE_MESSAGE:
-        return new MessageOneofFieldGenerator(field, params);
-      case JAVATYPE_ENUM:
-      default:
-        return new PrimitiveOneofFieldGenerator(field, params);
-    }
-  } else if (params.optional_field_accessors() && field->is_optional()
-      && java_type != JAVATYPE_MESSAGE) {
-    // We need a has-bit for each primitive/enum field because their default
-    // values could be same as explicitly set values. But we don't need it
-    // for a message field because they have no defaults and Nano uses 'null'
-    // for unset messages, which cannot be set explicitly.
-    switch (java_type) {
-      case JAVATYPE_ENUM:
-        return new AccessorEnumFieldGenerator(
-            field, params, (*next_has_bit_index)++);
-      default:
-        return new AccessorPrimitiveFieldGenerator(
-            field, params, (*next_has_bit_index)++);
-    }
-  } else {
-    switch (java_type) {
-      case JAVATYPE_MESSAGE:
-        return new MessageFieldGenerator(field, params);
-      case JAVATYPE_ENUM:
-        return new EnumFieldGenerator(field, params);
-      default:
-        return new PrimitiveFieldGenerator(field, params);
-    }
-  }
-}
-
-FieldGeneratorMap::~FieldGeneratorMap() {}
-
-const FieldGenerator& FieldGeneratorMap::get(
-    const FieldDescriptor* field) const {
-  GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
-  return *field_generators_[field->index()];
-}
-
-void SetCommonOneofVariables(const FieldDescriptor* descriptor,
-                             map<string, string>* variables) {
-  (*variables)["oneof_name"] =
-      UnderscoresToCamelCase(descriptor->containing_oneof());
-  (*variables)["oneof_capitalized_name"] =
-      UnderscoresToCapitalizedCamelCase(descriptor->containing_oneof());
-  (*variables)["oneof_index"] =
-      SimpleItoa(descriptor->containing_oneof()->index());
-  (*variables)["set_oneof_case"] =
-      "this." + (*variables)["oneof_name"] +
-      "Case_ = " + SimpleItoa(descriptor->number());
-  (*variables)["clear_oneof_case"] =
-      "this." + (*variables)["oneof_name"] + "Case_ = 0";
-  (*variables)["has_oneof_case"] =
-      "this." + (*variables)["oneof_name"] + "Case_ == " +
-      SimpleItoa(descriptor->number());
-}
-
-void GenerateOneofFieldEquals(const FieldDescriptor* descriptor,
-                              const map<string, string>& variables,
-                              io::Printer* printer) {
-  if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
-    printer->Print(variables,
-      "if (this.has$capitalized_name$()) {\n"
-      "  if (!java.util.Arrays.equals((byte[]) this.$oneof_name$_,\n"
-      "                               (byte[]) other.$oneof_name$_)) {\n"
-      "    return false;\n"
-      "  }\n"
-      "}\n");
-  } else {
-    printer->Print(variables,
-      "if (this.has$capitalized_name$()) {\n"
-      "  if (!this.$oneof_name$_.equals(other.$oneof_name$_)) {\n"
-      "    return false;\n"
-      "  }\n"
-      "}\n");
-  }
-}
-
-void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor,
-                                const map<string, string>& variables,
-                                io::Printer* printer) {
-  if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
-    printer->Print(variables,
-      "result = 31 * result + ($has_oneof_case$\n"
-      "   ? java.util.Arrays.hashCode((byte[]) this.$oneof_name$_) : 0);\n");
-  } else {
-    printer->Print(variables,
-      "result = 31 * result +\n"
-      "  ($has_oneof_case$ ? this.$oneof_name$_.hashCode() : 0);\n");
-  }
-}
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_field.h b/src/google/protobuf/compiler/javanano/javanano_field.h
deleted file mode 100644
index 57c221f..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_field.h
+++ /dev/null
@@ -1,130 +0,0 @@
-// 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)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__
-
-#include <map>
-#include <string>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/compiler/javanano/javanano_params.h>
-
-namespace google {
-namespace protobuf {
-  namespace io {
-    class Printer;             // printer.h
-  }
-}
-
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-class FieldGenerator {
- public:
-  FieldGenerator(const Params& params) : params_(params) {}
-  virtual ~FieldGenerator();
-
-  virtual bool SavedDefaultNeeded() const;
-  virtual void GenerateInitSavedDefaultCode(io::Printer* printer) const;
-
-  // Generates code for Java fields and methods supporting this field.
-  // If this field needs a saved default (SavedDefaultNeeded() is true),
-  // then @lazy_init controls how the static field for that default value
-  // and its initialization code should be generated. If @lazy_init is
-  // true, the static field is not declared final and the initialization
-  // code is generated only when GenerateInitSavedDefaultCode is called;
-  // otherwise, the static field is declared final and initialized inline.
-  // GenerateInitSavedDefaultCode will not be called in the latter case.
-  virtual void GenerateMembers(
-      io::Printer* printer, bool lazy_init) const = 0;
-
-  virtual void GenerateClearCode(io::Printer* printer) const = 0;
-  virtual void GenerateMergingCode(io::Printer* printer) const = 0;
-
-  // Generates code to merge from packed serialized form. The default
-  // implementation will fail; subclasses which can handle packed serialized
-  // forms will override this and print appropriate code to the printer.
-  virtual void GenerateMergingCodeFromPacked(io::Printer* printer) const;
-
-  virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
-  virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
-  virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
-  virtual void GenerateHashCodeCode(io::Printer* printer) const = 0;
-  virtual void GenerateFixClonedCode(io::Printer* printer) const {}
-
- protected:
-  const Params& params_;
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
-};
-
-// Convenience class which constructs FieldGenerators for a Descriptor.
-class FieldGeneratorMap {
- public:
-  explicit FieldGeneratorMap(const Descriptor* descriptor, const Params &params);
-  ~FieldGeneratorMap();
-
-  const FieldGenerator& get(const FieldDescriptor* field) const;
-  int total_bits() const { return total_bits_; }
-  bool saved_defaults_needed() const { return saved_defaults_needed_; }
-
- private:
-  const Descriptor* descriptor_;
-  scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
-  int total_bits_;
-  bool saved_defaults_needed_;
-
-  static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
-      const Params &params, int* next_has_bit_index);
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
-};
-
-void SetCommonOneofVariables(const FieldDescriptor* descriptor,
-                             map<string, string>* variables);
-void GenerateOneofFieldEquals(const FieldDescriptor* descriptor,
-                              const map<string, string>& variables,
-                              io::Printer* printer);
-void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor,
-                                const map<string, string>& variables,
-                                io::Printer* printer);
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-
-}  // namespace google
-#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_file.cc b/src/google/protobuf/compiler/javanano/javanano_file.cc
deleted file mode 100644
index 3676ab9..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_file.cc
+++ /dev/null
@@ -1,263 +0,0 @@
-// 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)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-
-#include <iostream>
-
-#include <google/protobuf/compiler/javanano/javanano_file.h>
-#include <google/protobuf/compiler/javanano/javanano_enum.h>
-#include <google/protobuf/compiler/javanano/javanano_extension.h>
-#include <google/protobuf/compiler/javanano/javanano_helpers.h>
-#include <google/protobuf/compiler/javanano/javanano_message.h>
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/stubs/strutil.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-namespace {
-
-// Recursively searches the given message to see if it contains any extensions.
-bool UsesExtensions(const Message& message) {
-  const Reflection* reflection = message.GetReflection();
-
-  // We conservatively assume that unknown fields are extensions.
-  if (reflection->GetUnknownFields(message).field_count() > 0) return true;
-
-  vector<const FieldDescriptor*> fields;
-  reflection->ListFields(message, &fields);
-
-  for (int i = 0; i < fields.size(); i++) {
-    if (fields[i]->is_extension()) return true;
-
-    if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
-      if (fields[i]->is_repeated()) {
-        int size = reflection->FieldSize(message, fields[i]);
-        for (int j = 0; j < size; j++) {
-          const Message& sub_message =
-            reflection->GetRepeatedMessage(message, fields[i], j);
-          if (UsesExtensions(sub_message)) return true;
-        }
-      } else {
-        const Message& sub_message = reflection->GetMessage(message, fields[i]);
-        if (UsesExtensions(sub_message)) return true;
-      }
-    }
-  }
-
-  return false;
-}
-
-}  // namespace
-
-FileGenerator::FileGenerator(const FileDescriptor* file, const Params& params)
-  : file_(file),
-    params_(params),
-    java_package_(FileJavaPackage(params, file)),
-    classname_(FileClassName(params, file)) {}
-
-FileGenerator::~FileGenerator() {}
-
-bool FileGenerator::Validate(string* error) {
-  // Check for extensions
-  FileDescriptorProto file_proto;
-  file_->CopyTo(&file_proto);
-  if (UsesExtensions(file_proto) && !params_.store_unknown_fields()) {
-    error->assign(file_->name());
-    error->append(
-        ": Java NANO_RUNTIME only supports extensions when the "
-        "'store_unknown_fields' generator option is 'true'.");
-    return false;
-  }
-
-  if (file_->service_count() != 0 && !params_.ignore_services()) {
-    error->assign(file_->name());
-    error->append(
-      ": Java NANO_RUNTIME does not support services\"");
-    return false;
-  }
-
-  if (!IsOuterClassNeeded(params_, file_)) {
-    return true;
-  }
-
-  // Check whether legacy javanano generator would omit the outer class.
-  if (!params_.has_java_outer_classname(file_->name())
-      && file_->message_type_count() == 1
-      && file_->enum_type_count() == 0 && file_->extension_count() == 0) {
-    cout << "INFO: " << file_->name() << ":" << endl;
-    cout << "Javanano generator has changed to align with java generator. "
-        "An outer class will be created for this file and the single message "
-        "in the file will become a nested class. Use java_multiple_files to "
-        "skip generating the outer class, or set an explicit "
-        "java_outer_classname to suppress this message." << endl;
-  }
-
-  // Check that no class name matches the file's class name.  This is a common
-  // problem that leads to Java compile errors that can be hard to understand.
-  // It's especially bad when using the java_multiple_files, since we would
-  // end up overwriting the outer class with one of the inner ones.
-  bool found_conflict = false;
-  for (int i = 0; !found_conflict && i < file_->message_type_count(); i++) {
-    if (file_->message_type(i)->name() == classname_) {
-      found_conflict = true;
-    }
-  }
-  if (params_.java_enum_style()) {
-    for (int i = 0; !found_conflict && i < file_->enum_type_count(); i++) {
-      if (file_->enum_type(i)->name() == classname_) {
-        found_conflict = true;
-      }
-    }
-  }
-  if (found_conflict) {
-    error->assign(file_->name());
-    error->append(
-      ": Cannot generate Java output because the file's outer class name, \"");
-    error->append(classname_);
-    error->append(
-      "\", matches the name of one of the types declared inside it.  "
-      "Please either rename the type or use the java_outer_classname "
-      "option to specify a different outer class name for the .proto file.");
-    return false;
-  }
-  return true;
-}
-
-void FileGenerator::Generate(io::Printer* printer) {
-  // We don't import anything because we refer to all classes by their
-  // fully-qualified names in the generated source.
-  printer->Print(
-    "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n");
-  if (!java_package_.empty()) {
-    printer->Print(
-      "\n"
-      "package $package$;\n",
-      "package", java_package_);
-  }
-
-  // Note: constants (from enums, emitted in the loop below) may have the same names as constants
-  // in the nested classes. This causes Java warnings, but is not fatal, so we suppress those
-  // warnings here in the top-most class declaration.
-  printer->Print(
-    "\n"
-    "@SuppressWarnings(\"hiding\")\n"
-    "public interface $classname$ {\n",
-    "classname", classname_);
-  printer->Indent();
-
-  // -----------------------------------------------------------------
-
-  // Extensions.
-  for (int i = 0; i < file_->extension_count(); i++) {
-    ExtensionGenerator(file_->extension(i), params_).Generate(printer);
-  }
-
-  // Enums.
-  for (int i = 0; i < file_->enum_type_count(); i++) {
-    EnumGenerator(file_->enum_type(i), params_).Generate(printer);
-  }
-
-  // Messages.
-  if (!params_.java_multiple_files(file_->name())) {
-    for (int i = 0; i < file_->message_type_count(); i++) {
-      MessageGenerator(file_->message_type(i), params_).Generate(printer);
-    }
-  }
-
-  // Static variables.
-  for (int i = 0; i < file_->message_type_count(); i++) {
-    // TODO(kenton):  Reuse MessageGenerator objects?
-    MessageGenerator(file_->message_type(i), params_).GenerateStaticVariables(printer);
-  }
-
-  printer->Outdent();
-  printer->Print(
-    "}\n");
-}
-
-template<typename GeneratorClass, typename DescriptorClass>
-static void GenerateSibling(const string& package_dir,
-                            const string& java_package,
-                            const DescriptorClass* descriptor,
-                            GeneratorContext* output_directory,
-                            vector<string>* file_list,
-                            const Params& params) {
-  string filename = package_dir + descriptor->name() + ".java";
-  file_list->push_back(filename);
-
-  scoped_ptr<io::ZeroCopyOutputStream> output(
-    output_directory->Open(filename));
-  io::Printer printer(output.get(), '$');
-
-  printer.Print(
-    "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n");
-  if (!java_package.empty()) {
-    printer.Print(
-      "\n"
-      "package $package$;\n",
-      "package", java_package);
-  }
-
-  GeneratorClass(descriptor, params).Generate(&printer);
-}
-
-void FileGenerator::GenerateSiblings(const string& package_dir,
-                                     GeneratorContext* output_directory,
-                                     vector<string>* file_list) {
-  if (params_.java_multiple_files(file_->name())) {
-    for (int i = 0; i < file_->message_type_count(); i++) {
-      GenerateSibling<MessageGenerator>(package_dir, java_package_,
-                                        file_->message_type(i),
-                                        output_directory, file_list, params_);
-    }
-
-    if (params_.java_enum_style()) {
-      for (int i = 0; i < file_->enum_type_count(); i++) {
-        GenerateSibling<EnumGenerator>(package_dir, java_package_,
-                                       file_->enum_type(i),
-                                       output_directory, file_list, params_);
-      }
-    }
-  }
-}
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_file.h b/src/google/protobuf/compiler/javanano/javanano_file.h
deleted file mode 100644
index 217eafe..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_file.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// 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)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_FILE_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_FILE_H__
-
-#include <string>
-#include <vector>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/javanano/javanano_params.h>
-
-namespace google {
-namespace protobuf {
-  class FileDescriptor;        // descriptor.h
-  namespace io {
-    class Printer;             // printer.h
-  }
-  namespace compiler {
-    class GeneratorContext;     // code_generator.h
-  }
-}
-
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-class FileGenerator {
- public:
-  explicit FileGenerator(const FileDescriptor* file, const Params& params);
-  ~FileGenerator();
-
-  // Checks for problems that would otherwise lead to cryptic compile errors.
-  // Returns true if there are no problems, or writes an error description to
-  // the given string and returns false otherwise.
-  bool Validate(string* error);
-
-  void Generate(io::Printer* printer);
-
-  // If we aren't putting everything into one file, this will write all the
-  // files other than the outer file (i.e. one for each message, enum, and
-  // service type).
-  void GenerateSiblings(const string& package_dir,
-                        GeneratorContext* output_directory,
-                        vector<string>* file_list);
-
-  const string& java_package() { return java_package_; }
-  const string& classname()    { return classname_;    }
-
- private:
-  const FileDescriptor* file_;
-  const Params& params_;
-  string java_package_;
-  string classname_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
-};
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-
-}  // namespace google
-#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_FILE_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc
deleted file mode 100644
index a33eba1..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_generator.cc
+++ /dev/null
@@ -1,232 +0,0 @@
-// 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)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-
-#include <google/protobuf/compiler/javanano/javanano_params.h>
-#include <google/protobuf/compiler/javanano/javanano_generator.h>
-#include <google/protobuf/compiler/javanano/javanano_file.h>
-#include <google/protobuf/compiler/javanano/javanano_helpers.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/stubs/strutil.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-namespace {
-
-string TrimString(const string& s) {
-  string::size_type start = s.find_first_not_of(" \n\r\t");
-  if (start == string::npos) {
-    return "";
-  }
-  string::size_type end = s.find_last_not_of(" \n\r\t") + 1;
-  return s.substr(start, end - start);
-}
-
-} // namespace
-
-void UpdateParamsRecursively(Params& params,
-    const FileDescriptor* file) {
-  // Add any parameters for this file
-  if (file->options().has_java_outer_classname()) {
-    params.set_java_outer_classname(
-      file->name(), file->options().java_outer_classname());
-  }
-  if (file->options().has_java_package()) {
-    string result = file->options().java_package();
-    if (!file->options().javanano_use_deprecated_package()) {
-      if (!result.empty()) {
-        result += ".";
-      }
-      result += "nano";
-    }
-    params.set_java_package(
-      file->name(), result);
-  }
-  if (file->options().has_java_multiple_files()) {
-    params.set_java_multiple_files(
-      file->name(), file->options().java_multiple_files());
-  }
-
-  // Loop through all dependent files recursively
-  // adding dep
-  for (int i = 0; i < file->dependency_count(); i++) {
-    UpdateParamsRecursively(params, file->dependency(i));
-  }
-}
-
-JavaNanoGenerator::JavaNanoGenerator() {}
-JavaNanoGenerator::~JavaNanoGenerator() {}
-
-bool JavaNanoGenerator::Generate(const FileDescriptor* file,
-                             const string& parameter,
-                             GeneratorContext* output_directory,
-                             string* error) const {
-  vector<pair<string, string> > options;
-
-  ParseGeneratorParameter(parameter, &options);
-
-  // -----------------------------------------------------------------
-  // parse generator options
-
-  // Name a file where we will write a list of generated file names, one
-  // per line.
-  string output_list_file;
-  Params params(file->name());
-
-  // Update per file params
-  UpdateParamsRecursively(params, file);
-
-  // Replace any existing options with ones from command line
-  for (int i = 0; i < options.size(); i++) {
-    string option_name = TrimString(options[i].first);
-    string option_value = TrimString(options[i].second);
-    if (option_name == "output_list_file") {
-      output_list_file = option_value;
-    } else if (option_name == "java_package") {
-        vector<string> parts;
-        SplitStringUsing(option_value, "|", &parts);
-        if (parts.size() != 2) {
-          *error = "Bad java_package, expecting filename|PackageName found '"
-            + option_value + "'";
-          return false;
-        }
-        params.set_java_package(parts[0], parts[1]);
-    } else if (option_name == "java_outer_classname") {
-        vector<string> parts;
-        SplitStringUsing(option_value, "|", &parts);
-        if (parts.size() != 2) {
-          *error = "Bad java_outer_classname, "
-                   "expecting filename|ClassName found '"
-                   + option_value + "'";
-          return false;
-        }
-        params.set_java_outer_classname(parts[0], parts[1]);
-    } else if (option_name == "store_unknown_fields") {
-      params.set_store_unknown_fields(option_value == "true");
-    } else if (option_name == "java_multiple_files") {
-      params.set_override_java_multiple_files(option_value == "true");
-    } else if (option_name == "java_nano_generate_has") {
-      params.set_generate_has(option_value == "true");
-    } else if (option_name == "enum_style") {
-      params.set_java_enum_style(option_value == "java");
-    } else if (option_name == "optional_field_style") {
-      params.set_optional_field_accessors(option_value == "accessors");
-      params.set_use_reference_types_for_primitives(option_value == "reftypes"
-          || option_value == "reftypes_compat_mode");
-      params.set_reftypes_primitive_enums(
-          option_value == "reftypes_compat_mode");
-      if (option_value == "reftypes_compat_mode") {
-        params.set_generate_clear(false);
-      }
-    } else if (option_name == "generate_equals") {
-      params.set_generate_equals(option_value == "true");
-    } else if (option_name == "ignore_services") {
-      params.set_ignore_services(option_value == "true");
-    } else if (option_name == "parcelable_messages") {
-      params.set_parcelable_messages(option_value == "true");
-    } else if (option_name == "generate_clone") {
-      params.set_generate_clone(option_value == "true");
-    } else if (option_name == "generate_intdefs") {
-      params.set_generate_intdefs(option_value == "true");
-    } else if (option_name == "generate_clear") {
-      params.set_generate_clear(option_value == "true");
-    } else {
-      *error = "Ignore unknown javanano generator option: " + option_name;
-    }
-  }
-
-  // Check illegal parameter combinations
-  // Note: the enum-like optional_field_style generator param ensures
-  // that we can never have illegal combinations of field styles
-  // (e.g. reftypes and accessors can't be on at the same time).
-  if (params.generate_has()
-      && (params.optional_field_accessors()
-          || params.use_reference_types_for_primitives())) {
-    error->assign("java_nano_generate_has=true cannot be used in conjunction"
-        " with optional_field_style=accessors or optional_field_style=reftypes");
-    return false;
-  }
-
-  // -----------------------------------------------------------------
-
-  FileGenerator file_generator(file, params);
-  if (!file_generator.Validate(error)) {
-    return false;
-  }
-
-  string package_dir =
-    StringReplace(file_generator.java_package(), ".", "/", true);
-  if (!package_dir.empty()) package_dir += "/";
-
-  vector<string> all_files;
-
-  if (IsOuterClassNeeded(params, file)) {
-    string java_filename = package_dir;
-    java_filename += file_generator.classname();
-    java_filename += ".java";
-    all_files.push_back(java_filename);
-
-    // Generate main java file.
-    scoped_ptr<io::ZeroCopyOutputStream> output(
-      output_directory->Open(java_filename));
-    io::Printer printer(output.get(), '$');
-    file_generator.Generate(&printer);
-  }
-
-  // Generate sibling files.
-  file_generator.GenerateSiblings(package_dir, output_directory, &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));
-    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]);
-    }
-  }
-
-  return true;
-}
-
-}  // namespace java
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.h b/src/google/protobuf/compiler/javanano/javanano_generator.h
deleted file mode 100644
index 6f9f7f2..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_generator.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// 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)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// Generates Java nano code for a given .proto file.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_NANO_GENERATOR_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_NANO_GENERATOR_H__
-
-#include <string>
-#include <google/protobuf/compiler/code_generator.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-// CodeGenerator implementation which generates Java nano code.  If you create your
-// own protocol compiler binary and you want it to support Java output for the
-// nano runtime, you can do so by registering an instance of this CodeGenerator with
-// the CommandLineInterface in your main() function.
-class LIBPROTOC_EXPORT JavaNanoGenerator : public CodeGenerator {
- public:
-  JavaNanoGenerator();
-  ~JavaNanoGenerator();
-
-  // implements CodeGenerator ----------------------------------------
-  bool Generate(const FileDescriptor* file,
-                const string& parameter,
-                GeneratorContext* output_directory,
-                string* error) const;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaNanoGenerator);
-};
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-
-}  // namespace google
-#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_NANO_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
deleted file mode 100644
index 5465655..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc
+++ /dev/null
@@ -1,593 +0,0 @@
-// 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)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-
-#include <limits>
-#include <vector>
-
-#include <google/protobuf/compiler/javanano/javanano_helpers.h>
-#include <google/protobuf/compiler/javanano/javanano_params.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/stubs/hash.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-const char kThickSeparator[] =
-  "// ===================================================================\n";
-const char kThinSeparator[] =
-  "// -------------------------------------------------------------------\n";
-
-class RenameKeywords {
- private:
-  hash_set<string> java_keywords_set_;
-
- public:
-  RenameKeywords() {
-    static const char* kJavaKeywordsList[] = {
-      // Reserved Java Keywords
-      "abstract", "assert", "boolean", "break", "byte", "case", "catch",
-      "char", "class", "const", "continue", "default", "do", "double", "else",
-      "enum", "extends", "final", "finally", "float", "for", "goto", "if",
-      "implements", "import", "instanceof", "int", "interface", "long",
-      "native", "new", "package", "private", "protected", "public", "return",
-      "short", "static", "strictfp", "super", "switch", "synchronized",
-      "this", "throw", "throws", "transient", "try", "void", "volatile", "while",
-
-      // Reserved Keywords for Literals
-      "false", "null", "true"
-    };
-
-    for (int i = 0; i < GOOGLE_ARRAYSIZE(kJavaKeywordsList); i++) {
-      java_keywords_set_.insert(kJavaKeywordsList[i]);
-    }
-  }
-
-  // Used to rename the a field name if it's a java keyword.  Specifically
-  // this is used to rename the ["name"] or ["capitalized_name"] field params.
-  // (http://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html)
-  string RenameJavaKeywordsImpl(const string& input) {
-    string result = input;
-
-    if (java_keywords_set_.find(result) != java_keywords_set_.end()) {
-      result += "_";
-    }
-
-    return result;
-  }
-
-};
-
-static RenameKeywords sRenameKeywords;
-
-namespace {
-
-const char* kDefaultPackage = "";
-
-const string& FieldName(const FieldDescriptor* field) {
-  // Groups are hacky:  The name of the field is just the lower-cased name
-  // of the group type.  In Java, though, we would like to retain the original
-  // capitalization of the type name.
-  if (field->type() == FieldDescriptor::TYPE_GROUP) {
-    return field->message_type()->name();
-  } else {
-    return field->name();
-  }
-}
-
-string UnderscoresToCamelCaseImpl(const string& input, bool cap_next_letter) {
-  string result;
-  // Note:  I distrust ctype.h due to locales.
-  for (int i = 0; i < input.size(); i++) {
-    if ('a' <= input[i] && input[i] <= 'z') {
-      if (cap_next_letter) {
-        result += input[i] + ('A' - 'a');
-      } else {
-        result += input[i];
-      }
-      cap_next_letter = false;
-    } else if ('A' <= input[i] && input[i] <= 'Z') {
-      if (i == 0 && !cap_next_letter) {
-        // Force first letter to lower-case unless explicitly told to
-        // capitalize it.
-        result += input[i] + ('a' - 'A');
-      } else {
-        // Capital letters after the first are left as-is.
-        result += input[i];
-      }
-      cap_next_letter = false;
-    } else if ('0' <= input[i] && input[i] <= '9') {
-      result += input[i];
-      cap_next_letter = true;
-    } else {
-      cap_next_letter = true;
-    }
-  }
-  return result;
-}
-
-}  // namespace
-
-string UnderscoresToCamelCase(const FieldDescriptor* field) {
-  return UnderscoresToCamelCaseImpl(FieldName(field), false);
-}
-
-string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
-  return UnderscoresToCamelCaseImpl(FieldName(field), true);
-}
-
-string UnderscoresToCamelCase(const MethodDescriptor* method) {
-  return UnderscoresToCamelCaseImpl(method->name(), false);
-}
-
-string UnderscoresToCamelCase(const OneofDescriptor* oneof) {
-  return UnderscoresToCamelCaseImpl(oneof->name(), false);
-}
-
-string UnderscoresToCapitalizedCamelCase(const OneofDescriptor* oneof) {
-  return UnderscoresToCamelCaseImpl(oneof->name(), true);
-}
-
-string RenameJavaKeywords(const string& input) {
-  return sRenameKeywords.RenameJavaKeywordsImpl(input);
-}
-
-string StripProto(const string& filename) {
-  if (HasSuffixString(filename, ".protodevel")) {
-    return StripSuffixString(filename, ".protodevel");
-  } else {
-    return StripSuffixString(filename, ".proto");
-  }
-}
-
-string FileClassName(const Params& params, const FileDescriptor* file) {
-  if (params.has_java_outer_classname(file->name())) {
-    return params.java_outer_classname(file->name());
-  } else {
-    // Use the filename itself with underscores removed
-    // and a CamelCase style name.
-    string basename;
-    string::size_type last_slash = file->name().find_last_of('/');
-    if (last_slash == string::npos) {
-      basename = file->name();
-    } else {
-      basename = file->name().substr(last_slash + 1);
-    }
-    return UnderscoresToCamelCaseImpl(StripProto(basename), true);
-  }
-}
-
-string FileJavaPackage(const Params& params, const FileDescriptor* file) {
-  if (params.has_java_package(file->name())) {
-    return params.java_package(file->name());
-  } else {
-    string result = kDefaultPackage;
-    if (!file->package().empty()) {
-      if (!result.empty()) result += '.';
-      result += file->package();
-    }
-
-    if (!file->options().javanano_use_deprecated_package()) {
-      if (!result.empty()) {
-        result += ".";
-      }
-      result += "nano";
-    }
-
-    return result;
-  }
-}
-
-bool IsOuterClassNeeded(const Params& params, const FileDescriptor* file) {
-  // If java_multiple_files is false, the outer class is always needed.
-  if (!params.java_multiple_files(file->name())) {
-    return true;
-  }
-
-  // File-scope extensions need the outer class as the scope.
-  if (file->extension_count() != 0) {
-    return true;
-  }
-
-  // If container interfaces are not generated, file-scope enums need the
-  // outer class as the scope.
-  if (file->enum_type_count() != 0 && !params.java_enum_style()) {
-    return true;
-  }
-
-  return false;
-}
-
-string ToJavaName(const Params& params, const string& name, bool is_class,
-    const Descriptor* parent, const FileDescriptor* file) {
-  string result;
-  if (parent != NULL) {
-    result.append(ClassName(params, parent));
-  } else if (is_class && params.java_multiple_files(file->name())) {
-    result.append(FileJavaPackage(params, file));
-  } else {
-    result.append(ClassName(params, file));
-  }
-  if (!result.empty()) result.append(1, '.');
-  result.append(RenameJavaKeywords(name));
-  return result;
-}
-
-string ClassName(const Params& params, const FileDescriptor* descriptor) {
-  string result = FileJavaPackage(params, descriptor);
-  if (!result.empty()) result += '.';
-  result += FileClassName(params, descriptor);
-  return result;
-}
-
-string ClassName(const Params& params, const EnumDescriptor* descriptor) {
-  const Descriptor* parent = descriptor->containing_type();
-  // When using Java enum style, an enum's class name contains the enum name.
-  // Use the standard ToJavaName translation.
-  if (params.java_enum_style()) {
-    return ToJavaName(params, descriptor->name(), true, parent,
-                      descriptor->file());
-  }
-  // Otherwise the enum members are accessed from the enclosing class.
-  if (parent != NULL) {
-    return ClassName(params, parent);
-  } else {
-    return ClassName(params, descriptor->file());
-  }
-}
-
-string FieldConstantName(const FieldDescriptor *field) {
-  string name = field->name() + "_FIELD_NUMBER";
-  UpperString(&name);
-  return name;
-}
-
-string FieldDefaultConstantName(const FieldDescriptor *field) {
-  return "_" + RenameJavaKeywords(UnderscoresToCamelCase(field)) + "Default";
-}
-
-void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) {
-  // We don't want to print group bodies so we cut off after the first line
-  // (the second line for extensions).
-  string def = field->DebugString();
-  string::size_type first_line_end = def.find_first_of('\n');
-  printer->Print("// $def$\n",
-    "def", def.substr(0, first_line_end));
-  if (field->is_extension()) {
-    string::size_type second_line_start = first_line_end + 1;
-    string::size_type second_line_length =
-        def.find('\n', second_line_start) - second_line_start;
-    printer->Print("// $def$\n",
-      "def", def.substr(second_line_start, second_line_length));
-  }
-}
-
-JavaType GetJavaType(FieldDescriptor::Type field_type) {
-  switch (field_type) {
-    case FieldDescriptor::TYPE_INT32:
-    case FieldDescriptor::TYPE_UINT32:
-    case FieldDescriptor::TYPE_SINT32:
-    case FieldDescriptor::TYPE_FIXED32:
-    case FieldDescriptor::TYPE_SFIXED32:
-      return JAVATYPE_INT;
-
-    case FieldDescriptor::TYPE_INT64:
-    case FieldDescriptor::TYPE_UINT64:
-    case FieldDescriptor::TYPE_SINT64:
-    case FieldDescriptor::TYPE_FIXED64:
-    case FieldDescriptor::TYPE_SFIXED64:
-      return JAVATYPE_LONG;
-
-    case FieldDescriptor::TYPE_FLOAT:
-      return JAVATYPE_FLOAT;
-
-    case FieldDescriptor::TYPE_DOUBLE:
-      return JAVATYPE_DOUBLE;
-
-    case FieldDescriptor::TYPE_BOOL:
-      return JAVATYPE_BOOLEAN;
-
-    case FieldDescriptor::TYPE_STRING:
-      return JAVATYPE_STRING;
-
-    case FieldDescriptor::TYPE_BYTES:
-      return JAVATYPE_BYTES;
-
-    case FieldDescriptor::TYPE_ENUM:
-      return JAVATYPE_ENUM;
-
-    case FieldDescriptor::TYPE_GROUP:
-    case FieldDescriptor::TYPE_MESSAGE:
-      return JAVATYPE_MESSAGE;
-
-    // No default because we want the compiler to complain if any new
-    // types are added.
-  }
-
-  GOOGLE_LOG(FATAL) << "Can't get here.";
-  return JAVATYPE_INT;
-}
-
-string PrimitiveTypeName(JavaType type) {
-  switch (type) {
-    case JAVATYPE_INT    : return "int";
-    case JAVATYPE_LONG   : return "long";
-    case JAVATYPE_FLOAT  : return "float";
-    case JAVATYPE_DOUBLE : return "double";
-    case JAVATYPE_BOOLEAN: return "boolean";
-    case JAVATYPE_STRING : return "java.lang.String";
-    case JAVATYPE_BYTES  : return "byte[]";
-    case JAVATYPE_ENUM   : return "int";
-    case JAVATYPE_MESSAGE: return "";
-
-    // No default because we want the compiler to complain if any new
-    // JavaTypes are added.
-  }
-
-  GOOGLE_LOG(FATAL) << "Can't get here.";
-  return "";
-}
-
-string BoxedPrimitiveTypeName(JavaType type) {
-  switch (type) {
-    case JAVATYPE_INT    : return "java.lang.Integer";
-    case JAVATYPE_LONG   : return "java.lang.Long";
-    case JAVATYPE_FLOAT  : return "java.lang.Float";
-    case JAVATYPE_DOUBLE : return "java.lang.Double";
-    case JAVATYPE_BOOLEAN: return "java.lang.Boolean";
-    case JAVATYPE_STRING : return "java.lang.String";
-    case JAVATYPE_BYTES  : return "byte[]";
-    case JAVATYPE_ENUM   : return "java.lang.Integer";
-    case JAVATYPE_MESSAGE: return "";
-
-    // No default because we want the compiler to complain if any new
-    // JavaTypes are added.
-  }
-
-  GOOGLE_LOG(FATAL) << "Can't get here.";
-  return "";
-}
-
-string EmptyArrayName(const Params& params, const FieldDescriptor* field) {
-  switch (GetJavaType(field)) {
-    case JAVATYPE_INT    : return "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
-    case JAVATYPE_LONG   : return "com.google.protobuf.nano.WireFormatNano.EMPTY_LONG_ARRAY";
-    case JAVATYPE_FLOAT  : return "com.google.protobuf.nano.WireFormatNano.EMPTY_FLOAT_ARRAY";
-    case JAVATYPE_DOUBLE : return "com.google.protobuf.nano.WireFormatNano.EMPTY_DOUBLE_ARRAY";
-    case JAVATYPE_BOOLEAN: return "com.google.protobuf.nano.WireFormatNano.EMPTY_BOOLEAN_ARRAY";
-    case JAVATYPE_STRING : return "com.google.protobuf.nano.WireFormatNano.EMPTY_STRING_ARRAY";
-    case JAVATYPE_BYTES  : return "com.google.protobuf.nano.WireFormatNano.EMPTY_BYTES_ARRAY";
-    case JAVATYPE_ENUM   : return "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
-    case JAVATYPE_MESSAGE: return ClassName(params, field->message_type()) + ".EMPTY_ARRAY";
-
-    // No default because we want the compiler to complain if any new
-    // JavaTypes are added.
-  }
-
-  GOOGLE_LOG(FATAL) << "Can't get here.";
-  return "";
-}
-
-string DefaultValue(const Params& params, const FieldDescriptor* field) {
-  if (field->label() == FieldDescriptor::LABEL_REPEATED) {
-    return EmptyArrayName(params, field);
-  }
-
-  if (params.use_reference_types_for_primitives()) {
-    if (params.reftypes_primitive_enums()
-          && field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
-      return "Integer.MIN_VALUE";
-    }
-    return "null";
-  }
-
-  // Switch on cpp_type since we need to know which default_value_* method
-  // of FieldDescriptor to call.
-  switch (field->cpp_type()) {
-    case FieldDescriptor::CPPTYPE_INT32:
-      return SimpleItoa(field->default_value_int32());
-    case FieldDescriptor::CPPTYPE_UINT32:
-      // Need to print as a signed int since Java has no unsigned.
-      return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
-    case FieldDescriptor::CPPTYPE_INT64:
-      return SimpleItoa(field->default_value_int64()) + "L";
-    case FieldDescriptor::CPPTYPE_UINT64:
-      return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
-             "L";
-    case FieldDescriptor::CPPTYPE_DOUBLE: {
-      double value = field->default_value_double();
-      if (value == numeric_limits<double>::infinity()) {
-        return "Double.POSITIVE_INFINITY";
-      } else if (value == -numeric_limits<double>::infinity()) {
-        return "Double.NEGATIVE_INFINITY";
-      } else if (value != value) {
-        return "Double.NaN";
-      } else {
-        return SimpleDtoa(value) + "D";
-      }
-    }
-    case FieldDescriptor::CPPTYPE_FLOAT: {
-      float value = field->default_value_float();
-      if (value == numeric_limits<float>::infinity()) {
-        return "Float.POSITIVE_INFINITY";
-      } else if (value == -numeric_limits<float>::infinity()) {
-        return "Float.NEGATIVE_INFINITY";
-      } else if (value != value) {
-        return "Float.NaN";
-      } else {
-        return SimpleFtoa(value) + "F";
-      }
-    }
-    case FieldDescriptor::CPPTYPE_BOOL:
-      return field->default_value_bool() ? "true" : "false";
-    case FieldDescriptor::CPPTYPE_STRING:
-      if (!field->default_value_string().empty()) {
-        // Point it to the static final in the generated code.
-        return FieldDefaultConstantName(field);
-      } else {
-        if (field->type() == FieldDescriptor::TYPE_BYTES) {
-          return "com.google.protobuf.nano.WireFormatNano.EMPTY_BYTES";
-        } else {
-          return "\"\"";
-        }
-      }
-
-    case FieldDescriptor::CPPTYPE_ENUM:
-      return ClassName(params, field->enum_type()) + "." +
-             RenameJavaKeywords(field->default_value_enum()->name());
-
-    case FieldDescriptor::CPPTYPE_MESSAGE:
-      return "null";
-
-    // No default because we want the compiler to complain if any new
-    // types are added.
-  }
-
-  GOOGLE_LOG(FATAL) << "Can't get here.";
-  return "";
-}
-
-
-static const char* kBitMasks[] = {
-  "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 var_name = "bitField";
-  var_name += SimpleItoa(index);
-  var_name += "_";
-  return var_name;
-}
-
-string GetBitFieldNameForBit(int bit_index) {
-  return GetBitFieldName(bit_index / 32);
-}
-
-string GenerateGetBit(int bit_index) {
-  string var_name = GetBitFieldNameForBit(bit_index);
-  int bit_in_var_index = bit_index % 32;
-
-  string mask = kBitMasks[bit_in_var_index];
-  string result = "((" + var_name + " & " + mask + ") != 0)";
-  return result;
-}
-
-string GenerateSetBit(int bit_index) {
-  string var_name = GetBitFieldNameForBit(bit_index);
-  int bit_in_var_index = bit_index % 32;
-
-  string mask = kBitMasks[bit_in_var_index];
-  string result = var_name + " |= " + mask;
-  return result;
-}
-
-string GenerateClearBit(int bit_index) {
-  string var_name = GetBitFieldNameForBit(bit_index);
-  int bit_in_var_index = bit_index % 32;
-
-  string mask = kBitMasks[bit_in_var_index];
-  string result = var_name + " = (" + var_name + " & ~" + mask + ")";
-  return result;
-}
-
-string GenerateDifferentBit(int bit_index) {
-  string var_name = GetBitFieldNameForBit(bit_index);
-  int bit_in_var_index = bit_index % 32;
-
-  string mask = kBitMasks[bit_in_var_index];
-  string result = "((" + var_name + " & " + mask
-      + ") != (other." + var_name + " & " + mask + "))";
-  return result;
-}
-
-void SetBitOperationVariables(const string name,
-    int bitIndex, map<string, string>* variables) {
-  (*variables)["get_" + name] = GenerateGetBit(bitIndex);
-  (*variables)["set_" + name] = GenerateSetBit(bitIndex);
-  (*variables)["clear_" + name] = GenerateClearBit(bitIndex);
-  (*variables)["different_" + name] = GenerateDifferentBit(bitIndex);
-}
-
-bool HasMapField(const Descriptor* descriptor) {
-  for (int i = 0; i < descriptor->field_count(); ++i) {
-    const FieldDescriptor* field = descriptor->field(i);
-    if (field->type() == FieldDescriptor::TYPE_MESSAGE &&
-        IsMapEntry(field->message_type())) {
-      return true;
-    }
-  }
-  return false;
-}
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.h b/src/google/protobuf/compiler/javanano/javanano_helpers.h
deleted file mode 100644
index 014c85a..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_helpers.h
+++ /dev/null
@@ -1,199 +0,0 @@
-// 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)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_HELPERS_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_HELPERS_H__
-
-#include <string>
-#include <google/protobuf/compiler/javanano/javanano_params.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/printer.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-// Commonly-used separator comments.  Thick is a line of '=', thin is a line
-// of '-'.
-extern const char kThickSeparator[];
-extern const char kThinSeparator[];
-
-// Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes
-// "fooBarBaz" or "FooBarBaz", respectively.
-string UnderscoresToCamelCase(const FieldDescriptor* field);
-string UnderscoresToCamelCase(const OneofDescriptor* oneof);
-string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field);
-string UnderscoresToCapitalizedCamelCase(const OneofDescriptor* oneof);
-
-// Appends an "_" to the end of a field where the name is a reserved java
-// keyword.  For example int32 public = 1 will generate int public_.
-string RenameJavaKeywords(const string& input);
-
-// Similar, but for method names.  (Typically, this merely has the effect
-// of lower-casing the first letter of the name.)
-string UnderscoresToCamelCase(const MethodDescriptor* method);
-
-// Strips ".proto" or ".protodevel" from the end of a filename.
-string StripProto(const string& filename);
-
-// Gets the unqualified class name for the file.  Each .proto file becomes a
-// single Java class, with all its contents nested in that class.
-string FileClassName(const Params& params, const FileDescriptor* file);
-
-// Returns the file's Java package name.
-string FileJavaPackage(const Params& params, const FileDescriptor* file);
-
-// Returns whether the Java outer class is needed, i.e. whether the option
-// java_multiple_files is false, or the proto file contains any file-scope
-// enums/extensions.
-bool IsOuterClassNeeded(const Params& params, const FileDescriptor* file);
-
-// Converts the given simple name of a proto entity to its fully-qualified name
-// in the Java namespace, given that it is in the given file enclosed in the
-// given parent message (or NULL for file-scope entities). Whether the file's
-// outer class name should be included in the return value depends on factors
-// inferrable from the given arguments, including is_class which indicates
-// whether the entity translates to a Java class.
-string ToJavaName(const Params& params, const string& name, bool is_class,
-    const Descriptor* parent, const FileDescriptor* file);
-
-// These return the fully-qualified class name corresponding to the given
-// descriptor.
-inline string ClassName(const Params& params, const Descriptor* descriptor) {
-  return ToJavaName(params, descriptor->name(), true,
-                    descriptor->containing_type(), descriptor->file());
-}
-string ClassName(const Params& params, const EnumDescriptor* descriptor);
-inline string ClassName(const Params& params,
-    const ServiceDescriptor* descriptor) {
-  return ToJavaName(params, descriptor->name(), true, NULL, descriptor->file());
-}
-inline string ExtensionIdentifierName(const Params& params,
-    const FieldDescriptor* descriptor) {
-  return ToJavaName(params, descriptor->name(), false,
-                    descriptor->extension_scope(), descriptor->file());
-}
-string ClassName(const Params& params, const FileDescriptor* descriptor);
-
-// Get the unqualified name that should be used for a field's field
-// number constant.
-string FieldConstantName(const FieldDescriptor *field);
-
-string FieldDefaultConstantName(const FieldDescriptor *field);
-
-// Print the field's proto-syntax definition as a comment.
-void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field);
-
-enum JavaType {
-  JAVATYPE_INT,
-  JAVATYPE_LONG,
-  JAVATYPE_FLOAT,
-  JAVATYPE_DOUBLE,
-  JAVATYPE_BOOLEAN,
-  JAVATYPE_STRING,
-  JAVATYPE_BYTES,
-  JAVATYPE_ENUM,
-  JAVATYPE_MESSAGE
-};
-
-JavaType GetJavaType(FieldDescriptor::Type field_type);
-
-inline JavaType GetJavaType(const FieldDescriptor* field) {
-  return GetJavaType(field->type());
-}
-
-string PrimitiveTypeName(JavaType type);
-
-// Get the fully-qualified class name for a boxed primitive type, e.g.
-// "java.lang.Integer" for JAVATYPE_INT.  Returns NULL for enum and message
-// types.
-string BoxedPrimitiveTypeName(JavaType type);
-
-string EmptyArrayName(const Params& params, const FieldDescriptor* field);
-
-string DefaultValue(const Params& params, const FieldDescriptor* field);
-
-
-// Methods for shared bitfields.
-
-// Gets the name of the shared bitfield for the given field index.
-string GetBitFieldName(int index);
-
-// Gets the name of the shared bitfield for the given bit index.
-// Effectively, GetBitFieldName(bit_index / 32)
-string GetBitFieldNameForBit(int bit_index);
-
-// Generates the java code for the expression that returns whether the bit at
-// the given bit index is set.
-// Example: "((bitField1_ & 0x04000000) != 0)"
-string GenerateGetBit(int bit_index);
-
-// Generates the java code for the expression that sets the bit at the given
-// bit index.
-// Example: "bitField1_ |= 0x04000000"
-string GenerateSetBit(int bit_index);
-
-// Generates the java code for the expression that clears the bit at the given
-// bit index.
-// Example: "bitField1_ = (bitField1_ & ~0x04000000)"
-string GenerateClearBit(int bit_index);
-
-// Generates the java code for the expression that returns whether the bit at
-// the given bit index contains different values in the current object and
-// another object accessible via the variable 'other'.
-// Example: "((bitField1_ & 0x04000000) != (other.bitField1_ & 0x04000000))"
-string GenerateDifferentBit(int bit_index);
-
-// Sets the 'get_*', 'set_*', 'clear_*' and 'different_*' variables, where * is
-// the given name of the bit, to the appropriate Java expressions for the given
-// bit index.
-void SetBitOperationVariables(const string name,
-    int bitIndex, map<string, string>* variables);
-
-inline bool IsMapEntry(const Descriptor* descriptor) {
-  // TODO(liujisi): Add an option to turn on maps for proto2 syntax as well.
-  return descriptor->options().map_entry() &&
-      descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
-}
-
-bool HasMapField(const Descriptor* descriptor);
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-
-}  // namespace google
-#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_HELPERS_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.cc b/src/google/protobuf/compiler/javanano/javanano_map_field.cc
deleted file mode 100644
index 83b2b0c..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_map_field.cc
+++ /dev/null
@@ -1,186 +0,0 @@
-// 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.
-
-#include <google/protobuf/compiler/javanano/javanano_map_field.h>
-#include <google/protobuf/compiler/javanano/javanano_helpers.h>
-#include <google/protobuf/stubs/common.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 javanano {
-
-namespace {
-
-string TypeName(const Params& params, const FieldDescriptor* field,
-                bool boxed) {
-  JavaType java_type = GetJavaType(field);
-  switch (java_type) {
-    case JAVATYPE_MESSAGE:
-      return ClassName(params, field->message_type());
-    case JAVATYPE_INT:
-    case JAVATYPE_LONG:
-    case JAVATYPE_FLOAT:
-    case JAVATYPE_DOUBLE:
-    case JAVATYPE_BOOLEAN:
-    case JAVATYPE_STRING:
-    case JAVATYPE_BYTES:
-    case JAVATYPE_ENUM:
-      if (boxed) {
-        return BoxedPrimitiveTypeName(java_type);
-      } else {
-        return PrimitiveTypeName(java_type);
-      }
-    // No default because we want the compiler to complain if any new JavaTypes
-    // are added..
-  }
-
-  GOOGLE_LOG(FATAL) << "should not reach here.";
-  return "";
-}
-
-const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) {
-  GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
-  const Descriptor* message = descriptor->message_type();
-  GOOGLE_CHECK(message->options().map_entry());
-  return message->FindFieldByName("key");
-}
-
-const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) {
-  GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
-  const Descriptor* message = descriptor->message_type();
-  GOOGLE_CHECK(message->options().map_entry());
-  return message->FindFieldByName("value");
-}
-
-void SetMapVariables(const Params& params,
-    const FieldDescriptor* descriptor, map<string, string>* variables) {
-  const FieldDescriptor* key = KeyField(descriptor);
-  const FieldDescriptor* value = ValueField(descriptor);
-  (*variables)["name"] =
-    RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
-  (*variables)["number"] = SimpleItoa(descriptor->number());
-  (*variables)["key_type"] = TypeName(params, key, false);
-  (*variables)["boxed_key_type"] = TypeName(params,key, true);
-  (*variables)["key_desc_type"] =
-      "TYPE_" + ToUpper(FieldDescriptor::TypeName(key->type()));
-  (*variables)["key_tag"] = SimpleItoa(internal::WireFormat::MakeTag(key));
-  (*variables)["value_type"] = TypeName(params, value, false);
-  (*variables)["boxed_value_type"] = TypeName(params, value, true);
-  (*variables)["value_desc_type"] =
-      "TYPE_" + ToUpper(FieldDescriptor::TypeName(value->type()));
-  (*variables)["value_tag"] = SimpleItoa(internal::WireFormat::MakeTag(value));
-  (*variables)["type_parameters"] =
-      (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
-  (*variables)["value_default"] =
-      value->type() == FieldDescriptor::TYPE_MESSAGE
-          ? "new " + (*variables)["value_type"] + "()"
-          : "null";
-}
-}  // namespace
-
-// ===================================================================
-MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
-                                     const Params& params)
-    : FieldGenerator(params), descriptor_(descriptor) {
-  SetMapVariables(params, descriptor, &variables_);
-}
-
-MapFieldGenerator::~MapFieldGenerator() {}
-
-void MapFieldGenerator::
-GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
-  printer->Print(variables_,
-    "public java.util.Map<$type_parameters$> $name$;\n");
-}
-
-void MapFieldGenerator::
-GenerateClearCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "$name$ = null;\n");
-}
-
-void MapFieldGenerator::
-GenerateMergingCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "this.$name$ = com.google.protobuf.nano.InternalNano.mergeMapEntry(\n"
-    "  input, this.$name$, mapFactory,\n"
-    "  com.google.protobuf.nano.InternalNano.$key_desc_type$,\n"
-    "  com.google.protobuf.nano.InternalNano.$value_desc_type$,\n"
-    "  $value_default$,\n"
-    "  $key_tag$, $value_tag$);\n"
-    "\n");
-}
-
-void MapFieldGenerator::
-GenerateSerializationCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (this.$name$ != null) {\n"
-    "  com.google.protobuf.nano.InternalNano.serializeMapField(\n"
-    "    output, this.$name$, $number$,\n"
-    "  com.google.protobuf.nano.InternalNano.$key_desc_type$,\n"
-    "  com.google.protobuf.nano.InternalNano.$value_desc_type$);\n"
-    "}\n");
-}
-
-void MapFieldGenerator::
-GenerateSerializedSizeCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (this.$name$ != null) {\n"
-    "  size += com.google.protobuf.nano.InternalNano.computeMapFieldSize(\n"
-    "    this.$name$, $number$,\n"
-    "  com.google.protobuf.nano.InternalNano.$key_desc_type$,\n"
-    "  com.google.protobuf.nano.InternalNano.$value_desc_type$);\n"
-    "}\n");
-}
-
-void MapFieldGenerator::
-GenerateEqualsCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (!com.google.protobuf.nano.InternalNano.equals(\n"
-    "  this.$name$, other.$name$)) {\n"
-    "  return false;\n"
-    "}\n");
-}
-
-void MapFieldGenerator::
-GenerateHashCodeCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "result = 31 * result +\n"
-    "    com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
-}
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.h b/src/google/protobuf/compiler/javanano/javanano_map_field.h
deleted file mode 100644
index c01bde3..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_map_field.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// 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.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__
-
-#include <map>
-#include <string>
-#include <vector>
-#include <google/protobuf/compiler/javanano/javanano_field.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-class MapFieldGenerator : public FieldGenerator {
- public:
-  explicit MapFieldGenerator(
-      const FieldDescriptor* descriptor, const Params& params);
-  ~MapFieldGenerator();
-
-  // implements FieldGenerator ---------------------------------------
-  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
-  void GenerateClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCodeCode(io::Printer* printer) const;
-
- private:
-  const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
-};
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
-#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc
deleted file mode 100644
index a41da5a..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_message.cc
+++ /dev/null
@@ -1,676 +0,0 @@
-// 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)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-
-#include <algorithm>
-#include <google/protobuf/stubs/hash.h>
-#include <google/protobuf/compiler/javanano/javanano_message.h>
-#include <google/protobuf/compiler/javanano/javanano_enum.h>
-#include <google/protobuf/compiler/javanano/javanano_extension.h>
-#include <google/protobuf/compiler/javanano/javanano_helpers.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/descriptor.pb.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-using internal::WireFormat;
-using internal::WireFormatLite;
-
-namespace {
-
-struct FieldOrderingByNumber {
-  inline bool operator()(const FieldDescriptor* a,
-                         const FieldDescriptor* b) const {
-    return a->number() < b->number();
-  }
-};
-
-// Sort the fields of the given Descriptor by number into a new[]'d array
-// and return it.
-const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
-  const FieldDescriptor** fields =
-    new const FieldDescriptor*[descriptor->field_count()];
-  for (int i = 0; i < descriptor->field_count(); i++) {
-    fields[i] = descriptor->field(i);
-  }
-  sort(fields, fields + descriptor->field_count(),
-       FieldOrderingByNumber());
-  return fields;
-}
-
-}  // namespace
-
-// ===================================================================
-
-MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Params& params)
-  : params_(params),
-    descriptor_(descriptor),
-    field_generators_(descriptor, params) {
-}
-
-MessageGenerator::~MessageGenerator() {}
-
-void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
-  // Generate static members for all nested types.
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    // TODO(kenton):  Reuse MessageGenerator objects?
-    if (IsMapEntry(descriptor_->nested_type(i))) continue;
-    MessageGenerator(descriptor_->nested_type(i), params_)
-      .GenerateStaticVariables(printer);
-  }
-}
-
-void MessageGenerator::GenerateStaticVariableInitializers(
-    io::Printer* printer) {
-  // Generate static member initializers for all nested types.
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-   // TODO(kenton):  Reuse MessageGenerator objects?
-    if (IsMapEntry(descriptor_->nested_type(i))) continue;
-    MessageGenerator(descriptor_->nested_type(i), params_)
-      .GenerateStaticVariableInitializers(printer);
-  }
-}
-
-void MessageGenerator::Generate(io::Printer* printer) {
-  if (!params_.store_unknown_fields() &&
-      (descriptor_->extension_count() != 0 || descriptor_->extension_range_count() != 0)) {
-    GOOGLE_LOG(FATAL) << "Extensions are only supported in NANO_RUNTIME if the "
-        "'store_unknown_fields' generator option is 'true'\n";
-  }
-
-  const string& file_name = descriptor_->file()->name();
-  bool is_own_file =
-    params_.java_multiple_files(file_name)
-      && descriptor_->containing_type() == NULL;
-
-  if (is_own_file) {
-    // Note: constants (from enums and fields requiring stored defaults, emitted in the loop below)
-    // may have the same names as constants in the nested classes. This causes Java warnings, but
-    // is not fatal, so we suppress those warnings here in the top-most class declaration.
-    printer->Print(
-      "\n"
-      "@SuppressWarnings(\"hiding\")\n"
-      "public final class $classname$ extends\n",
-      "classname", descriptor_->name());
-  } else {
-    printer->Print(
-      "\n"
-      "public static final class $classname$ extends\n",
-      "classname", descriptor_->name());
-  }
-  if (params_.store_unknown_fields() && params_.parcelable_messages()) {
-    printer->Print(
-      "    com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$>",
-      "classname", descriptor_->name());
-  } else if (params_.store_unknown_fields()) {
-    printer->Print(
-      "    com.google.protobuf.nano.ExtendableMessageNano<$classname$>",
-      "classname", descriptor_->name());
-  } else if (params_.parcelable_messages()) {
-    printer->Print(
-      "    com.google.protobuf.nano.android.ParcelableMessageNano");
-  } else {
-    printer->Print(
-      "    com.google.protobuf.nano.MessageNano");
-  }
-  if (params_.generate_clone()) {
-    printer->Print(" implements java.lang.Cloneable {\n");
-  } else {
-    printer->Print(" {\n");
-  }
-  printer->Indent();
-
-  if (params_.parcelable_messages()) {
-    printer->Print(
-      "\n"
-      "// Used by Parcelable\n"
-      "@SuppressWarnings({\"unused\"})\n"
-      "public static final android.os.Parcelable.Creator<$classname$> CREATOR =\n"
-      "    new com.google.protobuf.nano.android.ParcelableMessageNanoCreator<\n"
-      "        $classname$>($classname$.class);\n",
-      "classname", descriptor_->name());
-  }
-
-  // Nested types and extensions
-  for (int i = 0; i < descriptor_->extension_count(); i++) {
-    ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer);
-  }
-
-  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
-    EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer);
-  }
-
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    if (IsMapEntry(descriptor_->nested_type(i))) continue;
-    MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer);
-  }
-
-  // oneof
-  map<string, string> vars;
-  vars["message_name"] = descriptor_->name();
-  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
-    const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i);
-    vars["oneof_name"] = UnderscoresToCamelCase(oneof_desc);
-    vars["oneof_capitalized_name"] =
-        UnderscoresToCapitalizedCamelCase(oneof_desc);
-    vars["oneof_index"] = SimpleItoa(oneof_desc->index());
-    // Oneof Constants
-    for (int j = 0; j < oneof_desc->field_count(); j++) {
-      const FieldDescriptor* field = oneof_desc->field(j);
-      vars["number"] = SimpleItoa(field->number());
-      vars["cap_field_name"] = ToUpper(field->name());
-      printer->Print(vars,
-        "public static final int $cap_field_name$_FIELD_NUMBER = $number$;\n");
-    }
-    // oneofCase_ and oneof_
-    printer->Print(vars,
-      "private int $oneof_name$Case_ = 0;\n"
-      "private java.lang.Object $oneof_name$_;\n");
-    printer->Print(vars,
-      "public int get$oneof_capitalized_name$Case() {\n"
-      "  return this.$oneof_name$Case_;\n"
-      "}\n");
-    // Oneof clear
-    printer->Print(vars,
-      "public $message_name$ clear$oneof_capitalized_name$() {\n"
-      "  this.$oneof_name$Case_ = 0;\n"
-      "  this.$oneof_name$_ = null;\n"
-      "  return this;\n"
-      "}\n");
-  }
-
-  // Lazy initialization of otherwise static final fields can help prevent the
-  // class initializer from being generated. We want to prevent it because it
-  // stops ProGuard from inlining any methods in this class into call sites and
-  // therefore reducing the method count. However, extensions are best kept as
-  // public static final fields with initializers, so with their existence we
-  // won't bother with lazy initialization.
-  bool lazy_init = descriptor_->extension_count() == 0;
-
-  // Empty array
-  if (lazy_init) {
-    printer->Print(
-      "\n"
-      "private static volatile $classname$[] _emptyArray;\n"
-      "public static $classname$[] emptyArray() {\n"
-      "  // Lazily initializes the empty array\n"
-      "  if (_emptyArray == null) {\n"
-      "    synchronized (\n"
-      "        com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
-      "      if (_emptyArray == null) {\n"
-      "        _emptyArray = new $classname$[0];\n"
-      "      }\n"
-      "    }\n"
-      "  }\n"
-      "  return _emptyArray;\n"
-      "}\n",
-      "classname", descriptor_->name());
-  } else {
-    printer->Print(
-      "\n"
-      "private static final $classname$[] EMPTY_ARRAY = {};\n"
-      "public static $classname$[] emptyArray() {\n"
-      "  return EMPTY_ARRAY;\n"
-      "}\n",
-      "classname", descriptor_->name());
-  }
-
-  // Integers for bit fields
-  int totalInts = (field_generators_.total_bits() + 31) / 32;
-  if (totalInts > 0) {
-    printer->Print("\n");
-    for (int i = 0; i < totalInts; i++) {
-      printer->Print("private int $bit_field_name$;\n",
-        "bit_field_name", GetBitFieldName(i));
-    }
-  }
-
-  // Fields and maybe their default values
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    printer->Print("\n");
-    PrintFieldComment(printer, descriptor_->field(i));
-    field_generators_.get(descriptor_->field(i)).GenerateMembers(
-        printer, lazy_init);
-  }
-
-  // Constructor, with lazy init code if needed
-  if (lazy_init && field_generators_.saved_defaults_needed()) {
-    printer->Print(
-      "\n"
-      "private static volatile boolean _classInitialized;\n"
-      "\n"
-      "public $classname$() {\n"
-      "  // Lazily initializes the field defaults\n"
-      "  if (!_classInitialized) {\n"
-      "    synchronized (\n"
-      "        com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
-      "      if (!_classInitialized) {\n",
-      "classname", descriptor_->name());
-    printer->Indent();
-    printer->Indent();
-    printer->Indent();
-    printer->Indent();
-    for (int i = 0; i < descriptor_->field_count(); i++) {
-      field_generators_.get(descriptor_->field(i))
-          .GenerateInitSavedDefaultCode(printer);
-    }
-    printer->Outdent();
-    printer->Outdent();
-    printer->Outdent();
-    printer->Outdent();
-    printer->Print(
-      "        _classInitialized = true;\n"
-      "      }\n"
-      "    }\n"
-      "  }\n");
-    if (params_.generate_clear()) {
-      printer->Print("  clear();\n");
-    }
-    printer->Print("}\n");
-  } else {
-    printer->Print(
-      "\n"
-      "public $classname$() {\n",
-      "classname", descriptor_->name());
-    if (params_.generate_clear()) {
-      printer->Print("  clear();\n");
-    } else {
-      printer->Indent();
-      GenerateFieldInitializers(printer);
-      printer->Outdent();
-    }
-    printer->Print("}\n");
-  }
-
-  // Other methods in this class
-
-  GenerateClear(printer);
-
-  if (params_.generate_clone()) {
-    GenerateClone(printer);
-  }
-
-  if (params_.generate_equals()) {
-    GenerateEquals(printer);
-    GenerateHashCode(printer);
-  }
-
-  GenerateMessageSerializationMethods(printer);
-  GenerateMergeFromMethods(printer);
-  GenerateParseFromMethods(printer);
-
-  printer->Outdent();
-  printer->Print("}\n");
-}
-
-// ===================================================================
-
-void MessageGenerator::
-GenerateMessageSerializationMethods(io::Printer* printer) {
-  // Rely on the parent implementations of writeTo() and getSerializedSize()
-  // if there are no fields to serialize in this message.
-  if (descriptor_->field_count() == 0) {
-    return;
-  }
-
-  scoped_array<const FieldDescriptor*> sorted_fields(
-    SortFieldsByNumber(descriptor_));
-
-  printer->Print(
-    "\n"
-    "@Override\n"
-    "public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)\n"
-    "    throws java.io.IOException {\n");
-  printer->Indent();
-
-  // Output the fields in sorted order
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    GenerateSerializeOneField(printer, sorted_fields[i]);
-  }
-
-  // The parent implementation will write any unknown fields if necessary.
-  printer->Print(
-    "super.writeTo(output);\n");
-
-  printer->Outdent();
-  printer->Print("}\n");
-
-  // The parent implementation will get the serialized size for unknown
-  // fields if necessary.
-  printer->Print(
-    "\n"
-    "@Override\n"
-    "protected int computeSerializedSize() {\n"
-    "  int size = super.computeSerializedSize();\n");
-  printer->Indent();
-
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
-  }
-
-  printer->Outdent();
-  printer->Print(
-    "  return size;\n"
-    "}\n");
-}
-
-void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
-  scoped_array<const FieldDescriptor*> sorted_fields(
-    SortFieldsByNumber(descriptor_));
-
-  printer->Print(
-    "\n"
-    "@Override\n"
-    "public $classname$ mergeFrom(\n"
-    "        com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
-    "    throws java.io.IOException {\n",
-    "classname", descriptor_->name());
-
-  printer->Indent();
-  if (HasMapField(descriptor_)) {
-    printer->Print(
-      "com.google.protobuf.nano.MapFactories.MapFactory mapFactory =\n"
-      "  com.google.protobuf.nano.MapFactories.getMapFactory();\n");
-  }
-
-  printer->Print(
-    "while (true) {\n");
-  printer->Indent();
-
-  printer->Print(
-    "int tag = input.readTag();\n"
-    "switch (tag) {\n");
-  printer->Indent();
-
-  printer->Print(
-    "case 0:\n"          // zero signals EOF / limit reached
-    "  return this;\n"
-    "default: {\n");
-
-  printer->Indent();
-  if (params_.store_unknown_fields()) {
-    printer->Print(
-        "if (!storeUnknownField(input, tag)) {\n"
-        "  return this;\n"
-        "}\n");
-  } else {
-    printer->Print(
-        "if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n"
-        "  return this;\n"   // it's an endgroup tag
-        "}\n");
-  }
-  printer->Print("break;\n");
-  printer->Outdent();
-  printer->Print("}\n");
-
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = sorted_fields[i];
-    uint32 tag = WireFormatLite::MakeTag(field->number(),
-      WireFormat::WireTypeForFieldType(field->type()));
-
-    printer->Print(
-      "case $tag$: {\n",
-      "tag", SimpleItoa(tag));
-    printer->Indent();
-
-    field_generators_.get(field).GenerateMergingCode(printer);
-
-    printer->Outdent();
-    printer->Print(
-      "  break;\n"
-      "}\n");
-
-    if (field->is_packable()) {
-      // To make packed = true wire compatible, we generate parsing code from a
-      // packed version of this field regardless of field->options().packed().
-      uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
-        WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
-      printer->Print(
-        "case $tag$: {\n",
-        "tag", SimpleItoa(packed_tag));
-      printer->Indent();
-
-      field_generators_.get(field).GenerateMergingCodeFromPacked(printer);
-
-      printer->Outdent();
-      printer->Print(
-        "  break;\n"
-        "}\n");
-    }
-  }
-
-  printer->Outdent();
-  printer->Outdent();
-  printer->Outdent();
-  printer->Print(
-    "    }\n"     // switch (tag)
-    "  }\n"       // while (true)
-    "}\n");
-}
-
-void MessageGenerator::
-GenerateParseFromMethods(io::Printer* printer) {
-  // Note:  These are separate from GenerateMessageSerializationMethods()
-  //   because they need to be generated even for messages that are optimized
-  //   for code size.
-  printer->Print(
-    "\n"
-    "public static $classname$ parseFrom(byte[] data)\n"
-    "    throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n"
-    "  return com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n"
-    "}\n"
-    "\n"
-    "public static $classname$ parseFrom(\n"
-    "        com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
-    "    throws java.io.IOException {\n"
-    "  return new $classname$().mergeFrom(input);\n"
-    "}\n",
-    "classname", descriptor_->name());
-}
-
-void MessageGenerator::GenerateSerializeOneField(
-    io::Printer* printer, const FieldDescriptor* field) {
-  field_generators_.get(field).GenerateSerializationCode(printer);
-}
-
-void MessageGenerator::GenerateClear(io::Printer* printer) {
-  if (!params_.generate_clear()) {
-    return;
-  }
-  printer->Print(
-    "\n"
-    "public $classname$ clear() {\n",
-    "classname", descriptor_->name());
-  printer->Indent();
-
-  GenerateFieldInitializers(printer);
-
-  printer->Outdent();
-  printer->Print(
-    "  return this;\n"
-    "}\n");
-}
-
-void MessageGenerator::GenerateFieldInitializers(io::Printer* printer) {
-  // Clear bit fields.
-  int totalInts = (field_generators_.total_bits() + 31) / 32;
-  for (int i = 0; i < totalInts; i++) {
-    printer->Print("$bit_field_name$ = 0;\n",
-      "bit_field_name", GetBitFieldName(i));
-  }
-
-  // Call clear for all of the fields.
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = descriptor_->field(i);
-    field_generators_.get(field).GenerateClearCode(printer);
-  }
-
-  // Clear oneofs.
-  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
-    printer->Print(
-      "clear$oneof_capitalized_name$();\n",
-      "oneof_capitalized_name", UnderscoresToCapitalizedCamelCase(
-          descriptor_->oneof_decl(i)));
-  }
-
-  // Clear unknown fields.
-  if (params_.store_unknown_fields()) {
-    printer->Print("unknownFieldData = null;\n");
-  }
-  printer->Print("cachedSize = -1;\n");
-}
-
-void MessageGenerator::GenerateClone(io::Printer* printer) {
-  printer->Print(
-    "@Override\n"
-    "public $classname$ clone() {\n",
-    "classname", descriptor_->name());
-  printer->Indent();
-
-  printer->Print(
-    "$classname$ cloned;\n"
-    "try {\n"
-    "  cloned = ($classname$) super.clone();\n"
-    "} catch (java.lang.CloneNotSupportedException e) {\n"
-    "  throw new java.lang.AssertionError(e);\n"
-    "}\n",
-    "classname", descriptor_->name());
-
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    field_generators_.get(descriptor_->field(i)).GenerateFixClonedCode(printer);
-  }
-
-  printer->Outdent();
-  printer->Print(
-    "  return cloned;\n"
-    "}\n"
-    "\n");
-}
-
-void MessageGenerator::GenerateEquals(io::Printer* printer) {
-  // Don't override if there are no fields. We could generate an
-  // equals method that compares types, but often empty messages
-  // are used as namespaces.
-  if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
-    return;
-  }
-
-  printer->Print(
-    "\n"
-    "@Override\n"
-    "public boolean equals(Object o) {\n");
-  printer->Indent();
-  printer->Print(
-    "if (o == this) {\n"
-    "  return true;\n"
-    "}\n"
-    "if (!(o instanceof $classname$)) {\n"
-    "  return false;\n"
-    "}\n"
-    "$classname$ other = ($classname$) o;\n",
-    "classname", descriptor_->name());
-
-  // Checking oneof case before checking each oneof field.
-  for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
-    const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i);
-    printer->Print(
-      "if (this.$oneof_name$Case_ != other.$oneof_name$Case_) {\n"
-      "  return false;\n"
-      "}\n",
-      "oneof_name", UnderscoresToCamelCase(oneof_desc));
-  }
-
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = descriptor_->field(i);
-    field_generators_.get(field).GenerateEqualsCode(printer);
-  }
-
-  if (params_.store_unknown_fields()) {
-    printer->Print(
-      "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n"
-      "  return other.unknownFieldData == null || other.unknownFieldData.isEmpty();\n"
-      "} else {\n"
-      "  return unknownFieldData.equals(other.unknownFieldData);\n"
-      "}");
-  } else {
-    printer->Print(
-      "return true;\n");
-  }
-
-  printer->Outdent();
-  printer->Print("}\n");
-}
-
-void MessageGenerator::GenerateHashCode(io::Printer* printer) {
-  if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
-    return;
-  }
-
-  printer->Print(
-    "\n"
-    "@Override\n"
-    "public int hashCode() {\n");
-  printer->Indent();
-
-  printer->Print("int result = 17;\n");
-  printer->Print("result = 31 * result + getClass().getName().hashCode();\n");
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = descriptor_->field(i);
-    field_generators_.get(field).GenerateHashCodeCode(printer);
-  }
-
-  if (params_.store_unknown_fields()) {
-    printer->Print(
-      "result = 31 * result + \n"
-      "  (unknownFieldData == null || unknownFieldData.isEmpty() ? 0 : \n"
-      "  unknownFieldData.hashCode());\n");
-  }
-
-  printer->Print("return result;\n");
-
-  printer->Outdent();
-  printer->Print("}\n");
-}
-
-// ===================================================================
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_message.h b/src/google/protobuf/compiler/javanano/javanano_message.h
deleted file mode 100644
index 281ec64..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_message.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// 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)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_H__
-
-#include <string>
-#include <google/protobuf/compiler/javanano/javanano_helpers.h>
-#include <google/protobuf/compiler/javanano/javanano_field.h>
-#include <google/protobuf/compiler/javanano/javanano_params.h>
-#include <google/protobuf/stubs/common.h>
-
-namespace google {
-namespace protobuf {
-  namespace io {
-    class Printer;             // printer.h
-  }
-}
-
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-class MessageGenerator {
- public:
-  explicit MessageGenerator(const Descriptor* descriptor, const Params& params);
-  ~MessageGenerator();
-
-  // All static variables have to be declared at the top-level of the file
-  // so that we can control initialization order, which is important for
-  // DescriptorProto bootstrapping to work.
-  void GenerateStaticVariables(io::Printer* printer);
-
-  // Output code which initializes the static variables generated by
-  // GenerateStaticVariables().
-  void GenerateStaticVariableInitializers(io::Printer* printer);
-
-  // Generate the class itself.
-  void Generate(io::Printer* printer);
-
- private:
-  void GenerateMessageSerializationMethods(io::Printer* printer);
-  void GenerateMergeFromMethods(io::Printer* printer);
-  void GenerateParseFromMethods(io::Printer* printer);
-  void GenerateSerializeOneField(io::Printer* printer,
-                                 const FieldDescriptor* field);
-
-  void GenerateClear(io::Printer* printer);
-  void GenerateFieldInitializers(io::Printer* printer);
-  void GenerateEquals(io::Printer* printer);
-  void GenerateHashCode(io::Printer* printer);
-  void GenerateClone(io::Printer* printer);
-
-  const Params& params_;
-  const Descriptor* descriptor_;
-  FieldGeneratorMap field_generators_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
-};
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-
-}  // namespace google
-#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
deleted file mode 100644
index d1d04b5..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc
+++ /dev/null
@@ -1,363 +0,0 @@
-// 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)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-
-#include <map>
-#include <string>
-
-#include <google/protobuf/compiler/javanano/javanano_message_field.h>
-#include <google/protobuf/compiler/javanano/javanano_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 javanano {
-
-using internal::WireFormat;
-using internal::WireFormatLite;
-
-namespace {
-
-// TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
-//   repeat code between this and the other field types.
-void SetMessageVariables(const Params& params,
-    const FieldDescriptor* descriptor, map<string, string>* variables) {
-  (*variables)["name"] =
-    RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
-  (*variables)["capitalized_name"] =
-    RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
-  (*variables)["number"] = SimpleItoa(descriptor->number());
-  (*variables)["type"] = ClassName(params, descriptor->message_type());
-  (*variables)["group_or_message"] =
-    (descriptor->type() == FieldDescriptor::TYPE_GROUP) ?
-    "Group" : "Message";
-  (*variables)["message_name"] = descriptor->containing_type()->name();
-  //(*variables)["message_type"] = descriptor->message_type()->name();
-  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
-}
-
-}  // namespace
-
-// ===================================================================
-
-MessageFieldGenerator::
-MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
-  : FieldGenerator(params), descriptor_(descriptor) {
-  SetMessageVariables(params, descriptor, &variables_);
-}
-
-MessageFieldGenerator::~MessageFieldGenerator() {}
-
-void MessageFieldGenerator::
-GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
-  printer->Print(variables_,
-    "public $type$ $name$;\n");
-}
-
-void MessageFieldGenerator::
-GenerateClearCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "$name$ = null;\n");
-}
-
-void MessageFieldGenerator::
-GenerateMergingCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (this.$name$ == null) {\n"
-    "  this.$name$ = new $type$();\n"
-    "}\n");
-
-  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
-    printer->Print(variables_,
-      "input.readGroup(this.$name$, $number$);\n");
-  } else {
-    printer->Print(variables_,
-      "input.readMessage(this.$name$);\n");
-  }
-}
-
-void MessageFieldGenerator::
-GenerateSerializationCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (this.$name$ != null) {\n"
-    "  output.write$group_or_message$($number$, this.$name$);\n"
-    "}\n");
-}
-
-void MessageFieldGenerator::
-GenerateSerializedSizeCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (this.$name$ != null) {\n"
-    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
-    "    .compute$group_or_message$Size($number$, this.$name$);\n"
-    "}\n");
-}
-
-void MessageFieldGenerator::
-GenerateFixClonedCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (this.$name$ != null) {\n"
-    "  cloned.$name$ = this.$name$.clone();\n"
-    "}\n");
-}
-
-void MessageFieldGenerator::
-GenerateEqualsCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (this.$name$ == null) { \n"
-    "  if (other.$name$ != null) {\n"
-    "    return false;\n"
-    "  }\n"
-    "} else {\n"
-    "  if (!this.$name$.equals(other.$name$)) {\n"
-    "    return false;\n"
-    "  }\n"
-    "}\n");
-}
-
-void MessageFieldGenerator::
-GenerateHashCodeCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "result = 31 * result +\n"
-    "    (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
-}
-// ===================================================================
-
-MessageOneofFieldGenerator::MessageOneofFieldGenerator(
-    const FieldDescriptor* descriptor, const Params& params)
-    : FieldGenerator(params), descriptor_(descriptor) {
-    SetMessageVariables(params, descriptor, &variables_);
-    SetCommonOneofVariables(descriptor, &variables_);
-}
-
-MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
-
-void MessageOneofFieldGenerator::
-GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
-  printer->Print(variables_,
-    "public boolean has$capitalized_name$() {\n"
-    "  return $has_oneof_case$;\n"
-    "}\n"
-    "public $type$ get$capitalized_name$() {\n"
-    "  if ($has_oneof_case$) {\n"
-    "    return ($type$) this.$oneof_name$_;\n"
-    "  }\n"
-    "  return null;\n"
-    "}\n"
-    "public $message_name$ set$capitalized_name$($type$ value) {\n"
-    "  if (value == null) { throw new java.lang.NullPointerException(); }\n"
-    "  $set_oneof_case$;\n"
-    "  this.$oneof_name$_ = value;\n"
-    "  return this;\n"
-    "}\n");
-}
-
-void MessageOneofFieldGenerator::
-GenerateClearCode(io::Printer* printer) const {
-  // No clear method for oneof fields.
-}
-
-void MessageOneofFieldGenerator::
-GenerateMergingCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (!($has_oneof_case$)) {\n"
-    "  this.$oneof_name$_ = new $type$();\n"
-    "}\n"
-    "input.readMessage(\n"
-    "    (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
-    "$set_oneof_case$;\n");
-}
-
-void MessageOneofFieldGenerator::
-GenerateSerializationCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if ($has_oneof_case$) {\n"
-    "  output.writeMessage($number$,\n"
-    "      (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
-    "}\n");
-}
-
-void MessageOneofFieldGenerator::
-GenerateSerializedSizeCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if ($has_oneof_case$) {\n"
-    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
-    "    .computeMessageSize($number$,\n"
-    "        (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
-    "}\n");
-}
-
-void MessageOneofFieldGenerator::
-GenerateFixClonedCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (this.$oneof_name$ != null) {\n"
-    "  cloned.$oneof_name$ = this.$oneof_name$.clone();\n"
-    "}\n");
-}
-
-void MessageOneofFieldGenerator::
-GenerateEqualsCode(io::Printer* printer) const {
-  GenerateOneofFieldEquals(descriptor_, variables_, printer);
-}
-
-void MessageOneofFieldGenerator::
-GenerateHashCodeCode(io::Printer* printer) const {
-  GenerateOneofFieldHashCode(descriptor_, variables_, printer);
-}
-
-// ===================================================================
-
-RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
-    const FieldDescriptor* descriptor, const Params& params)
-    : FieldGenerator(params), descriptor_(descriptor) {
-  SetMessageVariables(params, descriptor, &variables_);
-}
-
-RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
-
-void RepeatedMessageFieldGenerator::
-GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
-  printer->Print(variables_,
-    "public $type$[] $name$;\n");
-}
-
-void RepeatedMessageFieldGenerator::
-GenerateClearCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "$name$ = $type$.emptyArray();\n");
-}
-
-void RepeatedMessageFieldGenerator::
-GenerateMergingCode(io::Printer* printer) const {
-  // First, figure out the length of the array, then parse.
-  printer->Print(variables_,
-    "int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
-    "    .getRepeatedFieldArrayLength(input, $tag$);\n"
-    "int i = this.$name$ == null ? 0 : this.$name$.length;\n"
-    "$type$[] newArray =\n"
-    "    new $type$[i + arrayLength];\n"
-    "if (i != 0) {\n"
-    "  java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
-    "}\n"
-    "for (; i < newArray.length - 1; i++) {\n"
-    "  newArray[i] = new $type$();\n");
-
-  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
-    printer->Print(variables_,
-      "  input.readGroup(newArray[i], $number$);\n");
-  } else {
-    printer->Print(variables_,
-      "  input.readMessage(newArray[i]);\n");
-  }
-
-  printer->Print(variables_,
-    "  input.readTag();\n"
-    "}\n"
-    "// Last one without readTag.\n"
-    "newArray[i] = new $type$();\n");
-
-  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
-    printer->Print(variables_,
-      "input.readGroup(newArray[i], $number$);\n");
-  } else {
-    printer->Print(variables_,
-      "input.readMessage(newArray[i]);\n");
-  }
-
-  printer->Print(variables_,
-    "this.$name$ = newArray;\n");
-}
-
-void RepeatedMessageFieldGenerator::
-GenerateSerializationCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (this.$name$ != null && this.$name$.length > 0) {\n"
-    "  for (int i = 0; i < this.$name$.length; i++) {\n"
-    "    $type$ element = this.$name$[i];\n"
-    "    if (element != null) {\n"
-    "      output.write$group_or_message$($number$, element);\n"
-    "    }\n"
-    "  }\n"
-    "}\n");
-}
-
-void RepeatedMessageFieldGenerator::
-GenerateSerializedSizeCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (this.$name$ != null && this.$name$.length > 0) {\n"
-    "  for (int i = 0; i < this.$name$.length; i++) {\n"
-    "    $type$ element = this.$name$[i];\n"
-    "    if (element != null) {\n"
-    "      size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
-    "        .compute$group_or_message$Size($number$, element);\n"
-    "    }\n"
-    "  }\n"
-    "}\n");
-}
-
-void RepeatedMessageFieldGenerator::
-GenerateFixClonedCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (this.$name$ != null && this.$name$.length > 0) {\n"
-    "  cloned.$name$ = new $type$[this.$name$.length];\n"
-    "  for (int i = 0; i < this.$name$.length; i++) {\n"
-    "    if (this.$name$[i] != null) {\n"
-    "      cloned.$name$[i] = this.$name$[i].clone();\n"
-    "    }\n"
-    "  }\n"
-    "}\n");
-}
-
-void RepeatedMessageFieldGenerator::
-GenerateEqualsCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (!com.google.protobuf.nano.InternalNano.equals(\n"
-    "    this.$name$, other.$name$)) {\n"
-    "  return false;\n"
-    "}\n");
-}
-
-void RepeatedMessageFieldGenerator::
-GenerateHashCodeCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "result = 31 * result\n"
-    "    + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
-}
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.h b/src/google/protobuf/compiler/javanano/javanano_message_field.h
deleted file mode 100644
index e074735..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_message_field.h
+++ /dev/null
@@ -1,121 +0,0 @@
-// 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)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_FIELD_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_FIELD_H__
-
-#include <map>
-#include <string>
-#include <google/protobuf/compiler/javanano/javanano_field.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-class MessageFieldGenerator : public FieldGenerator {
- public:
-  explicit MessageFieldGenerator(
-      const FieldDescriptor* descriptor, const Params& params);
-  ~MessageFieldGenerator();
-
-  // implements FieldGenerator ---------------------------------------
-  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
-  void GenerateClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCodeCode(io::Printer* printer) const;
-  void GenerateFixClonedCode(io::Printer* printer) const;
-
- private:
-  const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
-};
-
-class MessageOneofFieldGenerator : public FieldGenerator {
- public:
-  explicit MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
-                                      const Params& params);
-  ~MessageOneofFieldGenerator();
-
-  // implements FieldGenerator ---------------------------------------
-  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
-  void GenerateClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCodeCode(io::Printer* printer) const;
-  void GenerateFixClonedCode(io::Printer* printer) const;
-
- private:
-  const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
-};
-
-class RepeatedMessageFieldGenerator : public FieldGenerator {
- public:
-  explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
-        const Params& params);
-  ~RepeatedMessageFieldGenerator();
-
-  // implements FieldGenerator ---------------------------------------
-  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
-  void GenerateClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCodeCode(io::Printer* printer) const;
-  void GenerateFixClonedCode(io::Printer* printer) const;
-
- private:
-  const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
-};
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-
-}  // namespace google
-#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_FIELD_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_params.h b/src/google/protobuf/compiler/javanano/javanano_params.h
deleted file mode 100644
index e3b4bb9..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_params.h
+++ /dev/null
@@ -1,258 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2010 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: wink@google.com (Wink Saville)
-
-#ifndef PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_
-#define PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_
-
-#include <map>
-#include <set>
-#include <google/protobuf/stubs/strutil.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-enum eMultipleFiles { JAVANANO_MUL_UNSET, JAVANANO_MUL_FALSE, JAVANANO_MUL_TRUE };
-
-// Parameters for used by the generators
-class Params {
- public:
-  typedef map<string, string> NameMap;
-  typedef set<string> NameSet;
- private:
-  string empty_;
-  string base_name_;
-  eMultipleFiles override_java_multiple_files_;
-  bool store_unknown_fields_;
-  NameMap java_packages_;
-  NameMap java_outer_classnames_;
-  NameSet java_multiple_files_;
-  bool generate_has_;
-  bool java_enum_style_;
-  bool optional_field_accessors_;
-  bool use_reference_types_for_primitives_;
-  bool generate_equals_;
-  bool ignore_services_;
-  bool parcelable_messages_;
-  bool reftypes_primitive_enums_;
-  bool generate_clear_;
-  bool generate_clone_;
-  bool generate_intdefs_;
-
- public:
-  Params(const string & base_name) :
-    empty_(""),
-    base_name_(base_name),
-    override_java_multiple_files_(JAVANANO_MUL_UNSET),
-    store_unknown_fields_(false),
-    generate_has_(false),
-    java_enum_style_(false),
-    optional_field_accessors_(false),
-    use_reference_types_for_primitives_(false),
-    generate_equals_(false),
-    ignore_services_(false),
-    parcelable_messages_(false),
-    reftypes_primitive_enums_(false),
-    generate_clear_(true),
-    generate_clone_(false),
-    generate_intdefs_(false) {
-  }
-
-  const string& base_name() const {
-    return base_name_;
-  }
-
-  bool has_java_package(const string& file_name) const {
-    return java_packages_.find(file_name)
-                        != java_packages_.end();
-  }
-  void set_java_package(const string& file_name,
-      const string& java_package) {
-    java_packages_[file_name] = java_package;
-  }
-  const string& java_package(const string& file_name) const {
-    NameMap::const_iterator itr;
-
-    itr = java_packages_.find(file_name);
-    if  (itr == java_packages_.end()) {
-      return empty_;
-    } else {
-      return itr->second;
-    }
-  }
-  const NameMap& java_packages() {
-    return java_packages_;
-  }
-
-  bool has_java_outer_classname(const string& file_name) const {
-    return java_outer_classnames_.find(file_name)
-                        != java_outer_classnames_.end();
-  }
-  void set_java_outer_classname(const string& file_name,
-      const string& java_outer_classname) {
-    java_outer_classnames_[file_name] = java_outer_classname;
-  }
-  const string& java_outer_classname(const string& file_name) const {
-    NameMap::const_iterator itr;
-
-    itr = java_outer_classnames_.find(file_name);
-    if  (itr == java_outer_classnames_.end()) {
-      return empty_;
-    } else {
-      return itr->second;
-    }
-  }
-  const NameMap& java_outer_classnames() {
-    return java_outer_classnames_;
-  }
-
-  void set_override_java_multiple_files(bool java_multiple_files) {
-    if (java_multiple_files) {
-      override_java_multiple_files_ = JAVANANO_MUL_TRUE;
-    } else {
-      override_java_multiple_files_ = JAVANANO_MUL_FALSE;
-    }
-  }
-  void clear_override_java_multiple_files() {
-    override_java_multiple_files_ = JAVANANO_MUL_UNSET;
-  }
-
-  void set_java_multiple_files(const string& file_name, bool value) {
-    if (value) {
-      java_multiple_files_.insert(file_name);
-    } else {
-      java_multiple_files_.erase(file_name);
-    }
-  }
-  bool java_multiple_files(const string& file_name) const {
-    switch (override_java_multiple_files_) {
-      case JAVANANO_MUL_FALSE:
-        return false;
-      case JAVANANO_MUL_TRUE:
-        return true;
-      default:
-        return java_multiple_files_.find(file_name)
-                != java_multiple_files_.end();
-    }
-  }
-
-  void set_store_unknown_fields(bool value) {
-    store_unknown_fields_ = value;
-  }
-  bool store_unknown_fields() const {
-    return store_unknown_fields_;
-  }
-
-  void set_generate_has(bool value) {
-    generate_has_ = value;
-  }
-  bool generate_has() const {
-    return generate_has_;
-  }
-
-  void set_java_enum_style(bool value) {
-    java_enum_style_ = value;
-  }
-  bool java_enum_style() const {
-    return java_enum_style_;
-  }
-
-  void set_optional_field_accessors(bool value) {
-    optional_field_accessors_ = value;
-  }
-  bool optional_field_accessors() const {
-    return optional_field_accessors_;
-  }
-
-  void set_use_reference_types_for_primitives(bool value) {
-    use_reference_types_for_primitives_ = value;
-  }
-  bool use_reference_types_for_primitives() const {
-    return use_reference_types_for_primitives_;
-  }
-
-  void set_generate_equals(bool value) {
-    generate_equals_ = value;
-  }
-  bool generate_equals() const {
-    return generate_equals_;
-  }
-
-  void set_ignore_services(bool value) {
-    ignore_services_ = value;
-  }
-  bool ignore_services() const {
-    return ignore_services_;
-  }
-
-  void set_parcelable_messages(bool value) {
-    parcelable_messages_ = value;
-  }
-  bool parcelable_messages() const {
-    return parcelable_messages_;
-  }
-
-  void set_reftypes_primitive_enums(bool value) {
-    reftypes_primitive_enums_ = value;
-  }
-  bool reftypes_primitive_enums() const {
-    return reftypes_primitive_enums_;
-  }
-
-  void set_generate_clear(bool value) {
-    generate_clear_ = value;
-  }
-  bool generate_clear() const {
-    return generate_clear_;
-  }
-
-  void set_generate_clone(bool value) {
-    generate_clone_ = value;
-  }
-  bool generate_clone() const {
-    return generate_clone_;
-  }
-
-  void set_generate_intdefs(bool value) {
-    generate_intdefs_ = value;
-  }
-  bool generate_intdefs() const {
-    return generate_intdefs_;
-  }
-};
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
-#endif  // PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
deleted file mode 100644
index 978abf2..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
+++ /dev/null
@@ -1,968 +0,0 @@
-// 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)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-
-#include <map>
-#include <math.h>
-#include <string>
-
-#include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/javanano/javanano_helpers.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-using internal::WireFormat;
-using internal::WireFormatLite;
-
-namespace {
-
-bool IsReferenceType(JavaType type) {
-  switch (type) {
-    case JAVATYPE_INT    : return false;
-    case JAVATYPE_LONG   : return false;
-    case JAVATYPE_FLOAT  : return false;
-    case JAVATYPE_DOUBLE : return false;
-    case JAVATYPE_BOOLEAN: return false;
-    case JAVATYPE_STRING : return true;
-    case JAVATYPE_BYTES  : return true;
-    case JAVATYPE_ENUM   : return false;
-    case JAVATYPE_MESSAGE: return true;
-
-    // No default because we want the compiler to complain if any new
-    // JavaTypes are added.
-  }
-
-  GOOGLE_LOG(FATAL) << "Can't get here.";
-  return false;
-}
-
-bool IsArrayType(JavaType type) {
-  switch (type) {
-    case JAVATYPE_INT    : return false;
-    case JAVATYPE_LONG   : return false;
-    case JAVATYPE_FLOAT  : return false;
-    case JAVATYPE_DOUBLE : return false;
-    case JAVATYPE_BOOLEAN: return false;
-    case JAVATYPE_STRING : return false;
-    case JAVATYPE_BYTES  : return true;
-    case JAVATYPE_ENUM   : return false;
-    case JAVATYPE_MESSAGE: return false;
-
-    // No default because we want the compiler to complain if any new
-    // JavaTypes are added.
-  }
-
-  GOOGLE_LOG(FATAL) << "Can't get here.";
-  return false;
-}
-
-const char* GetCapitalizedType(const FieldDescriptor* field) {
-  switch (field->type()) {
-    case FieldDescriptor::TYPE_INT32   : return "Int32"   ;
-    case FieldDescriptor::TYPE_UINT32  : return "UInt32"  ;
-    case FieldDescriptor::TYPE_SINT32  : return "SInt32"  ;
-    case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ;
-    case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
-    case FieldDescriptor::TYPE_INT64   : return "Int64"   ;
-    case FieldDescriptor::TYPE_UINT64  : return "UInt64"  ;
-    case FieldDescriptor::TYPE_SINT64  : return "SInt64"  ;
-    case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ;
-    case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
-    case FieldDescriptor::TYPE_FLOAT   : return "Float"   ;
-    case FieldDescriptor::TYPE_DOUBLE  : return "Double"  ;
-    case FieldDescriptor::TYPE_BOOL    : return "Bool"    ;
-    case FieldDescriptor::TYPE_STRING  : return "String"  ;
-    case FieldDescriptor::TYPE_BYTES   : return "Bytes"   ;
-    case FieldDescriptor::TYPE_ENUM    : return "Enum"    ;
-    case FieldDescriptor::TYPE_GROUP   : return "Group"   ;
-    case FieldDescriptor::TYPE_MESSAGE : return "Message" ;
-
-    // No default because we want the compiler to complain if any new
-    // types are added.
-  }
-
-  GOOGLE_LOG(FATAL) << "Can't get here.";
-  return NULL;
-}
-
-// For encodings with fixed sizes, returns that size in bytes.  Otherwise
-// returns -1.
-int FixedSize(FieldDescriptor::Type type) {
-  switch (type) {
-    case FieldDescriptor::TYPE_INT32   : return -1;
-    case FieldDescriptor::TYPE_INT64   : return -1;
-    case FieldDescriptor::TYPE_UINT32  : return -1;
-    case FieldDescriptor::TYPE_UINT64  : return -1;
-    case FieldDescriptor::TYPE_SINT32  : return -1;
-    case FieldDescriptor::TYPE_SINT64  : return -1;
-    case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
-    case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
-    case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
-    case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
-    case FieldDescriptor::TYPE_FLOAT   : return WireFormatLite::kFloatSize;
-    case FieldDescriptor::TYPE_DOUBLE  : return WireFormatLite::kDoubleSize;
-
-    case FieldDescriptor::TYPE_BOOL    : return WireFormatLite::kBoolSize;
-    case FieldDescriptor::TYPE_ENUM    : return -1;
-
-    case FieldDescriptor::TYPE_STRING  : return -1;
-    case FieldDescriptor::TYPE_BYTES   : return -1;
-    case FieldDescriptor::TYPE_GROUP   : return -1;
-    case FieldDescriptor::TYPE_MESSAGE : return -1;
-
-    // No default because we want the compiler to complain if any new
-    // types are added.
-  }
-  GOOGLE_LOG(FATAL) << "Can't get here.";
-  return -1;
-}
-
-bool AllAscii(const string& text) {
-  for (int i = 0; i < text.size(); i++) {
-    if ((text[i] & 0x80) != 0) {
-      return false;
-    }
-  }
-  return true;
-}
-
-
-void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params,
-                           map<string, string>* variables) {
-  (*variables)["name"] =
-    RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
-  (*variables)["capitalized_name"] =
-    RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
-  (*variables)["number"] = SimpleItoa(descriptor->number());
-  if (params.use_reference_types_for_primitives()
-      && !descriptor->is_repeated()) {
-    (*variables)["type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
-  } else {
-    (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
-  }
-  // Deals with defaults. For C++-string types (string and bytes),
-  // we might need to have the generated code do the unicode decoding
-  // (see comments in InternalNano.java for gory details.). We would
-  // like to do this once into a static field and re-use that from
-  // then on.
-  if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
-      !descriptor->default_value_string().empty() &&
-      !params.use_reference_types_for_primitives()) {
-    if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
-      (*variables)["default"] = DefaultValue(params, descriptor);
-      (*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
-      (*variables)["default_constant_value"] = strings::Substitute(
-          "com.google.protobuf.nano.InternalNano.bytesDefaultValue(\"$0\")",
-          CEscape(descriptor->default_value_string()));
-      (*variables)["default_copy_if_needed"] =
-          (*variables)["default"] + ".clone()";
-    } else if (AllAscii(descriptor->default_value_string())) {
-      // All chars are ASCII.  In this case directly referencing a
-      // CEscape()'d string literal works fine.
-      (*variables)["default"] =
-          "\"" + CEscape(descriptor->default_value_string()) + "\"";
-      (*variables)["default_copy_if_needed"] = (*variables)["default"];
-    } else {
-      // Strings where some chars are non-ASCII. We need to save the
-      // default value.
-      (*variables)["default"] = DefaultValue(params, descriptor);
-      (*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
-      (*variables)["default_constant_value"] = strings::Substitute(
-          "com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")",
-          CEscape(descriptor->default_value_string()));
-      (*variables)["default_copy_if_needed"] = (*variables)["default"];
-    }
-  } else {
-    // Non-string, non-bytes field. Defaults are literals.
-    (*variables)["default"] = DefaultValue(params, descriptor);
-    (*variables)["default_copy_if_needed"] = (*variables)["default"];
-  }
-  (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
-  (*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
-  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
-  (*variables)["tag_size"] = SimpleItoa(
-      WireFormat::TagSize(descriptor->number(), descriptor->type()));
-  (*variables)["non_packed_tag"] = SimpleItoa(
-      internal::WireFormatLite::MakeTag(descriptor->number(),
-          internal::WireFormat::WireTypeForFieldType(descriptor->type())));
-  int fixed_size = FixedSize(descriptor->type());
-  if (fixed_size != -1) {
-    (*variables)["fixed_size"] = SimpleItoa(fixed_size);
-  }
-  (*variables)["message_name"] = descriptor->containing_type()->name();
-  (*variables)["empty_array_name"] = EmptyArrayName(params, descriptor);
-}
-}  // namespace
-
-// ===================================================================
-
-PrimitiveFieldGenerator::
-PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
-  : FieldGenerator(params), descriptor_(descriptor) {
-  SetPrimitiveVariables(descriptor, params, &variables_);
-}
-
-PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
-
-bool PrimitiveFieldGenerator::SavedDefaultNeeded() const {
-  return variables_.find("default_constant") != variables_.end();
-}
-
-void PrimitiveFieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const {
-  if (variables_.find("default_constant") != variables_.end()) {
-    printer->Print(variables_,
-      "$default_constant$ = $default_constant_value$;\n");
-  }
-}
-
-void PrimitiveFieldGenerator::
-GenerateMembers(io::Printer* printer, bool lazy_init) const {
-  if (variables_.find("default_constant") != variables_.end()) {
-    // Those primitive types that need a saved default.
-    if (lazy_init) {
-      printer->Print(variables_,
-        "private static $type$ $default_constant$;\n");
-    } else {
-      printer->Print(variables_,
-        "private static final $type$ $default_constant$ =\n"
-        "    $default_constant_value$;\n");
-    }
-  }
-
-  printer->Print(variables_,
-    "public $type$ $name$;\n");
-
-  if (params_.generate_has()) {
-    printer->Print(variables_,
-      "public boolean has$capitalized_name$;\n");
-  }
-}
-
-void PrimitiveFieldGenerator::
-GenerateClearCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "$name$ = $default_copy_if_needed$;\n");
-
-  if (params_.generate_has()) {
-    printer->Print(variables_,
-      "has$capitalized_name$ = false;\n");
-  }
-}
-
-void PrimitiveFieldGenerator::
-GenerateMergingCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "this.$name$ = input.read$capitalized_type$();\n");
-
-  if (params_.generate_has()) {
-    printer->Print(variables_,
-      "has$capitalized_name$ = true;\n");
-  }
-}
-
-void PrimitiveFieldGenerator::
-GenerateSerializationConditional(io::Printer* printer) const {
-  if (params_.use_reference_types_for_primitives()) {
-    // For reference type mode, serialize based on equality
-    // to null.
-    printer->Print(variables_,
-      "if (this.$name$ != null) {\n");
-    return;
-  }
-  if (params_.generate_has()) {
-    printer->Print(variables_,
-      "if (has$capitalized_name$ || ");
-  } else {
-    printer->Print(variables_,
-      "if (");
-  }
-  JavaType java_type = GetJavaType(descriptor_);
-  if (IsArrayType(java_type)) {
-    printer->Print(variables_,
-      "!java.util.Arrays.equals(this.$name$, $default$)) {\n");
-  } else if (IsReferenceType(java_type)) {
-    printer->Print(variables_,
-      "!this.$name$.equals($default$)) {\n");
-  } else if (java_type == JAVATYPE_FLOAT) {
-    printer->Print(variables_,
-      "java.lang.Float.floatToIntBits(this.$name$)\n"
-      "    != java.lang.Float.floatToIntBits($default$)) {\n");
-  } else if (java_type == JAVATYPE_DOUBLE) {
-    printer->Print(variables_,
-      "java.lang.Double.doubleToLongBits(this.$name$)\n"
-      "    != java.lang.Double.doubleToLongBits($default$)) {\n");
-  } else {
-    printer->Print(variables_,
-      "this.$name$ != $default$) {\n");
-  }
-}
-
-void PrimitiveFieldGenerator::
-GenerateSerializationCode(io::Printer* printer) const {
-  if (descriptor_->is_required() && !params_.generate_has()) {
-    // Always serialize a required field if we don't have the 'has' signal.
-    printer->Print(variables_,
-      "output.write$capitalized_type$($number$, this.$name$);\n");
-  } else {
-    GenerateSerializationConditional(printer);
-    printer->Print(variables_,
-      "  output.write$capitalized_type$($number$, this.$name$);\n"
-      "}\n");
-  }
-}
-
-void PrimitiveFieldGenerator::
-GenerateSerializedSizeCode(io::Printer* printer) const {
-  if (descriptor_->is_required() && !params_.generate_has()) {
-    printer->Print(variables_,
-      "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
-      "    .compute$capitalized_type$Size($number$, this.$name$);\n");
-  } else {
-    GenerateSerializationConditional(printer);
-    printer->Print(variables_,
-      "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
-      "      .compute$capitalized_type$Size($number$, this.$name$);\n"
-      "}\n");
-  }
-}
-
-void RepeatedPrimitiveFieldGenerator::
-GenerateFixClonedCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (this.$name$ != null && this.$name$.length > 0) {\n"
-    "  cloned.$name$ = this.$name$.clone();\n"
-    "}\n");
-}
-
-void PrimitiveFieldGenerator::
-GenerateEqualsCode(io::Printer* printer) const {
-  // We define equality as serialized form equality. If generate_has(),
-  // then if the field value equals the default value in both messages,
-  // but one's 'has' field is set and the other's is not, the serialized
-  // forms are different and we should return false.
-  JavaType java_type = GetJavaType(descriptor_);
-  if (java_type == JAVATYPE_BYTES) {
-    printer->Print(variables_,
-      "if (!java.util.Arrays.equals(this.$name$, other.$name$)");
-    if (params_.generate_has()) {
-      printer->Print(variables_,
-        "\n"
-        "    || (java.util.Arrays.equals(this.$name$, $default$)\n"
-        "        && this.has$capitalized_name$ != other.has$capitalized_name$)");
-    }
-    printer->Print(") {\n"
-      "  return false;\n"
-      "}\n");
-  } else if (java_type == JAVATYPE_STRING
-      || params_.use_reference_types_for_primitives()) {
-    printer->Print(variables_,
-      "if (this.$name$ == null) {\n"
-      "  if (other.$name$ != null) {\n"
-      "    return false;\n"
-      "  }\n"
-      "} else if (!this.$name$.equals(other.$name$)");
-    if (params_.generate_has()) {
-      printer->Print(variables_,
-        "\n"
-        "    || (this.$name$.equals($default$)\n"
-        "        && this.has$capitalized_name$ != other.has$capitalized_name$)");
-    }
-    printer->Print(") {\n"
-      "  return false;\n"
-      "}\n");
-  } else if (java_type == JAVATYPE_FLOAT) {
-    printer->Print(variables_,
-      "{\n"
-      "  int bits = java.lang.Float.floatToIntBits(this.$name$);\n"
-      "  if (bits != java.lang.Float.floatToIntBits(other.$name$)");
-    if (params_.generate_has()) {
-      printer->Print(variables_,
-        "\n"
-        "      || (bits == java.lang.Float.floatToIntBits($default$)\n"
-        "          && this.has$capitalized_name$ != other.has$capitalized_name$)");
-    }
-    printer->Print(") {\n"
-      "    return false;\n"
-      "  }\n"
-      "}\n");
-  } else if (java_type == JAVATYPE_DOUBLE) {
-    printer->Print(variables_,
-      "{\n"
-      "  long bits = java.lang.Double.doubleToLongBits(this.$name$);\n"
-      "  if (bits != java.lang.Double.doubleToLongBits(other.$name$)");
-    if (params_.generate_has()) {
-      printer->Print(variables_,
-        "\n"
-        "      || (bits == java.lang.Double.doubleToLongBits($default$)\n"
-        "          && this.has$capitalized_name$ != other.has$capitalized_name$)");
-    }
-    printer->Print(") {\n"
-      "    return false;\n"
-      "  }\n"
-      "}\n");
-  } else {
-    printer->Print(variables_,
-      "if (this.$name$ != other.$name$");
-    if (params_.generate_has()) {
-      printer->Print(variables_,
-        "\n"
-        "    || (this.$name$ == $default$\n"
-        "        && this.has$capitalized_name$ != other.has$capitalized_name$)");
-    }
-    printer->Print(") {\n"
-      "  return false;\n"
-      "}\n");
-  }
-}
-
-void PrimitiveFieldGenerator::
-GenerateHashCodeCode(io::Printer* printer) const {
-  JavaType java_type = GetJavaType(descriptor_);
-  if (java_type == JAVATYPE_BYTES) {
-    printer->Print(variables_,
-      "result = 31 * result + java.util.Arrays.hashCode(this.$name$);\n");
-  } else if (java_type == JAVATYPE_STRING
-      || params_.use_reference_types_for_primitives()) {
-    printer->Print(variables_,
-      "result = 31 * result\n"
-      "    + (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
-  } else {
-    switch (java_type) {
-      // For all Java primitive types below, the hash codes match the
-      // results of BoxedType.valueOf(primitiveValue).hashCode().
-      case JAVATYPE_INT:
-        printer->Print(variables_,
-          "result = 31 * result + this.$name$;\n");
-        break;
-      case JAVATYPE_LONG:
-        printer->Print(variables_,
-          "result = 31 * result\n"
-          "    + (int) (this.$name$ ^ (this.$name$ >>> 32));\n");
-        break;
-      case JAVATYPE_FLOAT:
-        printer->Print(variables_,
-          "result = 31 * result\n"
-          "    + java.lang.Float.floatToIntBits(this.$name$);\n");
-        break;
-      case JAVATYPE_DOUBLE:
-        printer->Print(variables_,
-          "{\n"
-          "  long v = java.lang.Double.doubleToLongBits(this.$name$);\n"
-          "  result = 31 * result + (int) (v ^ (v >>> 32));\n"
-          "}\n");
-        break;
-      case JAVATYPE_BOOLEAN:
-        printer->Print(variables_,
-          "result = 31 * result + (this.$name$ ? 1231 : 1237);\n");
-        break;
-      default:
-        GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
-        break;
-    }
-  }
-}
-
-// ===================================================================
-
-AccessorPrimitiveFieldGenerator::
-AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
-     const Params& params, int has_bit_index)
-  : FieldGenerator(params), descriptor_(descriptor) {
-  SetPrimitiveVariables(descriptor, params, &variables_);
-  SetBitOperationVariables("has", has_bit_index, &variables_);
-}
-
-AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {}
-
-bool AccessorPrimitiveFieldGenerator::SavedDefaultNeeded() const {
-  return variables_.find("default_constant") != variables_.end();
-}
-
-void AccessorPrimitiveFieldGenerator::
-GenerateInitSavedDefaultCode(io::Printer* printer) const {
-  if (variables_.find("default_constant") != variables_.end()) {
-    printer->Print(variables_,
-      "$default_constant$ = $default_constant_value$;\n");
-  }
-}
-
-void AccessorPrimitiveFieldGenerator::
-GenerateMembers(io::Printer* printer, bool lazy_init) const {
-  if (variables_.find("default_constant") != variables_.end()) {
-    // Those primitive types that need a saved default.
-    if (lazy_init) {
-      printer->Print(variables_,
-        "private static $type$ $default_constant$;\n");
-    } else {
-      printer->Print(variables_,
-        "private static final $type$ $default_constant$ =\n"
-        "    $default_constant_value$;\n");
-    }
-  }
-  printer->Print(variables_,
-    "private $type$ $name$_;\n"
-    "public $type$ get$capitalized_name$() {\n"
-    "  return $name$_;\n"
-    "}\n"
-    "public $message_name$ set$capitalized_name$($type$ value) {\n");
-  if (IsReferenceType(GetJavaType(descriptor_))) {
-    printer->Print(variables_,
-      "  if (value == null) {\n"
-      "    throw new java.lang.NullPointerException();\n"
-      "  }\n");
-  }
-  printer->Print(variables_,
-    "  $name$_ = value;\n"
-    "  $set_has$;\n"
-    "  return this;\n"
-    "}\n"
-    "public boolean has$capitalized_name$() {\n"
-    "  return $get_has$;\n"
-    "}\n"
-    "public $message_name$ clear$capitalized_name$() {\n"
-    "  $name$_ = $default_copy_if_needed$;\n"
-    "  $clear_has$;\n"
-    "  return this;\n"
-    "}\n");
-}
-
-void AccessorPrimitiveFieldGenerator::
-GenerateClearCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "$name$_ = $default_copy_if_needed$;\n");
-}
-
-void AccessorPrimitiveFieldGenerator::
-GenerateMergingCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "$name$_ = input.read$capitalized_type$();\n"
-    "$set_has$;\n");
-}
-
-void AccessorPrimitiveFieldGenerator::
-GenerateSerializationCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if ($get_has$) {\n"
-    "  output.write$capitalized_type$($number$, $name$_);\n"
-    "}\n");
-}
-
-void AccessorPrimitiveFieldGenerator::
-GenerateSerializedSizeCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if ($get_has$) {\n"
-    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
-    "      .compute$capitalized_type$Size($number$, $name$_);\n"
-    "}\n");
-}
-
-void AccessorPrimitiveFieldGenerator::
-GenerateEqualsCode(io::Printer* printer) const {
-  switch (GetJavaType(descriptor_)) {
-    // For all Java primitive types below, the equality checks match the
-    // results of BoxedType.valueOf(primitiveValue).equals(otherValue).
-    case JAVATYPE_FLOAT:
-      printer->Print(variables_,
-        "if ($different_has$\n"
-        "    || java.lang.Float.floatToIntBits($name$_)\n"
-        "        != java.lang.Float.floatToIntBits(other.$name$_)) {\n"
-        "  return false;\n"
-        "}\n");
-      break;
-    case JAVATYPE_DOUBLE:
-      printer->Print(variables_,
-        "if ($different_has$\n"
-        "    || java.lang.Double.doubleToLongBits($name$_)\n"
-        "        != java.lang.Double.doubleToLongBits(other.$name$_)) {\n"
-        "  return false;\n"
-        "}\n");
-      break;
-    case JAVATYPE_INT:
-    case JAVATYPE_LONG:
-    case JAVATYPE_BOOLEAN:
-      printer->Print(variables_,
-        "if ($different_has$\n"
-        "    || $name$_ != other.$name$_) {\n"
-        "  return false;\n"
-        "}\n");
-      break;
-    case JAVATYPE_STRING:
-      // Accessor style would guarantee $name$_ non-null
-      printer->Print(variables_,
-        "if ($different_has$\n"
-        "    || !$name$_.equals(other.$name$_)) {\n"
-        "  return false;\n"
-        "}\n");
-      break;
-    case JAVATYPE_BYTES:
-      // Accessor style would guarantee $name$_ non-null
-      printer->Print(variables_,
-        "if ($different_has$\n"
-        "    || !java.util.Arrays.equals($name$_, other.$name$_)) {\n"
-        "  return false;\n"
-        "}\n");
-      break;
-    default:
-      GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
-      break;
-  }
-}
-
-void AccessorPrimitiveFieldGenerator::
-GenerateHashCodeCode(io::Printer* printer) const {
-  switch (GetJavaType(descriptor_)) {
-    // For all Java primitive types below, the hash codes match the
-    // results of BoxedType.valueOf(primitiveValue).hashCode().
-    case JAVATYPE_INT:
-      printer->Print(variables_,
-        "result = 31 * result + $name$_;\n");
-      break;
-    case JAVATYPE_LONG:
-      printer->Print(variables_,
-        "result = 31 * result + (int) ($name$_ ^ ($name$_ >>> 32));\n");
-      break;
-    case JAVATYPE_FLOAT:
-      printer->Print(variables_,
-        "result = 31 * result +\n"
-        "    java.lang.Float.floatToIntBits($name$_);\n");
-      break;
-    case JAVATYPE_DOUBLE:
-      printer->Print(variables_,
-        "{\n"
-        "  long v = java.lang.Double.doubleToLongBits($name$_);\n"
-        "  result = 31 * result + (int) (v ^ (v >>> 32));\n"
-        "}\n");
-      break;
-    case JAVATYPE_BOOLEAN:
-      printer->Print(variables_,
-        "result = 31 * result + ($name$_ ? 1231 : 1237);\n");
-      break;
-    case JAVATYPE_STRING:
-      // Accessor style would guarantee $name$_ non-null
-      printer->Print(variables_,
-        "result = 31 * result + $name$_.hashCode();\n");
-      break;
-    case JAVATYPE_BYTES:
-      // Accessor style would guarantee $name$_ non-null
-      printer->Print(variables_,
-        "result = 31 * result + java.util.Arrays.hashCode($name$_);\n");
-      break;
-    default:
-      GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
-      break;
-  }
-}
-
-// ===================================================================
-
-PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
-    const FieldDescriptor* descriptor, const Params& params)
-  : FieldGenerator(params), descriptor_(descriptor) {
-    SetPrimitiveVariables(descriptor, params, &variables_);
-    SetCommonOneofVariables(descriptor, &variables_);
-}
-
-PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
-
-void PrimitiveOneofFieldGenerator::GenerateMembers(
-    io::Printer* printer, bool /*unused lazy_init*/) const {
-  printer->Print(variables_,
-    "public boolean has$capitalized_name$() {\n"
-    "  return $has_oneof_case$;\n"
-    "}\n"
-    "public $type$ get$capitalized_name$() {\n"
-    "  if ($has_oneof_case$) {\n"
-    "    return ($type$) ($boxed_type$) this.$oneof_name$_;\n"
-    "  }\n"
-    "  return $default$;\n"
-    "}\n"
-    "public $message_name$ set$capitalized_name$($type$ value) {\n"
-    "  $set_oneof_case$;\n"
-    "  this.$oneof_name$_ = value;\n"
-    "  return this;\n"
-    "}\n");
-}
-
-void PrimitiveOneofFieldGenerator::GenerateClearCode(
-    io::Printer* printer) const {
-  // No clear method for oneof fields.
-}
-
-void PrimitiveOneofFieldGenerator::GenerateMergingCode(
-    io::Printer* printer) const {
-  printer->Print(variables_,
-    "this.$oneof_name$_ = input.read$capitalized_type$();\n"
-    "$set_oneof_case$;\n");
-}
-
-void PrimitiveOneofFieldGenerator::GenerateSerializationCode(
-    io::Printer* printer) const {
-  printer->Print(variables_,
-    "if ($has_oneof_case$) {\n"
-    "  output.write$capitalized_type$(\n"
-    "      $number$, ($boxed_type$) this.$oneof_name$_);\n"
-    "}\n");
-}
-
-void PrimitiveOneofFieldGenerator::GenerateSerializedSizeCode(
-    io::Printer* printer) const {
-  printer->Print(variables_,
-    "if ($has_oneof_case$) {\n"
-    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
-    "      .compute$capitalized_type$Size(\n"
-    "          $number$, ($boxed_type$) this.$oneof_name$_);\n"
-    "}\n");
-}
-
-void PrimitiveOneofFieldGenerator::GenerateEqualsCode(
-    io::Printer* printer) const {
-  GenerateOneofFieldEquals(descriptor_, variables_, printer);
-}
-
-void PrimitiveOneofFieldGenerator::GenerateHashCodeCode(
-    io::Printer* printer) const {
-  GenerateOneofFieldHashCode(descriptor_, variables_, printer);
-}
-
-// ===================================================================
-
-RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
-    const FieldDescriptor* descriptor, const Params& params)
-  : FieldGenerator(params), descriptor_(descriptor) {
-  SetPrimitiveVariables(descriptor, params, &variables_);
-}
-
-RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
-
-void RepeatedPrimitiveFieldGenerator::
-GenerateMembers(io::Printer* printer, bool /*unused init_defaults*/) const {
-  printer->Print(variables_,
-    "public $type$[] $name$;\n");
-}
-
-void RepeatedPrimitiveFieldGenerator::
-GenerateClearCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "$name$ = $default$;\n");
-}
-
-void RepeatedPrimitiveFieldGenerator::
-GenerateMergingCode(io::Printer* printer) const {
-  // First, figure out the length of the array, then parse.
-  printer->Print(variables_,
-    "int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
-    "    .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n"
-    "int i = this.$name$ == null ? 0 : this.$name$.length;\n");
-
-  if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
-    printer->Print(variables_,
-      "byte[][] newArray = new byte[i + arrayLength][];\n");
-  } else {
-    printer->Print(variables_,
-      "$type$[] newArray = new $type$[i + arrayLength];\n");
-  }
-  printer->Print(variables_,
-    "if (i != 0) {\n"
-    "  java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
-    "}\n"
-    "for (; i < newArray.length - 1; i++) {\n"
-    "  newArray[i] = input.read$capitalized_type$();\n"
-    "  input.readTag();\n"
-    "}\n"
-    "// Last one without readTag.\n"
-    "newArray[i] = input.read$capitalized_type$();\n"
-    "this.$name$ = newArray;\n");
-}
-
-void RepeatedPrimitiveFieldGenerator::
-GenerateMergingCodeFromPacked(io::Printer* printer) const {
-  printer->Print(
-    "int length = input.readRawVarint32();\n"
-    "int limit = input.pushLimit(length);\n");
-
-  // If we know the elements will all be of the same size, the arrayLength
-  // can be calculated much more easily. However, FixedSize() returns 1 for
-  // repeated bool fields, which are guaranteed to have the fixed size of
-  // 1 byte per value only if we control the output. On the wire they can
-  // legally appear as variable-size integers, so we need to use the slow
-  // way for repeated bool fields.
-  if (descriptor_->type() == FieldDescriptor::TYPE_BOOL
-      || FixedSize(descriptor_->type()) == -1) {
-    printer->Print(variables_,
-      "// First pass to compute array length.\n"
-      "int arrayLength = 0;\n"
-      "int startPos = input.getPosition();\n"
-      "while (input.getBytesUntilLimit() > 0) {\n"
-      "  input.read$capitalized_type$();\n"
-      "  arrayLength++;\n"
-      "}\n"
-      "input.rewindToPosition(startPos);\n");
-  } else {
-    printer->Print(variables_,
-      "int arrayLength = length / $fixed_size$;\n");
-  }
-
-  printer->Print(variables_,
-    "int i = this.$name$ == null ? 0 : this.$name$.length;\n"
-    "$type$[] newArray = new $type$[i + arrayLength];\n"
-    "if (i != 0) {\n"
-    "  java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
-    "}\n"
-    "for (; i < newArray.length; i++) {\n"
-    "  newArray[i] = input.read$capitalized_type$();\n"
-    "}\n"
-    "this.$name$ = newArray;\n"
-    "input.popLimit(limit);\n");
-}
-
-void RepeatedPrimitiveFieldGenerator::
-GenerateRepeatedDataSizeCode(io::Printer* printer) const {
-  // Creates a variable dataSize and puts the serialized size in there.
-  // If the element type is a Java reference type, also generates
-  // dataCount which stores the number of non-null elements in the field.
-  if (IsReferenceType(GetJavaType(descriptor_))) {
-    printer->Print(variables_,
-      "int dataCount = 0;\n"
-      "int dataSize = 0;\n"
-      "for (int i = 0; i < this.$name$.length; i++) {\n"
-      "  $type$ element = this.$name$[i];\n"
-      "  if (element != null) {\n"
-      "    dataCount++;\n"
-      "    dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
-      "        .compute$capitalized_type$SizeNoTag(element);\n"
-      "  }\n"
-      "}\n");
-  } else if (FixedSize(descriptor_->type()) == -1) {
-    printer->Print(variables_,
-      "int dataSize = 0;\n"
-      "for (int i = 0; i < this.$name$.length; i++) {\n"
-      "  $type$ element = this.$name$[i];\n"
-      "  dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
-      "      .compute$capitalized_type$SizeNoTag(element);\n"
-      "}\n");
-  } else {
-    printer->Print(variables_,
-      "int dataSize = $fixed_size$ * this.$name$.length;\n");
-  }
-}
-
-void RepeatedPrimitiveFieldGenerator::
-GenerateSerializationCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (this.$name$ != null && this.$name$.length > 0) {\n");
-  printer->Indent();
-
-  if (descriptor_->is_packable() && descriptor_->options().packed()) {
-    GenerateRepeatedDataSizeCode(printer);
-    printer->Print(variables_,
-      "output.writeRawVarint32($tag$);\n"
-      "output.writeRawVarint32(dataSize);\n"
-      "for (int i = 0; i < this.$name$.length; i++) {\n"
-      "  output.write$capitalized_type$NoTag(this.$name$[i]);\n"
-      "}\n");
-  } else if (IsReferenceType(GetJavaType(descriptor_))) {
-    printer->Print(variables_,
-      "for (int i = 0; i < this.$name$.length; i++) {\n"
-      "  $type$ element = this.$name$[i];\n"
-      "  if (element != null) {\n"
-      "    output.write$capitalized_type$($number$, element);\n"
-      "  }\n"
-      "}\n");
-  } else {
-    printer->Print(variables_,
-      "for (int i = 0; i < this.$name$.length; i++) {\n"
-      "  output.write$capitalized_type$($number$, this.$name$[i]);\n"
-      "}\n");
-  }
-
-  printer->Outdent();
-  printer->Print("}\n");
-}
-
-void RepeatedPrimitiveFieldGenerator::
-GenerateSerializedSizeCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (this.$name$ != null && this.$name$.length > 0) {\n");
-  printer->Indent();
-
-  GenerateRepeatedDataSizeCode(printer);
-
-  printer->Print(
-    "size += dataSize;\n");
-  if (descriptor_->is_packable() && descriptor_->options().packed()) {
-    printer->Print(variables_,
-      "size += $tag_size$;\n"
-      "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
-      "    .computeRawVarint32Size(dataSize);\n");
-  } else if (IsReferenceType(GetJavaType(descriptor_))) {
-    printer->Print(variables_,
-      "size += $tag_size$ * dataCount;\n");
-  } else {
-    printer->Print(variables_,
-      "size += $tag_size$ * this.$name$.length;\n");
-  }
-
-  printer->Outdent();
-
-  printer->Print(
-    "}\n");
-}
-
-void RepeatedPrimitiveFieldGenerator::
-GenerateEqualsCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "if (!com.google.protobuf.nano.InternalNano.equals(\n"
-    "    this.$name$, other.$name$)) {\n"
-    "  return false;\n"
-    "}\n");
-}
-
-void RepeatedPrimitiveFieldGenerator::
-GenerateHashCodeCode(io::Printer* printer) const {
-  printer->Print(variables_,
-    "result = 31 * result\n"
-    "    + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
-}
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
deleted file mode 100644
index a01981d..0000000
--- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
+++ /dev/null
@@ -1,150 +0,0 @@
-// 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)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__
-
-#include <map>
-#include <string>
-#include <google/protobuf/compiler/javanano/javanano_field.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javanano {
-
-class PrimitiveFieldGenerator : public FieldGenerator {
- public:
-  explicit PrimitiveFieldGenerator(
-      const FieldDescriptor* descriptor, const Params& params);
-  ~PrimitiveFieldGenerator();
-
-  // implements FieldGenerator ---------------------------------------
-  bool SavedDefaultNeeded() const;
-  void GenerateInitSavedDefaultCode(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
-  void GenerateClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCodeCode(io::Printer* printer) const;
-
- private:
-  void GenerateSerializationConditional(io::Printer* printer) const;
-
-  const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
-};
-
-class AccessorPrimitiveFieldGenerator : public FieldGenerator {
- public:
-  explicit AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
-      const Params &params, int has_bit_index);
-  ~AccessorPrimitiveFieldGenerator();
-
-  // implements FieldGenerator ---------------------------------------
-  bool SavedDefaultNeeded() const;
-  void GenerateInitSavedDefaultCode(io::Printer* printer) const;
-  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
-  void GenerateClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCodeCode(io::Printer* printer) const;
-
- private:
-  const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorPrimitiveFieldGenerator);
-};
-
-class PrimitiveOneofFieldGenerator : public FieldGenerator {
- public:
-  explicit PrimitiveOneofFieldGenerator(
-      const FieldDescriptor* descriptor, const Params& params);
-  ~PrimitiveOneofFieldGenerator();
-
-  // implements FieldGenerator ---------------------------------------
-  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
-  void GenerateClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCodeCode(io::Printer* printer) const;
-
- private:
-  const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator);
-};
-
-class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
- public:
-  explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
-                                           const Params& params);
-  ~RepeatedPrimitiveFieldGenerator();
-
-  // implements FieldGenerator ---------------------------------------
-  void GenerateMembers(io::Printer* printer, bool lazy_init) const;
-  void GenerateClearCode(io::Printer* printer) const;
-  void GenerateMergingCode(io::Printer* printer) const;
-  void GenerateMergingCodeFromPacked(io::Printer* printer) const;
-  void GenerateSerializationCode(io::Printer* printer) const;
-  void GenerateSerializedSizeCode(io::Printer* printer) const;
-  void GenerateEqualsCode(io::Printer* printer) const;
-  void GenerateHashCodeCode(io::Printer* printer) const;
-  void GenerateFixClonedCode(io::Printer* printer) const;
-
- private:
-  void GenerateRepeatedDataSizeCode(io::Printer* printer) const;
-
-  const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
-};
-
-}  // namespace javanano
-}  // namespace compiler
-}  // namespace protobuf
-
-}  // namespace google
-#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__
diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc
index e6c3b36..b5771f2 100755
--- a/src/google/protobuf/compiler/js/js_generator.cc
+++ b/src/google/protobuf/compiler/js/js_generator.cc
@@ -35,9 +35,6 @@
 #include <limits>
 #include <map>
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 #include <string>
 #include <utility>
 #include <vector>
@@ -45,12 +42,14 @@
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/compiler/js/well_known_types_embed.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/stubs/strutil.h>
 
+
 namespace google {
 namespace protobuf {
 namespace compiler {
@@ -123,6 +122,16 @@
 
 namespace {
 
+// The mode of operation for bytes fields. Historically JSPB always carried
+// bytes as JS {string}, containing base64 content by convention. With binary
+// and proto3 serialization the new convention is to represent it as binary
+// data in Uint8Array. See b/26173701 for background on the migration.
+enum BytesMode {
+  BYTES_DEFAULT,  // Default type for getBytesField to return.
+  BYTES_B64,      // Explicitly coerce to base64 string where needed.
+  BYTES_U8,       // Explicitly coerce to Uint8Array where needed.
+};
+
 bool IsReserved(const string& ident) {
   for (int i = 0; i < kNumKeyword; i++) {
     if (ident == kKeyword[i]) {
@@ -132,18 +141,68 @@
   return false;
 }
 
+bool StrEndsWith(StringPiece sp, StringPiece x) {
+  return sp.size() >= x.size() && sp.substr(sp.size() - x.size()) == x;
+}
+
 // Returns a copy of |filename| with any trailing ".protodevel" or ".proto
 // suffix stripped.
+// TODO(haberman): Unify with copy in compiler/cpp/internal/helpers.cc.
 string StripProto(const string& filename) {
-  const char* suffix = HasSuffixString(filename, ".protodevel")
-      ? ".protodevel" : ".proto";
+  const char* suffix =
+      StrEndsWith(filename, ".protodevel") ? ".protodevel" : ".proto";
   return StripSuffixString(filename, suffix);
 }
 
+// Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript
+// file foo/bar/baz.js.
+string GetJSFilename(const GeneratorOptions& options, const string& filename) {
+  return StripProto(filename) + options.GetFileNameExtension();
+}
+
+// Given a filename like foo/bar/baz.proto, returns the root directory
+// path ../../
+string GetRootPath(const string& from_filename, const string& to_filename) {
+  if (to_filename.find("google/protobuf") == 0) {
+    // Well-known types (.proto files in the google/protobuf directory) are
+    // assumed to come from the 'google-protobuf' npm package.  We may want to
+    // generalize this exception later by letting others put generated code in
+    // their own npm packages.
+    return "google-protobuf/";
+  }
+
+  size_t slashes = std::count(from_filename.begin(), from_filename.end(), '/');
+  if (slashes == 0) {
+    return "./";
+  }
+  string result = "";
+  for (size_t i = 0; i < slashes; i++) {
+    result += "../";
+  }
+  return result;
+}
+
+// Returns the alias we assign to the module of the given .proto filename
+// when importing.
+string ModuleAlias(const string& filename) {
+  // This scheme could technically cause problems if a file includes any 2 of:
+  //   foo/bar_baz.proto
+  //   foo_bar_baz.proto
+  //   foo_bar/baz.proto
+  //
+  // We'll worry about this problem if/when we actually see it.  This name isn't
+  // exposed to users so we can change it later if we need to.
+  string basename = StripProto(filename);
+  ReplaceCharacters(&basename, "-", '$');
+  ReplaceCharacters(&basename, "/", '_');
+  ReplaceCharacters(&basename, ".", '_');
+  return basename + "_pb";
+}
+
 // Returns the fully normalized JavaScript path for the given
 // file descriptor's package.
-string GetPath(const GeneratorOptions& options,
-               const FileDescriptor* file) {
+string GetFilePath(const GeneratorOptions& options,
+                   const FileDescriptor* file) {
   if (!options.namespace_prefix.empty()) {
     return options.namespace_prefix;
   } else if (!file->package().empty()) {
@@ -153,66 +212,87 @@
   }
 }
 
-// Forward declare, so that GetPrefix can call this method,
-// which in turn, calls GetPrefix.
-string GetPath(const GeneratorOptions& options,
-               const Descriptor* descriptor);
+// Returns the name of the message with a leading dot and taking into account
+// nesting, for example ".OuterMessage.InnerMessage", or returns empty if
+// descriptor is null. This function does not handle namespacing, only message
+// nesting.
+string GetNestedMessageName(const Descriptor* descriptor) {
+  if (descriptor == NULL) {
+    return "";
+  }
+  string result =
+      StripPrefixString(descriptor->full_name(), descriptor->file()->package());
+  // Add a leading dot if one is not already present.
+  if (!result.empty() && result[0] != '.') {
+    result = "." + result;
+  }
+  return result;
+}
 
 // Returns the path prefix for a message or enumeration that
 // lives under the given file and containing type.
 string GetPrefix(const GeneratorOptions& options,
                  const FileDescriptor* file_descriptor,
                  const Descriptor* containing_type) {
-  string prefix = "";
-
-  if (containing_type == NULL) {
-    prefix = GetPath(options, file_descriptor);
-  } else {
-    prefix = GetPath(options, containing_type);
-  }
-
+  string prefix = GetFilePath(options, file_descriptor) +
+                  GetNestedMessageName(containing_type);
   if (!prefix.empty()) {
     prefix += ".";
   }
-
   return prefix;
 }
 
+// Returns the fully normalized JavaScript path prefix for the given
+// message descriptor.
+string GetMessagePathPrefix(const GeneratorOptions& options,
+                            const Descriptor* descriptor) {
+  return GetPrefix(
+      options, descriptor->file(),
+      descriptor->containing_type());
+}
 
 // Returns the fully normalized JavaScript path for the given
 // message descriptor.
-string GetPath(const GeneratorOptions& options,
-               const Descriptor* descriptor) {
-  return GetPrefix(
-      options, descriptor->file(),
-      descriptor->containing_type()) + descriptor->name();
+string GetMessagePath(const GeneratorOptions& options,
+                      const Descriptor* descriptor) {
+  return GetMessagePathPrefix(options, descriptor) + descriptor->name();
 }
 
-
-// Returns the fully normalized JavaScript path for the given
-// field's containing message descriptor.
-string GetPath(const GeneratorOptions& options,
-               const FieldDescriptor* descriptor) {
-  return GetPath(options, descriptor->containing_type());
+// Returns the fully normalized JavaScript path prefix for the given
+// enumeration descriptor.
+string GetEnumPathPrefix(const GeneratorOptions& options,
+                   const EnumDescriptor* enum_descriptor) {
+  return GetPrefix(options, enum_descriptor->file(),
+      enum_descriptor->containing_type());
 }
 
 // Returns the fully normalized JavaScript path for the given
 // enumeration descriptor.
-string GetPath(const GeneratorOptions& options,
-               const EnumDescriptor* enum_descriptor) {
-  return GetPrefix(
-      options, enum_descriptor->file(),
-      enum_descriptor->containing_type()) + enum_descriptor->name();
+string GetEnumPath(const GeneratorOptions& options,
+                   const EnumDescriptor* enum_descriptor) {
+  return GetEnumPathPrefix(options, enum_descriptor) + enum_descriptor->name();
 }
 
+string MaybeCrossFileRef(const GeneratorOptions& options,
+                         const FileDescriptor* from_file,
+                         const Descriptor* to_message) {
+  if (options.import_style == GeneratorOptions::kImportCommonJs &&
+      from_file != to_message->file()) {
+    // Cross-file ref in CommonJS needs to use the module alias instead of
+    // the global name.
+    return ModuleAlias(to_message->file()->name()) +
+           GetNestedMessageName(to_message->containing_type()) + "." +
+           to_message->name();
+  } else {
+    // Within a single file we use a full name.
+    return GetMessagePath(options, to_message);
+  }
+}
 
-// Returns the fully normalized JavaScript path for the given
-// enumeration value descriptor.
-string GetPath(const GeneratorOptions& options,
-               const EnumValueDescriptor* value_descriptor) {
-  return GetPath(
-      options,
-      value_descriptor->type()) + "." + value_descriptor->name();
+string SubmessageTypeRef(const GeneratorOptions& options,
+                         const FieldDescriptor* field) {
+  GOOGLE_CHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE);
+  return MaybeCrossFileRef(options, field->file(), field->message_type());
 }
 
 // - Object field name: LOWER_UNDERSCORE -> LOWER_CAMEL, except for group fields
@@ -232,8 +312,8 @@
   }
 }
 
-vector<string> ParseLowerUnderscore(const string& input) {
-  vector<string> words;
+std::vector<string> ParseLowerUnderscore(const string& input) {
+  std::vector<string> words;
   string running = "";
   for (int i = 0; i < input.size(); i++) {
     if (input[i] == '_') {
@@ -251,8 +331,8 @@
   return words;
 }
 
-vector<string> ParseUpperCamel(const string& input) {
-  vector<string> words;
+std::vector<string> ParseUpperCamel(const string& input) {
+  std::vector<string> words;
   string running = "";
   for (int i = 0; i < input.size(); i++) {
     if (input[i] >= 'A' && input[i] <= 'Z' && !running.empty()) {
@@ -267,7 +347,7 @@
   return words;
 }
 
-string ToLowerCamel(const vector<string>& words) {
+string ToLowerCamel(const std::vector<string>& words) {
   string result;
   for (int i = 0; i < words.size(); i++) {
     string word = words[i];
@@ -281,7 +361,7 @@
   return result;
 }
 
-string ToUpperCamel(const vector<string>& words) {
+string ToUpperCamel(const std::vector<string>& words) {
   string result;
   for (int i = 0; i < words.size(); i++) {
     string word = words[i];
@@ -326,16 +406,66 @@
   return result;
 }
 
+// When we're generating one output file per type name, this is the filename
+// that top-level extensions should go in.
+string GetExtensionFileName(const GeneratorOptions& options,
+                            const FileDescriptor* file) {
+  return options.output_dir + "/" + ToFileName(GetFilePath(options, file)) +
+         options.GetFileNameExtension();
+}
+
+// When we're generating one output file per type name, this is the filename
+// that a top-level message should go in.
+string GetMessageFileName(const GeneratorOptions& options,
+                          const Descriptor* desc) {
+  return options.output_dir + "/" + ToFileName(desc->name()) +
+         options.GetFileNameExtension();
+}
+
+// When we're generating one output file per type name, this is the filename
+// that a top-level message should go in.
+string GetEnumFileName(const GeneratorOptions& options,
+                       const EnumDescriptor* desc) {
+  return options.output_dir + "/" + ToFileName(desc->name()) +
+         options.GetFileNameExtension();
+}
+
 // Returns the message/response ID, if set.
 string GetMessageId(const Descriptor* desc) {
   return string();
 }
 
+bool IgnoreExtensionField(const FieldDescriptor* field) {
+  // Exclude descriptor extensions from output "to avoid clutter" (from original
+  // codegen).
+  return field->is_extension() &&
+         field->containing_type()->file()->name() ==
+             "google/protobuf/descriptor.proto";
+}
+
 
 // Used inside Google only -- do not remove.
 bool IsResponse(const Descriptor* desc) { return false; }
-bool IgnoreField(const FieldDescriptor* field) { return false; }
 
+bool IgnoreField(const FieldDescriptor* field) {
+  return IgnoreExtensionField(field);
+}
+
+
+// Used inside Google only -- do not remove.
+bool ShouldTreatMapsAsRepeatedFields(const FileDescriptor& descriptor) {
+  return false;
+}
+
+// Do we ignore this message type?
+bool IgnoreMessage(const GeneratorOptions& options, const Descriptor* d) {
+  return d->options().map_entry() &&
+         !ShouldTreatMapsAsRepeatedFields(*d->file());
+}
+
+bool IsMap(const GeneratorOptions& options, const FieldDescriptor* field) {
+  return field->is_map() && !ShouldTreatMapsAsRepeatedFields(*field->file());
+}
 
 // Does JSPB ignore this entire oneof? True only if all fields are ignored.
 bool IgnoreOneof(const OneofDescriptor* oneof) {
@@ -347,9 +477,8 @@
   return true;
 }
 
-string JSIdent(const FieldDescriptor* field,
-               bool is_upper_camel,
-               bool is_map) {
+string JSIdent(const GeneratorOptions& options, const FieldDescriptor* field,
+               bool is_upper_camel, bool is_map, bool drop_list) {
   string result;
   if (field->type() == FieldDescriptor::TYPE_GROUP) {
     result = is_upper_camel ?
@@ -360,31 +489,57 @@
         ToUpperCamel(ParseLowerUnderscore(field->name())) :
         ToLowerCamel(ParseLowerUnderscore(field->name()));
   }
-  if (is_map) {
+  if (is_map || IsMap(options, field)) {
+    // JSPB-style or proto3-style map.
     result += "Map";
-  } else if (field->is_repeated()) {
+  } else if (!drop_list && field->is_repeated()) {
+    // Repeated field.
     result += "List";
   }
   return result;
 }
 
-string JSObjectFieldName(const FieldDescriptor* field) {
-  string name = JSIdent(
-      field,
-      /* is_upper_camel = */ false,
-      /* is_map = */ false);
+string JSObjectFieldName(const GeneratorOptions& options,
+                         const FieldDescriptor* field) {
+  string name = JSIdent(options, field,
+                        /* is_upper_camel = */ false,
+                        /* is_map = */ false,
+                        /* drop_list = */ false);
   if (IsReserved(name)) {
     name = "pb_" + name;
   }
   return name;
 }
 
+string JSByteGetterSuffix(BytesMode bytes_mode) {
+  switch (bytes_mode) {
+    case BYTES_DEFAULT:
+      return "";
+    case BYTES_B64:
+      return "B64";
+    case BYTES_U8:
+      return "U8";
+    default:
+      assert(false);
+  }
+  return "";
+}
+
 // Returns the field name as a capitalized portion of a getter/setter method
 // name, e.g. MyField for .getMyField().
-string JSGetterName(const FieldDescriptor* field) {
-  string name = JSIdent(field,
+string JSGetterName(const GeneratorOptions& options,
+                    const FieldDescriptor* field,
+                    BytesMode bytes_mode = BYTES_DEFAULT,
+                    bool drop_list = false) {
+  string name = JSIdent(options, field,
                         /* is_upper_camel = */ true,
-                        /* is_map = */ false);
+                        /* is_map = */ false, drop_list);
+  if (field->type() == FieldDescriptor::TYPE_BYTES) {
+    string suffix = JSByteGetterSuffix(bytes_mode);
+    if (!suffix.empty()) {
+      name += "_as" + suffix;
+    }
+  }
   if (name == "Extension" || name == "JsPbMessageId") {
     // Avoid conflicts with base-class names.
     name += "$";
@@ -392,12 +547,6 @@
   return name;
 }
 
-string JSMapGetterName(const FieldDescriptor* field) {
-  return JSIdent(field,
-                 /* is_upper_camel = */ true,
-                 /* is_map = */ true);
-}
-
 
 
 string JSOneofName(const OneofDescriptor* oneof) {
@@ -445,8 +594,7 @@
   return SimpleItoa(index);
 }
 
-// Decodes a codepoint in \x0000 -- \xFFFF. Since JS strings are UTF-16, we only
-// need to handle the BMP (16-bit range) here.
+// Decodes a codepoint in \x0000 -- \xFFFF.
 uint16 DecodeUTF8Codepoint(uint8* bytes, size_t* length) {
   if (*length == 0) {
     return 0;
@@ -483,80 +631,56 @@
 }
 
 // Escapes the contents of a string to be included within double-quotes ("") in
-// JavaScript. |is_utf8| determines whether the input data (in a C++ string of
-// chars) is UTF-8 encoded (in which case codepoints become JavaScript string
-// characters, escaped with 16-bit hex escapes where necessary) or raw binary
-// (in which case bytes become JavaScript string characters 0 -- 255).
-string EscapeJSString(const string& in, bool is_utf8) {
-  string result;
+// JavaScript. The input data should be a UTF-8 encoded C++ string of chars.
+// Returns false if |out| was truncated because |in| contained invalid UTF-8 or
+// codepoints outside the BMP.
+// TODO(lukestebbing): Support codepoints outside the BMP.
+bool EscapeJSString(const string& in, string* out) {
   size_t decoded = 0;
   for (size_t i = 0; i < in.size(); i += decoded) {
     uint16 codepoint = 0;
-    if (is_utf8) {
-      // Decode the next UTF-8 codepoint.
-      size_t have_bytes = in.size() - i;
-      uint8 bytes[3] = {
+    // Decode the next UTF-8 codepoint.
+    size_t have_bytes = in.size() - i;
+    uint8 bytes[3] = {
         static_cast<uint8>(in[i]),
         static_cast<uint8>(((i + 1) < in.size()) ? in[i + 1] : 0),
         static_cast<uint8>(((i + 2) < in.size()) ? in[i + 2] : 0),
-      };
-      codepoint = DecodeUTF8Codepoint(bytes, &have_bytes);
-      if (have_bytes == 0) {
-        break;
-      }
-      decoded = have_bytes;
-    } else {
-      codepoint = static_cast<uint16>(static_cast<uint8>(in[i]));
-      decoded = 1;
+    };
+    codepoint = DecodeUTF8Codepoint(bytes, &have_bytes);
+    if (have_bytes == 0) {
+      return false;
     }
-
-    // Next byte -- used for minimal octal escapes below.
-    char next_byte = (i + decoded) < in.size() ?
-        in[i + decoded] : 0;
-    bool pad_octal = (next_byte >= '0' && next_byte <= '7');
+    decoded = have_bytes;
 
     switch (codepoint) {
-      case '\0': result += pad_octal ? "\\000" : "\\0";   break;
-      case '\b': result += "\\\b";  break;
-      case '\t': result += "\\\t";  break;
-      case '\n': result += "\\\n";  break;
-      case '\r': result += "\\\r";  break;
-      case '\f': result += "\\\f";  break;
-      case '\\': result += "\\\\";  break;
-      case '"':  result += pad_octal ? "\\042" : "\\42"; break;
-      case '&':  result += pad_octal ? "\\046" : "\\46"; break;
-      case '\'': result += pad_octal ? "\\047" : "\\47"; break;
-      case '<':  result += pad_octal ? "\\074" : "\\74"; break;
-      case '=':  result += pad_octal ? "\\075" : "\\75"; break;
-      case '>':  result += pad_octal ? "\\076" : "\\76"; break;
+      case '\'': *out += "\\x27"; break;
+      case '"': *out += "\\x22"; break;
+      case '<': *out += "\\x3c"; break;
+      case '=': *out += "\\x3d"; break;
+      case '>': *out += "\\x3e"; break;
+      case '&': *out += "\\x26"; break;
+      case '\b': *out += "\\b"; break;
+      case '\t': *out += "\\t"; break;
+      case '\n': *out += "\\n"; break;
+      case '\f': *out += "\\f"; break;
+      case '\r': *out += "\\r"; break;
+      case '\\': *out += "\\\\"; break;
       default:
-        // All other non-ASCII codepoints are escaped.
-        // Original codegen uses hex for >= 0x100 and octal for others.
+        // TODO(lukestebbing): Once we're supporting codepoints outside the BMP,
+        // use a single Unicode codepoint escape if the output language is
+        // ECMAScript 2015 or above. Otherwise, use a surrogate pair.
+        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#String_literals
         if (codepoint >= 0x20 && codepoint <= 0x7e) {
-          result += static_cast<char>(codepoint);
+          *out += static_cast<char>(codepoint);
+        } else if (codepoint >= 0x100) {
+          *out += StringPrintf("\\u%04x", codepoint);
         } else {
-          if (codepoint >= 0x100) {
-            result += StringPrintf("\\u%04x", codepoint);
-          } else {
-            if (pad_octal || codepoint >= 0100) {
-              result += "\\";
-              result += ('0' + ((codepoint >> 6) & 07));
-              result += ('0' + ((codepoint >> 3) & 07));
-              result += ('0' + ((codepoint >> 0) & 07));
-            } else if (codepoint >= 010) {
-              result += "\\";
-              result += ('0' + ((codepoint >> 3) & 07));
-              result += ('0' + ((codepoint >> 0) & 07));
-            } else {
-              result += "\\";
-              result += ('0' + ((codepoint >> 0) & 07));
-            }
-          }
+          *out += StringPrintf("\\x%02x", codepoint);
         }
         break;
     }
   }
-  return result;
+  return true;
 }
 
 string EscapeBase64(const string& in) {
@@ -648,12 +772,29 @@
   return PostProcessFloat(result);
 }
 
+// Return true if this is an integral field that should be represented as string
+// in JS.
+bool IsIntegralFieldWithStringJSType(const FieldDescriptor* field) {
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT64:
+    case FieldDescriptor::CPPTYPE_UINT64:
+      // The default value of JSType is JS_NORMAL, which behaves the same as
+      // JS_NUMBER.
+      return field->options().jstype() == google::protobuf::FieldOptions::JS_STRING;
+    default:
+      return false;
+  }
+}
+
 string MaybeNumberString(const FieldDescriptor* field, const string& orig) {
-  return orig;
+  return IsIntegralFieldWithStringJSType(field) ? ("\"" + orig + "\"") : orig;
 }
 
 string JSFieldDefault(const FieldDescriptor* field) {
-  assert(field->has_default_value());
+  if (field->is_repeated()) {
+    return "[]";
+  }
+
   switch (field->cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32:
       return MaybeNumberString(
@@ -681,11 +822,17 @@
       return DoubleToString(field->default_value_double());
     case FieldDescriptor::CPPTYPE_STRING:
       if (field->type() == FieldDescriptor::TYPE_STRING) {
-        return "\"" + EscapeJSString(field->default_value_string(), true) +
-               "\"";
-      } else {
-        return "\"" + EscapeBase64(field->default_value_string()) +
-               "\"";
+        string out;
+        bool is_valid = EscapeJSString(field->default_value_string(), &out);
+        if (!is_valid) {
+          // TODO(lukestebbing): Decide whether this should be a hard error.
+          GOOGLE_LOG(WARNING) << "The default value for field " << field->full_name()
+                       << " was truncated since it contained invalid UTF-8 or"
+                          " codepoints outside the basic multilingual plane.";
+        }
+        return "\"" + out + "\"";
+      } else {  // Bytes
+        return "\"" + EscapeBase64(field->default_value_string()) + "\"";
       }
     case FieldDescriptor::CPPTYPE_MESSAGE:
       return "null";
@@ -728,22 +875,41 @@
     case FieldDescriptor::TYPE_BYTES:
       return "bytes";
     case FieldDescriptor::TYPE_GROUP:
-      return GetPath(options, field->message_type());
+      return GetMessagePath(options, field->message_type());
     case FieldDescriptor::TYPE_ENUM:
-      return GetPath(options, field->enum_type());
+      return GetEnumPath(options, field->enum_type());
     case FieldDescriptor::TYPE_MESSAGE:
-      return GetPath(options, field->message_type());
+      return GetMessagePath(options, field->message_type());
     default:
       return "";
   }
 }
 
 string JSIntegerTypeName(const FieldDescriptor* field) {
-  return "number";
+  return IsIntegralFieldWithStringJSType(field) ? "string" : "number";
+}
+
+string JSStringTypeName(const GeneratorOptions& options,
+                        const FieldDescriptor* field,
+                        BytesMode bytes_mode) {
+  if (field->type() == FieldDescriptor::TYPE_BYTES) {
+    switch (bytes_mode) {
+      case BYTES_DEFAULT:
+        return "(string|Uint8Array)";
+      case BYTES_B64:
+        return "string";
+      case BYTES_U8:
+        return "Uint8Array";
+      default:
+        assert(false);
+    }
+  }
+  return "string";
 }
 
 string JSTypeName(const GeneratorOptions& options,
-                  const FieldDescriptor* field) {
+                  const FieldDescriptor* field,
+                  BytesMode bytes_mode) {
   switch (field->cpp_type()) {
     case FieldDescriptor::CPPTYPE_BOOL:
       return "boolean";
@@ -760,53 +926,132 @@
     case FieldDescriptor::CPPTYPE_DOUBLE:
       return "number";
     case FieldDescriptor::CPPTYPE_STRING:
-      return "string";
+      return JSStringTypeName(options, field, bytes_mode);
     case FieldDescriptor::CPPTYPE_ENUM:
-      return GetPath(options, field->enum_type());
+      return GetEnumPath(options, field->enum_type());
     case FieldDescriptor::CPPTYPE_MESSAGE:
-      return GetPath(options, field->message_type());
+      return GetMessagePath(options, field->message_type());
     default:
       return "";
   }
 }
 
-bool HasFieldPresence(const FieldDescriptor* field);
+// Used inside Google only -- do not remove.
+bool UseBrokenPresenceSemantics(const GeneratorOptions& options,
+                                const FieldDescriptor* field) {
+  return false;
+}
+
+// Returns true for fields that return "null" from accessors when they are
+// unset.  This should normally only be true for non-repeated submessages, but
+// we have legacy users who relied on old behavior where accessors behaved this
+// way.
+bool ReturnsNullWhenUnset(const GeneratorOptions& options,
+                          const FieldDescriptor* field) {
+  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+      field->is_optional()) {
+    return true;
+  }
+
+  // TODO(haberman): remove this case and unconditionally return false.
+  return UseBrokenPresenceSemantics(options, field) && !field->is_repeated() &&
+         !field->has_default_value();
+}
+
+// In a sane world, this would be the same as ReturnsNullWhenUnset().  But in
+// the status quo, some fields declare that they never return null/undefined
+// even though they actually do:
+//   * required fields
+//   * optional enum fields
+//   * proto3 primitive fields.
+bool DeclaredReturnTypeIsNullable(const GeneratorOptions& options,
+                                  const FieldDescriptor* field) {
+  if (field->is_required() || field->type() == FieldDescriptor::TYPE_ENUM) {
+    return false;
+  }
+
+  if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
+      field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+    return false;
+  }
+
+  return ReturnsNullWhenUnset(options, field);
+}
+
+bool SetterAcceptsUndefined(const GeneratorOptions& options,
+                            const FieldDescriptor* field) {
+  if (ReturnsNullWhenUnset(options, field)) {
+    return true;
+  }
+
+  // Broken presence semantics always accepts undefined for setters.
+  return UseBrokenPresenceSemantics(options, field);
+}
+
+bool SetterAcceptsNull(const GeneratorOptions& options,
+                       const FieldDescriptor* field) {
+  if (ReturnsNullWhenUnset(options, field)) {
+    return true;
+  }
+
+  // With broken presence semantics, fields with defaults accept "null" for
+  // setters, but other fields do not.  This is a strange quirk of the old
+  // codegen.
+  return UseBrokenPresenceSemantics(options, field) &&
+         field->has_default_value();
+}
+
+// Returns types which are known to by non-nullable by default.
+// The style guide requires that we omit "!" in this case.
+bool IsPrimitive(const string& type) {
+  return type == "undefined" || type == "string" || type == "number" ||
+         type == "boolean";
+}
 
 string JSFieldTypeAnnotation(const GeneratorOptions& options,
                              const FieldDescriptor* field,
-                             bool force_optional,
+                             bool is_setter_argument,
                              bool force_present,
                              bool singular_if_not_packed,
-                             bool always_singular) {
-  bool is_primitive =
-      (field->cpp_type() != FieldDescriptor::CPPTYPE_ENUM &&
-       field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE);
-
-  string jstype = JSTypeName(options, field);
+                             BytesMode bytes_mode = BYTES_DEFAULT) {
+  GOOGLE_CHECK(!(is_setter_argument && force_present));
+  string jstype = JSTypeName(options, field, bytes_mode);
 
   if (field->is_repeated() &&
-      !always_singular &&
       (field->is_packed() || !singular_if_not_packed)) {
-    if (!is_primitive) {
-      jstype = "!" + jstype;
-    }
-    jstype = "Array.<" + jstype + ">";
-    if (!force_optional) {
-      jstype = "!" + jstype;
+    if (field->type() == FieldDescriptor::TYPE_BYTES &&
+        bytes_mode == BYTES_DEFAULT) {
+      jstype = "(Array<!Uint8Array>|Array<string>)";
+    } else {
+      if (!IsPrimitive(jstype)) {
+        jstype = "!" + jstype;
+      }
+      jstype = "Array<" + jstype + ">";
     }
   }
 
-  if (field->is_optional() && is_primitive &&
-      (!field->has_default_value() || force_optional) && !force_present) {
-    jstype += "?";
-  } else if (field->is_required() && !is_primitive && !force_optional) {
-    jstype = "!" + jstype;
+  bool is_null_or_undefined = false;
+
+  if (is_setter_argument) {
+    if (SetterAcceptsNull(options, field)) {
+      jstype = "?" + jstype;
+      is_null_or_undefined = true;
+    }
+
+    if (SetterAcceptsUndefined(options, field)) {
+      jstype += "|undefined";
+      is_null_or_undefined = true;
+    }
+  } else if (force_present) {
+    // Don't add null or undefined.
+  } else {
+    if (DeclaredReturnTypeIsNullable(options, field)) {
+      jstype = "?" + jstype;
+      is_null_or_undefined = true;
+    }
   }
 
-  if (force_optional && HasFieldPresence(field)) {
-    jstype += "|undefined";
-  }
-  if (force_present && jstype[0] != '!' && !is_primitive) {
+  if (!is_null_or_undefined && !IsPrimitive(jstype)) {
     jstype = "!" + jstype;
   }
 
@@ -818,17 +1063,12 @@
   if (name[0] >= 'a' && name[0] <= 'z') {
     name[0] = (name[0] - 'a') + 'A';
   }
-
-  return name;
+  return IsIntegralFieldWithStringJSType(field) ? (name + "String") : name;
 }
 
 string JSBinaryReadWriteMethodName(const FieldDescriptor* field,
                                    bool is_writer) {
   string name = JSBinaryReaderMethodType(field);
-  if (is_writer && field->type() == FieldDescriptor::TYPE_BYTES) {
-    // Override for `bytes` fields: treat string as raw bytes, not base64.
-    name = "BytesRawString";
-  }
   if (field->is_packed()) {
     name = "Packed" + name;
   } else if (is_writer && field->is_repeated()) {
@@ -837,26 +1077,65 @@
   return name;
 }
 
-string JSBinaryReaderMethodName(const FieldDescriptor* field) {
-  return "read" + JSBinaryReadWriteMethodName(field, /* is_writer = */ false);
+string JSBinaryReaderMethodName(const GeneratorOptions& options,
+                                const FieldDescriptor* field) {
+  return "jspb.BinaryReader.prototype.read" +
+         JSBinaryReadWriteMethodName(field, /* is_writer = */ false);
 }
 
-string JSBinaryWriterMethodName(const FieldDescriptor* field) {
-  return "write" + JSBinaryReadWriteMethodName(field, /* is_writer = */ true);
+string JSBinaryWriterMethodName(const GeneratorOptions& options,
+                                const FieldDescriptor* field) {
+  return "jspb.BinaryWriter.prototype.write" +
+         JSBinaryReadWriteMethodName(field, /* is_writer = */ true);
 }
 
 string JSReturnClause(const FieldDescriptor* desc) {
   return "";
 }
 
+string JSTypeTag(const FieldDescriptor* desc) {
+  switch (desc->type()) {
+    case FieldDescriptor::TYPE_DOUBLE:
+    case FieldDescriptor::TYPE_FLOAT:
+      return "Float";
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_UINT32:
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_UINT64:
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_SFIXED32:
+    case FieldDescriptor::TYPE_SFIXED64:
+      if (IsIntegralFieldWithStringJSType(desc)) {
+        return "StringInt";
+      } else {
+        return "Int";
+      }
+    case FieldDescriptor::TYPE_BOOL:
+      return "Boolean";
+    case FieldDescriptor::TYPE_STRING:
+      return "String";
+    case FieldDescriptor::TYPE_BYTES:
+      return "Bytes";
+    case FieldDescriptor::TYPE_ENUM:
+      return "Enum";
+    default:
+      assert(false);
+  }
+  return "";
+}
+
 string JSReturnDoc(const GeneratorOptions& options,
                    const FieldDescriptor* desc) {
   return "";
 }
 
-bool HasRepeatedFields(const Descriptor* desc) {
+bool HasRepeatedFields(const GeneratorOptions& options,
+                       const Descriptor* desc) {
   for (int i = 0; i < desc->field_count(); i++) {
-    if (desc->field(i)->is_repeated()) {
+    if (desc->field(i)->is_repeated() && !IsMap(options, desc->field(i))) {
       return true;
     }
   }
@@ -867,8 +1146,9 @@
 
 string RepeatedFieldsArrayName(const GeneratorOptions& options,
                                const Descriptor* desc) {
-  return HasRepeatedFields(desc) ?
-      (GetPath(options, desc) + kRepeatedFieldArrayName) : "null";
+  return HasRepeatedFields(options, desc)
+             ? (GetMessagePath(options, desc) + kRepeatedFieldArrayName)
+             : "null";
 }
 
 bool HasOneofFields(const Descriptor* desc) {
@@ -884,14 +1164,16 @@
 
 string OneofFieldsArrayName(const GeneratorOptions& options,
                             const Descriptor* desc) {
-  return HasOneofFields(desc) ?
-      (GetPath(options, desc) + kOneofGroupArrayName) : "null";
+  return HasOneofFields(desc)
+             ? (GetMessagePath(options, desc) + kOneofGroupArrayName)
+             : "null";
 }
 
-string RepeatedFieldNumberList(const Descriptor* desc) {
+string RepeatedFieldNumberList(const GeneratorOptions& options,
+                               const Descriptor* desc) {
   std::vector<string> numbers;
   for (int i = 0; i < desc->field_count(); i++) {
-    if (desc->field(i)->is_repeated()) {
+    if (desc->field(i)->is_repeated() && !IsMap(options, desc->field(i))) {
       numbers.push_back(JSFieldIndex(desc->field(i)));
     }
   }
@@ -952,38 +1234,71 @@
 }
 
 string JSExtensionsObjectName(const GeneratorOptions& options,
+                              const FileDescriptor* from_file,
                               const Descriptor* desc) {
   if (desc->full_name() == "google.protobuf.bridge.MessageSet") {
+    // TODO(haberman): fix this for the kImportCommonJs case.
     return "jspb.Message.messageSetExtensions";
   } else {
-    return GetPath(options, desc) + ".extensions";
+    return MaybeCrossFileRef(options, from_file, desc) + ".extensions";
   }
 }
 
+static const int kMapKeyField = 1;
+static const int kMapValueField = 2;
+
+const FieldDescriptor* MapFieldKey(const FieldDescriptor* field) {
+  assert(field->is_map());
+  return field->message_type()->FindFieldByNumber(kMapKeyField);
+}
+
+const FieldDescriptor* MapFieldValue(const FieldDescriptor* field) {
+  assert(field->is_map());
+  return field->message_type()->FindFieldByNumber(kMapValueField);
+}
+
 string FieldDefinition(const GeneratorOptions& options,
                        const FieldDescriptor* field) {
-  string qualifier = field->is_repeated() ? "repeated" :
-      (field->is_optional() ? "optional" : "required");
-  string type, name;
-  if (field->type() == FieldDescriptor::TYPE_ENUM ||
-      field->type() == FieldDescriptor::TYPE_MESSAGE) {
-    type = RelativeTypeName(field);
-    name = field->name();
-  } else if (field->type() == FieldDescriptor::TYPE_GROUP) {
-    type = "group";
-    name = field->message_type()->name();
+  if (IsMap(options, field)) {
+    const FieldDescriptor* key_field = MapFieldKey(field);
+    const FieldDescriptor* value_field = MapFieldValue(field);
+    string key_type = ProtoTypeName(options, key_field);
+    string value_type;
+    if (value_field->type() == FieldDescriptor::TYPE_ENUM ||
+        value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
+      value_type = RelativeTypeName(value_field);
+    } else {
+      value_type = ProtoTypeName(options, value_field);
+    }
+    return StringPrintf("map<%s, %s> %s = %d;",
+                        key_type.c_str(),
+                        value_type.c_str(),
+                        field->name().c_str(),
+                        field->number());
   } else {
-    type = ProtoTypeName(options, field);
-    name = field->name();
+    string qualifier = field->is_repeated() ? "repeated" :
+        (field->is_optional() ? "optional" : "required");
+    string type, name;
+    if (field->type() == FieldDescriptor::TYPE_ENUM ||
+        field->type() == FieldDescriptor::TYPE_MESSAGE) {
+      type = RelativeTypeName(field);
+      name = field->name();
+    } else if (field->type() == FieldDescriptor::TYPE_GROUP) {
+      type = "group";
+      name = field->message_type()->name();
+    } else {
+      type = ProtoTypeName(options, field);
+      name = field->name();
+    }
+    return StringPrintf("%s %s %s = %d;",
+                        qualifier.c_str(),
+                        type.c_str(),
+                        name.c_str(),
+                        field->number());
   }
-  return StringPrintf("%s %s %s = %d;",
-                      qualifier.c_str(),
-                      type.c_str(),
-                      name.c_str(),
-                      field->number());
 }
 
-string FieldComments(const FieldDescriptor* field) {
+string FieldComments(const FieldDescriptor* field, BytesMode bytes_mode) {
   string comments;
   if (field->cpp_type() == FieldDescriptor::CPPTYPE_BOOL) {
     comments +=
@@ -992,12 +1307,10 @@
         " * You should avoid comparisons like {@code val === true/false} in "
         "those cases.\n";
   }
-  if (field->is_repeated()) {
+  if (field->type() == FieldDescriptor::TYPE_BYTES && bytes_mode == BYTES_U8) {
     comments +=
-        " * If you change this array by adding, removing or replacing "
-        "elements, or if you\n"
-        " * replace the array itself, then you must call the setter to "
-        "update it.\n";
+        " * Note that Uint8Array is not supported on all browsers.\n"
+        " * @see http://caniuse.com/Uint8Array\n";
   }
   return comments;
 }
@@ -1009,8 +1322,10 @@
 }
 
 bool HasExtensions(const Descriptor* desc) {
-  if (desc->extension_count() > 0) {
-    return true;
+  for (int i = 0; i < desc->extension_count(); i++) {
+    if (ShouldGenerateExtension(desc->extension(i))) {
+      return true;
+    }
   }
   for (int i = 0; i < desc->nested_type_count(); i++) {
     if (HasExtensions(desc->nested_type(i))) {
@@ -1034,6 +1349,29 @@
   return false;
 }
 
+bool HasMap(const GeneratorOptions& options, const Descriptor* desc) {
+  for (int i = 0; i < desc->field_count(); i++) {
+    if (IsMap(options, desc->field(i))) {
+      return true;
+    }
+  }
+  for (int i = 0; i < desc->nested_type_count(); i++) {
+    if (HasMap(options, desc->nested_type(i))) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool FileHasMap(const GeneratorOptions& options, const FileDescriptor* desc) {
+  for (int i = 0; i < desc->message_type_count(); i++) {
+    if (HasMap(options, desc->message_type(i))) {
+      return true;
+    }
+  }
+  return false;
+}
+
 bool IsExtendable(const Descriptor* desc) {
   return desc->extension_range_count() > 0;
 }
@@ -1041,7 +1379,7 @@
 // Returns the max index in the underlying data storage array beyond which the
 // extension object is used.
 string GetPivot(const Descriptor* desc) {
-  static const int kDefaultPivot = (1 << 29);  // max field number (29 bits)
+  static const int kDefaultPivot = 500;
 
   // Find the max field number
   int max_field_number = 0;
@@ -1053,7 +1391,7 @@
   }
 
   int pivot = -1;
-  if (IsExtendable(desc)) {
+  if (IsExtendable(desc) || (max_field_number >= kDefaultPivot)) {
     pivot = ((max_field_number + 1) < kDefaultPivot) ?
         (max_field_number + 1) : kDefaultPivot;
   }
@@ -1061,43 +1399,177 @@
   return SimpleItoa(pivot);
 }
 
-// Returns true for fields that represent "null" as distinct from the default
-// value. See https://go/proto3#heading=h.kozewqqcqhuz for more information.
-bool HasFieldPresence(const FieldDescriptor* field) {
-  return
-      (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ||
-      (field->containing_oneof() != NULL) ||
-      (field->file()->syntax() != FileDescriptor::SYNTAX_PROTO3);
+// Whether this field represents presence.  For fields with presence, we
+// generate extra methods (clearFoo() and hasFoo()) for this field.
+bool HasFieldPresence(const GeneratorOptions& options,
+                      const FieldDescriptor* field) {
+  if (field->is_repeated() || field->is_map()) {
+    // We say repeated fields and maps don't have presence, but we still do
+    // generate clearFoo() methods for them through a special case elsewhere.
+    return false;
+  }
+
+  if (UseBrokenPresenceSemantics(options, field)) {
+    // Proto3 files with broken presence semantics have field presence.
+    return true;
+  }
+
+  return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
+         field->containing_oneof() != NULL ||
+         field->file()->syntax() == FileDescriptor::SYNTAX_PROTO2;
 }
 
-// For proto3 fields without presence, returns a string representing the default
-// value in JavaScript. See https://go/proto3#heading=h.kozewqqcqhuz for more
-// information.
-string Proto3PrimitiveFieldDefault(const FieldDescriptor* field) {
-  switch (field->cpp_type()) {
-    case FieldDescriptor::CPPTYPE_INT32:
-    case FieldDescriptor::CPPTYPE_INT64:
-    case FieldDescriptor::CPPTYPE_UINT32:
-    case FieldDescriptor::CPPTYPE_UINT64: {
-      return "0";
+// We use this to implement the semantics that same file can be generated
+// multiple times, but the last one wins.  We never actually write the files,
+// but we keep a set of which descriptors were the final one for a given
+// filename.
+class FileDeduplicator {
+ public:
+  explicit FileDeduplicator(const GeneratorOptions& options)
+      : error_on_conflict_(options.error_on_name_conflict) {}
+
+  bool AddFile(const string& filename, const void* desc, string* error) {
+    if (descs_by_filename_.find(filename) != descs_by_filename_.end()) {
+      if (error_on_conflict_) {
+        *error = "Name conflict: file name " + filename +
+                 " would be generated by two descriptors";
+        return false;
+      }
+      allowed_descs_.erase(descs_by_filename_[filename]);
     }
 
-    case FieldDescriptor::CPPTYPE_ENUM:
-    case FieldDescriptor::CPPTYPE_FLOAT:
-    case FieldDescriptor::CPPTYPE_DOUBLE:
-      return "0";
-
-    case FieldDescriptor::CPPTYPE_BOOL:
-      return "false";
-
-    case FieldDescriptor::CPPTYPE_STRING:
-      return "\"\"";
-
-    default:
-      // BYTES and MESSAGE are handled separately.
-      assert(false);
-      return "";
+    descs_by_filename_[filename] = desc;
+    allowed_descs_.insert(desc);
+    return true;
   }
+
+  void GetAllowedSet(std::set<const void*>* allowed_set) {
+    *allowed_set = allowed_descs_;
+  }
+
+ private:
+  bool error_on_conflict_;
+  std::map<string, const void*> descs_by_filename_;
+  std::set<const void*> allowed_descs_;
+};
+
+void DepthFirstSearch(const FileDescriptor* file,
+                      std::vector<const FileDescriptor*>* list,
+                      std::set<const FileDescriptor*>* seen) {
+  if (!seen->insert(file).second) {
+    return;
+  }
+
+  // Add all dependencies.
+  for (int i = 0; i < file->dependency_count(); i++) {
+    DepthFirstSearch(file->dependency(i), list, seen);
+  }
+
+  // Add this file.
+  list->push_back(file);
+}
+
+// A functor for the predicate to remove_if() below.  Returns true if a given
+// FileDescriptor is not in the given set.
+class NotInSet {
+ public:
+  explicit NotInSet(const std::set<const FileDescriptor*>& file_set)
+      : file_set_(file_set) {}
+
+  bool operator()(const FileDescriptor* file) {
+    return file_set_.count(file) == 0;
+  }
+
+ private:
+  const std::set<const FileDescriptor*>& file_set_;
+};
+
+// This function generates an ordering of the input FileDescriptors that matches
+// the logic of the old code generator.  The order is significant because two
+// different input files can generate the same output file, and the last one
+// needs to win.
+void GenerateJspbFileOrder(const std::vector<const FileDescriptor*>& input,
+                           std::vector<const FileDescriptor*>* ordered) {
+  // First generate an ordering of all reachable files (including dependencies)
+  // with depth-first search.  This mimics the behavior of --include_imports,
+  // which is what the old codegen used.
+  ordered->clear();
+  std::set<const FileDescriptor*> seen;
+  std::set<const FileDescriptor*> input_set;
+  for (int i = 0; i < input.size(); i++) {
+    DepthFirstSearch(input[i], ordered, &seen);
+    input_set.insert(input[i]);
+  }
+
+  // Now remove the entries that are not actually in our input list.
+  ordered->erase(
+      std::remove_if(ordered->begin(), ordered->end(), NotInSet(input_set)),
+      ordered->end());
+}
+
+// If we're generating code in file-per-type mode, avoid overwriting files
+// by choosing the last descriptor that writes each filename and permitting
+// only those to generate code.
+
+bool GenerateJspbAllowedSet(const GeneratorOptions& options,
+                            const std::vector<const FileDescriptor*>& files,
+                            std::set<const void*>* allowed_set,
+                            string* error) {
+  std::vector<const FileDescriptor*> files_ordered;
+  GenerateJspbFileOrder(files, &files_ordered);
+
+  // Choose the last descriptor for each filename.
+  FileDeduplicator dedup(options);
+  for (int i = 0; i < files_ordered.size(); i++) {
+    for (int j = 0; j < files_ordered[i]->message_type_count(); j++) {
+      const Descriptor* desc = files_ordered[i]->message_type(j);
+      if (!dedup.AddFile(GetMessageFileName(options, desc), desc, error)) {
+        return false;
+      }
+    }
+    for (int j = 0; j < files_ordered[i]->enum_type_count(); j++) {
+      const EnumDescriptor* desc = files_ordered[i]->enum_type(j);
+      if (!dedup.AddFile(GetEnumFileName(options, desc), desc, error)) {
+        return false;
+      }
+    }
+
+    // Pull out all free-floating extensions and generate files for those too.
+    bool has_extension = false;
+
+    for (int j = 0; j < files_ordered[i]->extension_count(); j++) {
+      if (ShouldGenerateExtension(files_ordered[i]->extension(j))) {
+        has_extension = true;
+      }
+    }
+
+    if (has_extension) {
+      if (!dedup.AddFile(GetExtensionFileName(options, files_ordered[i]),
+                         files_ordered[i], error)) {
+        return false;
+      }
+    }
+  }
+
+  dedup.GetAllowedSet(allowed_set);
+
+  return true;
+}
+
+// Embeds base64 encoded GeneratedCodeInfo proto in a comment at the end of
+// file.
+void EmbedCodeAnnotations(const GeneratedCodeInfo& annotations,
+                          io::Printer* printer) {
+  // Serialize annotations proto into base64 string.
+  string meta_content;
+  annotations.SerializeToString(&meta_content);
+  string meta_64;
+  Base64Escape(meta_content, &meta_64);
+
+  // Print base64 encoded annotations at the end of output file in
+  // a comment.
+  printer->Print("\n// Below is base64 encoded GeneratedCodeInfo proto");
+  printer->Print("\n// $encoded_proto$\n", "encoded_proto", meta_64);
 }
 
 }  // anonymous namespace
@@ -1107,25 +1579,34 @@
   printer->Print("/**\n"
                  " * @fileoverview\n"
                  " * @enhanceable\n"
+                 " * @suppress {messageConventions} JS Compiler reports an "
+                 "error if a variable or\n"
+                 " *     field starts with 'MSG_' and isn't a translatable "
+                 "message.\n"
                  " * @public\n"
                  " */\n"
                  "// GENERATED CODE -- DO NOT EDIT!\n"
                  "\n");
 }
 
+void Generator::FindProvidesForFile(const GeneratorOptions& options,
+                                    io::Printer* printer,
+                                    const FileDescriptor* file,
+                                    std::set<string>* provided) const {
+  for (int i = 0; i < file->message_type_count(); i++) {
+    FindProvidesForMessage(options, printer, file->message_type(i), provided);
+  }
+  for (int i = 0; i < file->enum_type_count(); i++) {
+    FindProvidesForEnum(options, printer, file->enum_type(i), provided);
+  }
+}
+
 void Generator::FindProvides(const GeneratorOptions& options,
                              io::Printer* printer,
-                             const vector<const FileDescriptor*>& files,
+                             const std::vector<const FileDescriptor*>& files,
                              std::set<string>* provided) const {
   for (int i = 0; i < files.size(); i++) {
-    for (int j = 0; j < files[i]->message_type_count(); j++) {
-      FindProvidesForMessage(options, printer, files[i]->message_type(j),
-                                 provided);
-    }
-    for (int j = 0; j < files[i]->enum_type_count(); j++) {
-      FindProvidesForEnum(options, printer, files[i]->enum_type(j),
-                              provided);
-    }
+    FindProvidesForFile(options, printer, files[i], provided);
   }
 
   printer->Print("\n");
@@ -1136,7 +1617,11 @@
     io::Printer* printer,
     const Descriptor* desc,
     std::set<string>* provided) const {
-  string name = GetPath(options, desc);
+  if (IgnoreMessage(options, desc)) {
+    return;
+  }
+
+  string name = GetMessagePath(options, desc);
   provided->insert(name);
 
   for (int i = 0; i < desc->enum_type_count(); i++) {
@@ -1153,14 +1638,14 @@
                                     io::Printer* printer,
                                     const EnumDescriptor* enumdesc,
                                     std::set<string>* provided) const {
-  string name = GetPath(options, enumdesc);
+  string name = GetEnumPath(options, enumdesc);
   provided->insert(name);
 }
 
 void Generator::FindProvidesForFields(
     const GeneratorOptions& options,
     io::Printer* printer,
-    const vector<const FieldDescriptor*>& fields,
+    const std::vector<const FieldDescriptor*>& fields,
     std::set<string>* provided) const {
   for (int i = 0; i < fields.size(); i++) {
     const FieldDescriptor* field = fields[i];
@@ -1169,8 +1654,8 @@
       continue;
     }
 
-    string name =
-        GetPath(options, field->file()) + "." + JSObjectFieldName(field);
+    string name = GetFilePath(options, field->file()) + "." +
+                  JSObjectFieldName(options, field);
     provided->insert(name);
   }
 }
@@ -1180,15 +1665,26 @@
                                  std::set<string>* provided) const {
   for (std::set<string>::iterator it = provided->begin();
        it != provided->end(); ++it) {
-    printer->Print("goog.provide('$name$');\n",
-                   "name", *it);
+    if (options.import_style == GeneratorOptions::kImportClosure) {
+      printer->Print("goog.provide('$name$');\n", "name", *it);
+    } else {
+      // We aren't using Closure's import system, but we use goog.exportSymbol()
+      // to construct the expected tree of objects, eg.
+      //
+      //   goog.exportSymbol('foo.bar.Baz', null, this);
+      //
+      //   // Later generated code expects foo.bar = {} to exist:
+      //   foo.bar.Baz = function() { /* ... */ }
+      printer->Print("goog.exportSymbol('$name$', null, global);\n", "name",
+                     *it);
+    }
   }
 }
 
-void Generator::GenerateRequires(const GeneratorOptions& options,
-                                 io::Printer* printer,
-                                 const Descriptor* desc,
-                                 std::set<string>* provided) const {
+void Generator::GenerateRequiresForMessage(const GeneratorOptions& options,
+                                           io::Printer* printer,
+                                           const Descriptor* desc,
+                                           std::set<string>* provided) const {
   std::set<string> required;
   std::set<string> forwards;
   bool have_message = false;
@@ -1197,36 +1693,47 @@
 
   GenerateRequiresImpl(options, printer, &required, &forwards, provided,
                        /* require_jspb = */ have_message,
-                       /* require_extension = */ HasExtensions(desc));
+                       /* require_extension = */ HasExtensions(desc),
+                       /* require_map = */ HasMap(options, desc));
 }
 
-void Generator::GenerateRequires(const GeneratorOptions& options,
-                                 io::Printer* printer,
-                                 const vector<const FileDescriptor*>& files,
-                                 std::set<string>* provided) const {
+void Generator::GenerateRequiresForLibrary(
+    const GeneratorOptions& options, io::Printer* printer,
+    const std::vector<const FileDescriptor*>& files,
+    std::set<string>* provided) const {
+  GOOGLE_CHECK_EQ(options.import_style, GeneratorOptions::kImportClosure);
+  // For Closure imports we need to import every message type individually.
   std::set<string> required;
   std::set<string> forwards;
   bool have_extensions = false;
+  bool have_map = false;
   bool have_message = false;
 
   for (int i = 0; i < files.size(); i++) {
     for (int j = 0; j < files[i]->message_type_count(); j++) {
-      FindRequiresForMessage(options,
-                             files[i]->message_type(j),
-                             &required, &forwards, &have_message);
+      const Descriptor* desc = files[i]->message_type(j);
+      if (!IgnoreMessage(options, desc)) {
+        FindRequiresForMessage(options, desc, &required, &forwards,
+                               &have_message);
+      }
     }
+
     if (!have_extensions && HasExtensions(files[i])) {
       have_extensions = true;
     }
 
+    if (!have_map && FileHasMap(options, files[i])) {
+      have_map = true;
+    }
+
     for (int j = 0; j < files[i]->extension_count(); j++) {
       const FieldDescriptor* extension = files[i]->extension(j);
       if (IgnoreField(extension)) {
         continue;
       }
       if (extension->containing_type()->full_name() !=
-          "google.protobuf.bridge.MessageSet") {
-        required.insert(GetPath(options, extension->containing_type()));
+        "google.protobuf.bridge.MessageSet") {
+        required.insert(GetMessagePath(options, extension->containing_type()));
       }
       FindRequiresForField(options, extension, &required, &forwards);
       have_extensions = true;
@@ -1235,13 +1742,14 @@
 
   GenerateRequiresImpl(options, printer, &required, &forwards, provided,
                        /* require_jspb = */ have_message,
-                       /* require_extension = */ have_extensions);
+                       /* require_extension = */ have_extensions,
+                       /* require_map = */ have_map);
 }
 
-void Generator::GenerateRequires(const GeneratorOptions& options,
-                                 io::Printer* printer,
-                                 const vector<const FieldDescriptor*>& fields,
-                                 std::set<string>* provided) const {
+void Generator::GenerateRequiresForExtensions(
+    const GeneratorOptions& options, io::Printer* printer,
+    const std::vector<const FieldDescriptor*>& fields,
+    std::set<string>* provided) const {
   std::set<string> required;
   std::set<string> forwards;
   for (int i = 0; i < fields.size(); i++) {
@@ -1254,7 +1762,8 @@
 
   GenerateRequiresImpl(options, printer, &required, &forwards, provided,
                        /* require_jspb = */ false,
-                       /* require_extension = */ fields.size() > 0);
+                       /* require_extension = */ fields.size() > 0,
+                       /* require_map = */ false);
 }
 
 void Generator::GenerateRequiresImpl(const GeneratorOptions& options,
@@ -1262,20 +1771,19 @@
                                      std::set<string>* required,
                                      std::set<string>* forwards,
                                      std::set<string>* provided,
-                                     bool require_jspb,
-                                     bool require_extension) const {
+                                     bool require_jspb, bool require_extension,
+                                     bool require_map) const {
   if (require_jspb) {
-    printer->Print(
-        "goog.require('jspb.Message');\n");
-    if (options.binary) {
-      printer->Print(
-          "goog.require('jspb.BinaryReader');\n"
-          "goog.require('jspb.BinaryWriter');\n");
-    }
+    required->insert("jspb.Message");
+    required->insert("jspb.BinaryReader");
+    required->insert("jspb.BinaryWriter");
   }
   if (require_extension) {
-    printer->Print(
-        "goog.require('jspb.ExtensionFieldInfo');\n");
+    required->insert("jspb.ExtensionFieldBinaryInfo");
+    required->insert("jspb.ExtensionFieldInfo");
+  }
+  if (require_map) {
+    required->insert("jspb.Map");
   }
 
   std::set<string>::iterator it;
@@ -1344,12 +1852,14 @@
         // dependencies, as per original codegen.
         !(field->is_extension() && field->extension_scope() == NULL)) {
       if (options.add_require_for_enums) {
-        required->insert(GetPath(options, field->enum_type()));
+        required->insert(GetEnumPath(options, field->enum_type()));
       } else {
-        forwards->insert(GetPath(options, field->enum_type()));
+        forwards->insert(GetEnumPath(options, field->enum_type()));
       }
     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
-      required->insert(GetPath(options, field->message_type()));
+      if (!IgnoreMessage(options, field->message_type())) {
+        required->insert(GetMessagePath(options, field->message_type()));
+      }
     }
 }
 
@@ -1358,7 +1868,7 @@
                                          std::set<string>* required,
                                          std::set<string>* forwards) const {
     if (field->containing_type()->full_name() != "google.protobuf.bridge.MessageSet") {
-      required->insert(GetPath(options, field->containing_type()));
+      required->insert(GetMessagePath(options, field->containing_type()));
     }
     FindRequiresForField(options, field, required, forwards);
 }
@@ -1385,6 +1895,10 @@
 void Generator::GenerateClass(const GeneratorOptions& options,
                               io::Printer* printer,
                               const Descriptor* desc) const {
+  if (IgnoreMessage(options, desc)) {
+    return;
+  }
+
   if (!NamespaceOnly(desc)) {
     printer->Print("\n");
     GenerateClassConstructor(options, printer, desc);
@@ -1392,29 +1906,37 @@
 
 
     GenerateClassToObject(options, printer, desc);
-    if (options.binary) {
-      // These must come *before* the extension-field info generation in
-      // GenerateClassRegistration so that references to the binary
-      // serialization/deserialization functions may be placed in the extension
-      // objects.
-      GenerateClassDeserializeBinary(options, printer, desc);
-      GenerateClassSerializeBinary(options, printer, desc);
-    }
-    GenerateClassClone(options, printer, desc);
-    GenerateClassRegistration(options, printer, desc);
-    GenerateClassFields(options, printer, desc);
-    if (IsExtendable(desc) && desc->full_name() != "google.protobuf.bridge.MessageSet") {
-      GenerateClassExtensionFieldInfo(options, printer, desc);
-    }
+    // These must come *before* the extension-field info generation in
+    // GenerateClassRegistration so that references to the binary
+    // serialization/deserialization functions may be placed in the extension
+    // objects.
+    GenerateClassDeserializeBinary(options, printer, desc);
+    GenerateClassSerializeBinary(options, printer, desc);
   }
 
-  // Recurse on nested types.
+  // Recurse on nested types. These must come *before* the extension-field
+  // info generation in GenerateClassRegistration so that extensions that
+  // reference nested types proceed the definitions of the nested types.
   for (int i = 0; i < desc->enum_type_count(); i++) {
     GenerateEnum(options, printer, desc->enum_type(i));
   }
   for (int i = 0; i < desc->nested_type_count(); i++) {
     GenerateClass(options, printer, desc->nested_type(i));
   }
+
+  if (!NamespaceOnly(desc)) {
+    GenerateClassRegistration(options, printer, desc);
+    GenerateClassFields(options, printer, desc);
+    if (IsExtendable(desc) && desc->full_name() != "google.protobuf.bridge.MessageSet") {
+      GenerateClassExtensionFieldInfo(options, printer, desc);
+    }
+
+    if (options.import_style != GeneratorOptions::kImportClosure) {
+      for (int i = 0; i < desc->extension_count(); i++) {
+        GenerateExtension(options, printer, desc->extension(i));
+      }
+    }
+  }
 }
 
 void Generator::GenerateClassConstructor(const GeneratorOptions& options,
@@ -1435,8 +1957,10 @@
       " * @extends {jspb.Message}\n"
       " * @constructor\n"
       " */\n"
-      "$classname$ = function(opt_data) {\n",
-      "classname", GetPath(options, desc));
+      "$classprefix$$classname$ = function(opt_data) {\n",
+      "classprefix", GetMessagePathPrefix(options, desc),
+      "classname", desc->name());
+  printer->Annotate("classname", desc);
   string message_id = GetMessageId(desc);
   printer->Print(
       "  jspb.Message.initialize(this, opt_data, $messageId$, $pivot$, "
@@ -1453,13 +1977,13 @@
       "if (goog.DEBUG && !COMPILED) {\n"
       "  $classname$.displayName = '$classname$';\n"
       "}\n",
-      "classname", GetPath(options, desc));
+      "classname", GetMessagePath(options, desc));
 }
 
 void Generator::GenerateClassFieldInfo(const GeneratorOptions& options,
                                        io::Printer* printer,
                                        const Descriptor* desc) const {
-  if (HasRepeatedFields(desc)) {
+  if (HasRepeatedFields(options, desc)) {
     printer->Print(
         "/**\n"
         " * List of repeated fields within this message type.\n"
@@ -1468,9 +1992,9 @@
         " */\n"
         "$classname$$rptfieldarray$ = $rptfields$;\n"
         "\n",
-        "classname", GetPath(options, desc),
+        "classname", GetMessagePath(options, desc),
         "rptfieldarray", kRepeatedFieldArrayName,
-        "rptfields", RepeatedFieldNumberList(desc));
+        "rptfields", RepeatedFieldNumberList(options, desc));
   }
 
   if (HasOneofFields(desc)) {
@@ -1489,7 +2013,7 @@
         " */\n"
         "$classname$$oneofgrouparray$ = $oneofgroups$;\n"
         "\n",
-        "classname", GetPath(options, desc),
+        "classname", GetMessagePath(options, desc),
         "oneofgrouparray", kOneofGroupArrayName,
         "oneofgroups", OneofGroupList(desc));
 
@@ -1509,7 +2033,7 @@
       "\n"
       "\n"
       "$class$.prototype.messageXid = xid('$class$');\n",
-      "class", GetPath(options, desc));
+      "class", GetMessagePath(options, desc));
 }
 
 void Generator::GenerateOneofCaseDefinition(
@@ -1522,7 +2046,7 @@
       " */\n"
       "$classname$.$oneof$Case = {\n"
       "  $upcase$_NOT_SET: 0",
-      "classname", GetPath(options, oneof->containing_type()),
+      "classname", GetMessagePath(options, oneof->containing_type()),
       "oneof", JSOneofName(oneof),
       "upcase", ToEnumCase(oneof->name()));
 
@@ -1536,6 +2060,7 @@
         "  $upcase$: $number$",
         "upcase", ToEnumCase(oneof->field(i)->name()),
         "number", JSFieldIndex(oneof->field(i)));
+    printer->Annotate("upcase", oneof->field(i));
   }
 
   printer->Print(
@@ -1550,7 +2075,7 @@
       "computeOneofCase(this, $class$.oneofGroups_[$oneofindex$]));\n"
       "};\n"
       "\n",
-      "class", GetPath(options, oneof->containing_type()),
+      "class", GetMessagePath(options, oneof->containing_type()),
       "oneof", JSOneofName(oneof),
       "oneofindex", JSOneofIndex(oneof));
 }
@@ -1589,10 +2114,11 @@
       " *     http://goto/soy-param-migration\n"
       " * @param {!$classname$} msg The msg instance to transform.\n"
       " * @return {!Object}\n"
+      " * @suppress {unusedLocalVariables} f is only used for nested messages\n"
       " */\n"
       "$classname$.toObject = function(includeInstance, msg) {\n"
       "  var f, obj = {",
-      "classname", GetPath(options, desc));
+      "classname", GetMessagePath(options, desc));
 
   bool first = true;
   for (int i = 0; i < desc->field_count(); i++) {
@@ -1623,61 +2149,127 @@
         "obj,\n"
         "      $extObject$, $class$.prototype.getExtension,\n"
         "      includeInstance);\n",
-        "extObject", JSExtensionsObjectName(options, desc),
-        "class", GetPath(options, desc));
+        "extObject", JSExtensionsObjectName(options, desc->file(), desc),
+        "class", GetMessagePath(options, desc));
   }
 
   printer->Print(
       "  if (includeInstance) {\n"
-      "    obj.$$jspbMessageInstance = msg\n"
+      "    obj.$$jspbMessageInstance = msg;\n"
       "  }\n"
       "  return obj;\n"
       "};\n"
       "}\n"
       "\n"
       "\n",
-      "classname", GetPath(options, desc));
+      "classname", GetMessagePath(options, desc));
+}
+
+void Generator::GenerateFieldValueExpression(io::Printer* printer,
+                                             const char *obj_reference,
+                                             const FieldDescriptor* field,
+                                             bool use_default) const {
+  bool is_float_or_double =
+      field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT ||
+      field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE;
+  if (use_default) {
+    if (is_float_or_double) {
+      // Coerce "Nan" and "Infinity" to actual float values.
+      //
+      // This will change null to 0, but that doesn't matter since we're getting
+      // with a default.
+      printer->Print("+");
+    }
+
+    printer->Print(
+        "jspb.Message.getFieldWithDefault($obj$, $index$, $default$)",
+        "obj", obj_reference,
+        "index", JSFieldIndex(field),
+        "default", JSFieldDefault(field));
+  } else {
+    if (is_float_or_double) {
+      if (field->is_required()) {
+        // Use "+" to convert all fields to numeric (including null).
+        printer->Print(
+            "+jspb.Message.getField($obj$, $index$)",
+            "index", JSFieldIndex(field),
+            "obj", obj_reference);
+      } else {
+        // Converts "NaN" and "Infinity" while preserving null.
+        printer->Print(
+            "jspb.Message.get$cardinality$FloatingPointField($obj$, $index$)",
+            "cardinality", field->is_repeated() ? "Repeated" : "Optional",
+            "index", JSFieldIndex(field),
+            "obj", obj_reference);
+      }
+    } else {
+      printer->Print("jspb.Message.get$cardinality$Field($obj$, $index$)",
+                     "cardinality", field->is_repeated() ? "Repeated" : "",
+                     "index", JSFieldIndex(field),
+                     "obj", obj_reference);
+    }
+  }
 }
 
 void Generator::GenerateClassFieldToObject(const GeneratorOptions& options,
                                            io::Printer* printer,
                                            const FieldDescriptor* field) const {
   printer->Print("$fieldname$: ",
-                 "fieldname", JSObjectFieldName(field));
+                 "fieldname", JSObjectFieldName(options, field));
 
-  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+  if (IsMap(options, field)) {
+    const FieldDescriptor* value_field = MapFieldValue(field);
+    // If the map values are of a message type, we must provide their static
+    // toObject() method; otherwise we pass undefined for that argument.
+    string value_to_object;
+    if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      value_to_object =
+          GetMessagePath(options, value_field->message_type()) + ".toObject";
+    } else {
+      value_to_object = "undefined";
+    }
+    printer->Print(
+        "(f = msg.get$name$()) ? f.toObject(includeInstance, $valuetoobject$) "
+        ": []",
+        "name", JSGetterName(options, field), "valuetoobject", value_to_object);
+  } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
     // Message field.
     if (field->is_repeated()) {
       {
         printer->Print("jspb.Message.toObjectList(msg.get$getter$(),\n"
                        "    $type$.toObject, includeInstance)",
-                       "getter", JSGetterName(field),
-                       "type", GetPath(options, field->message_type()));
+                       "getter", JSGetterName(options, field),
+                       "type", SubmessageTypeRef(options, field));
       }
     } else {
       printer->Print("(f = msg.get$getter$()) && "
                      "$type$.toObject(includeInstance, f)",
-                     "getter", JSGetterName(field),
-                     "type", GetPath(options, field->message_type()));
+                     "getter", JSGetterName(options, field),
+                     "type", SubmessageTypeRef(options, field));
     }
+  } else if (field->type() == FieldDescriptor::TYPE_BYTES) {
+    // For bytes fields we want to always return the B64 data.
+    printer->Print("msg.get$getter$()",
+                   "getter", JSGetterName(options, field, BYTES_B64));
   } else {
-    // Simple field (singular or repeated).
-    if (!HasFieldPresence(field) && !field->is_repeated()) {
-      // Delegate to the generated get<field>() method in order not to duplicate
-      // the proto3-field-default-value logic here.
-      printer->Print("msg.get$getter$()",
-                     "getter", JSGetterName(field));
-    } else {
-      if (field->has_default_value()) {
-        printer->Print("jspb.Message.getField(msg, $index$) != null ? "
-                       "jspb.Message.getField(msg, $index$) : $defaultValue$",
-                       "index", JSFieldIndex(field),
-                       "defaultValue", JSFieldDefault(field));
-      } else {
-        printer->Print("jspb.Message.getField(msg, $index$)",
-                       "index", JSFieldIndex(field));
-      }
+    bool use_default = field->has_default_value();
+
+    if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
+        // Repeated fields get initialized to their default in the constructor
+        // (why?), so we emit a plain getField() call for them.
+        !field->is_repeated() && !UseBrokenPresenceSemantics(options, field)) {
+      // Proto3 puts all defaults (including implicit defaults) in toObject().
+      // But for proto2 we leave the existing semantics unchanged: unset fields
+      // without default are unset.
+      use_default = true;
     }
+
+    // We don't implement this by calling the accessors, because the semantics
+    // of the accessors are changing independently of the toObject() semantics.
+    // We are migrating the accessors to return defaults instead of null, but
+    // it may take longer to migrate toObject (or we might not want to do it at
+    // all).  So we want to generate independent code.
+    GenerateFieldValueExpression(printer, "msg", field, use_default);
   }
 }
 
@@ -1694,7 +2286,7 @@
       " */\n"
       "$classname$.fromObject = function(obj) {\n"
       "  var f, msg = new $classname$();\n",
-      "classname", GetPath(options, desc));
+      "classname", GetMessagePath(options, desc));
 
   for (int i = 0; i < desc->field_count(); i++) {
     const FieldDescriptor* field = desc->field(i);
@@ -1711,7 +2303,29 @@
     const GeneratorOptions& options,
     io::Printer* printer,
     const FieldDescriptor* field) const {
-  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+  if (IsMap(options, field)) {
+    const FieldDescriptor* value_field = MapFieldValue(field);
+    if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
+      // Since the map values are of message type, we have to do some extra work
+      // to recursively call fromObject() on them before setting the map field.
+      printer->Print(
+          "  goog.isDef(obj.$name$) && jspb.Message.setWrapperField(\n"
+          "      msg, $index$, jspb.Map.fromObject(obj.$name$, $fieldclass$, "
+          "$fieldclass$.fromObject));\n",
+          "name", JSObjectFieldName(options, field),
+          "index", JSFieldIndex(field),
+          "fieldclass", GetMessagePath(options, value_field->message_type()));
+    } else {
+      // `msg` is a newly-constructed message object that has not yet built any
+      // map containers wrapping underlying arrays, so we can simply directly
+      // set the array here without fear of a stale wrapper.
+      printer->Print(
+          "  goog.isDef(obj.$name$) && "
+          "jspb.Message.setField(msg, $index$, obj.$name$);\n",
+          "name", JSObjectFieldName(options, field),
+          "index", JSFieldIndex(field));
+    }
+  } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
     // Message field (singular or repeated)
     if (field->is_repeated()) {
       {
@@ -1721,43 +2335,28 @@
             "      msg, $index$, goog.array.map(obj.$name$, function(i) {\n"
             "        return $fieldclass$.fromObject(i);\n"
             "      }));\n",
-            "name", JSObjectFieldName(field),
+            "name", JSObjectFieldName(options, field),
             "index", JSFieldIndex(field),
-            "fieldclass", GetPath(options, field->message_type()));
+            "fieldclass", SubmessageTypeRef(options, field));
       }
     } else {
       printer->Print(
           "  goog.isDef(obj.$name$) && jspb.Message.setWrapperField(\n"
           "      msg, $index$, $fieldclass$.fromObject(obj.$name$));\n",
-          "name", JSObjectFieldName(field),
+          "name", JSObjectFieldName(options, field),
           "index", JSFieldIndex(field),
-          "fieldclass", GetPath(options, field->message_type()));
+          "fieldclass", SubmessageTypeRef(options, field));
     }
   } else {
     // Simple (primitive) field.
     printer->Print(
         "  goog.isDef(obj.$name$) && jspb.Message.setField(msg, $index$, "
         "obj.$name$);\n",
-        "name", JSObjectFieldName(field),
+        "name", JSObjectFieldName(options, field),
         "index", JSFieldIndex(field));
   }
 }
 
-void Generator::GenerateClassClone(const GeneratorOptions& options,
-                                   io::Printer* printer,
-                                   const Descriptor* desc) const {
-  printer->Print(
-      "/**\n"
-      " * Creates a deep clone of this proto. No data is shared with the "
-      "original.\n"
-      " * @return {!$name$} The clone.\n"
-      " */\n"
-      "$name$.prototype.cloneMessage = function() {\n"
-      "  return /** @type {!$name$} */ (jspb.Message.cloneMessage(this));\n"
-      "};\n\n\n",
-      "name", GetPath(options, desc));
-}
-
 void Generator::GenerateClassRegistration(const GeneratorOptions& options,
                                           io::Printer* printer,
                                           const Descriptor* desc) const {
@@ -1781,10 +2380,101 @@
   }
 }
 
+void GenerateBytesWrapper(const GeneratorOptions& options,
+                          io::Printer* printer,
+                          const FieldDescriptor* field,
+                          BytesMode bytes_mode) {
+  string type = JSFieldTypeAnnotation(
+      options, field,
+      /* is_setter_argument = */ false,
+      /* force_present = */ false,
+      /* singular_if_not_packed = */ false, bytes_mode);
+  printer->Print(
+      "/**\n"
+      " * $fielddef$\n"
+      "$comment$"
+      " * This is a type-conversion wrapper around `get$defname$()`\n"
+      " * @return {$type$}\n"
+      " */\n"
+      "$class$.prototype.get$name$ = function() {\n"
+      "  return /** @type {$type$} */ (jspb.Message.bytes$list$As$suffix$(\n"
+      "      this.get$defname$()));\n"
+      "};\n"
+      "\n"
+      "\n",
+      "fielddef", FieldDefinition(options, field),
+      "comment", FieldComments(field, bytes_mode),
+      "type", type,
+      "class", GetMessagePath(options, field->containing_type()),
+      "name", JSGetterName(options, field, bytes_mode),
+      "list", field->is_repeated() ? "List" : "",
+      "suffix", JSByteGetterSuffix(bytes_mode),
+      "defname", JSGetterName(options, field, BYTES_DEFAULT));
+}
+
 void Generator::GenerateClassField(const GeneratorOptions& options,
                                    io::Printer* printer,
                                    const FieldDescriptor* field) const {
-  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+  if (IsMap(options, field)) {
+    const FieldDescriptor* key_field = MapFieldKey(field);
+    const FieldDescriptor* value_field = MapFieldValue(field);
+    // Map field: special handling to instantiate the map object on demand.
+    string key_type =
+        JSFieldTypeAnnotation(
+            options, key_field,
+            /* is_setter_argument = */ false,
+            /* force_present = */ true,
+            /* singular_if_not_packed = */ false);
+    string value_type =
+        JSFieldTypeAnnotation(
+            options, value_field,
+            /* is_setter_argument = */ false,
+            /* force_present = */ true,
+            /* singular_if_not_packed = */ false);
+
+    printer->Print(
+        "/**\n"
+        " * $fielddef$\n"
+        " * @param {boolean=} opt_noLazyCreate Do not create the map if\n"
+        " * empty, instead returning `undefined`\n"
+        " * @return {!jspb.Map<$keytype$,$valuetype$>}\n"
+        " */\n",
+        "fielddef", FieldDefinition(options, field),
+        "keytype", key_type,
+        "valuetype", value_type);
+    printer->Print(
+        "$class$.prototype.$gettername$ = function(opt_noLazyCreate) {\n"
+        "  return /** @type {!jspb.Map<$keytype$,$valuetype$>} */ (\n",
+        "class", GetMessagePath(options, field->containing_type()),
+        "gettername", "get" + JSGetterName(options, field),
+        "keytype", key_type,
+        "valuetype", value_type);
+    printer->Annotate("gettername", field);
+    printer->Print(
+        "      jspb.Message.getMapField(this, $index$, opt_noLazyCreate",
+        "index", JSFieldIndex(field));
+
+    if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
+      printer->Print(
+          ",\n"
+          "      $messageType$",
+          "messageType", GetMessagePath(options, value_field->message_type()));
+    } else {
+      printer->Print(",\n"
+          "      null");
+    }
+
+    printer->Print(
+        "));\n");
+
+    printer->Print(
+        "};\n"
+        "\n"
+        "\n");
+  } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+    // Message field: special handling in order to wrap the underlying data
+    // array with a message object.
+
     printer->Print(
         "/**\n"
         " * $fielddef$\n"
@@ -1792,47 +2482,46 @@
         " * @return {$type$}\n"
         " */\n",
         "fielddef", FieldDefinition(options, field),
-        "comment", FieldComments(field),
+        "comment", FieldComments(field, BYTES_DEFAULT),
         "type", JSFieldTypeAnnotation(options, field,
-                                      /* force_optional = */ false,
+                                      /* is_setter_argument = */ false,
                                       /* force_present = */ false,
-                                      /* singular_if_not_packed = */ false,
-                                      /* always_singular = */ false));
+                                      /* singular_if_not_packed = */ false));
     printer->Print(
-        "$class$.prototype.get$name$ = function() {\n"
+        "$class$.prototype.$gettername$ = function() {\n"
         "  return /** @type{$type$} */ (\n"
         "    jspb.Message.get$rpt$WrapperField(this, $wrapperclass$, "
         "$index$$required$));\n"
         "};\n"
         "\n"
         "\n",
-        "class", GetPath(options, field->containing_type()),
-        "name", JSGetterName(field),
+        "class", GetMessagePath(options, field->containing_type()),
+        "gettername", "get" + JSGetterName(options, field),
         "type", JSFieldTypeAnnotation(options, field,
-                                      /* force_optional = */ false,
+                                      /* is_setter_argument = */ false,
                                       /* force_present = */ false,
-                                      /* singular_if_not_packed = */ false,
-                                      /* always_singular = */ false),
+                                      /* singular_if_not_packed = */ false),
         "rpt", (field->is_repeated() ? "Repeated" : ""),
         "index", JSFieldIndex(field),
-        "wrapperclass", GetPath(options, field->message_type()),
+        "wrapperclass", SubmessageTypeRef(options, field),
         "required", (field->label() == FieldDescriptor::LABEL_REQUIRED ?
                      ", 1" : ""));
+    printer->Annotate("gettername", field);
     printer->Print(
-        "/** @param {$optionaltype$} value $returndoc$ */\n"
-        "$class$.prototype.set$name$ = function(value) {\n"
+        "/** @param {$optionaltype$} value$returndoc$ */\n"
+        "$class$.prototype.$settername$ = function(value) {\n"
         "  jspb.Message.set$oneoftag$$repeatedtag$WrapperField(",
         "optionaltype",
         JSFieldTypeAnnotation(options, field,
-                              /* force_optional = */ true,
+                              /* is_setter_argument = */ true,
                               /* force_present = */ false,
-                              /* singular_if_not_packed = */ false,
-                              /* always_singular = */ false),
+                              /* singular_if_not_packed = */ false),
         "returndoc", JSReturnDoc(options, field),
-        "class", GetPath(options, field->containing_type()),
-        "name", JSGetterName(field),
+        "class", GetMessagePath(options, field->containing_type()),
+        "settername", "set" + JSGetterName(options, field),
         "oneoftag", (field->containing_oneof() ? "Oneof" : ""),
         "repeatedtag", (field->is_repeated() ? "Repeated" : ""));
+    printer->Annotate("settername", field);
 
     printer->Print(
         "this, $index$$oneofgroup$, value);$returnvalue$\n"
@@ -1844,27 +2533,34 @@
                        (", " + JSOneofArray(options, field)) : ""),
         "returnvalue", JSReturnClause(field));
 
-    printer->Print(
-        "$class$.prototype.clear$name$ = function() {\n"
-        "  this.set$name$($clearedvalue$);$returnvalue$\n"
-        "};\n"
-        "\n"
-        "\n",
-        "class", GetPath(options, field->containing_type()),
-        "name", JSGetterName(field),
-        "clearedvalue", (field->is_repeated() ? "[]" : "undefined"),
-        "returnvalue", JSReturnClause(field));
+    if (field->is_repeated()) {
+      GenerateRepeatedMessageHelperMethods(options, printer, field);
+    }
 
   } else {
-    string typed_annotation;
+    bool untyped =
+        false;
 
     // Simple (primitive) field, either singular or repeated.
-    {
-      typed_annotation = JSFieldTypeAnnotation(options, field,
-                              /* force_optional = */ false,
-                              /* force_present = */ !HasFieldPresence(field),
-                              /* singular_if_not_packed = */ false,
-                              /* always_singular = */ false),
+
+    // TODO(b/26173701): Always use BYTES_DEFAULT for the getter return type;
+    // at this point we "lie" to non-binary users and tell the return
+    // type is always base64 string, pending a LSC to migrate to typed getters.
+    BytesMode bytes_mode =
+        field->type() == FieldDescriptor::TYPE_BYTES && !options.binary ?
+            BYTES_B64 : BYTES_DEFAULT;
+    string typed_annotation = JSFieldTypeAnnotation(
+        options, field,
+        /* is_setter_argument = */ false,
+        /* force_present = */ false,
+        /* singular_if_not_packed = */ false,
+        /* bytes_mode = */ bytes_mode);
+    if (untyped) {
+      printer->Print(
+          "/**\n"
+          " * @return {?} Raw field, untyped.\n"
+          " */\n");
+    } else {
       printer->Print(
           "/**\n"
           " * $fielddef$\n"
@@ -1872,41 +2568,47 @@
           " * @return {$type$}\n"
           " */\n",
           "fielddef", FieldDefinition(options, field),
-          "comment", FieldComments(field),
+          "comment", FieldComments(field, bytes_mode),
           "type", typed_annotation);
     }
 
     printer->Print(
-        "$class$.prototype.get$name$ = function() {\n",
-        "class", GetPath(options, field->containing_type()),
-        "name", JSGetterName(field));
+        "$class$.prototype.$gettername$ = function() {\n",
+        "class", GetMessagePath(options, field->containing_type()),
+        "gettername", "get" + JSGetterName(options, field));
+    printer->Annotate("gettername", field);
 
-    {
+    if (untyped) {
+      printer->Print(
+          "  return ");
+    } else {
       printer->Print(
           "  return /** @type {$type$} */ (",
           "type", typed_annotation);
     }
 
-    // For proto3 fields without presence, use special getters that will return
-    // defaults when the field is unset, possibly constructing a value if
-    // required.
-    if (!HasFieldPresence(field) && !field->is_repeated()) {
-      printer->Print("jspb.Message.getFieldProto3(this, $index$, $default$)",
-                     "index", JSFieldIndex(field),
-                     "default", Proto3PrimitiveFieldDefault(field));
-    } else {
-      if (field->has_default_value()) {
-        printer->Print("jspb.Message.getField(this, $index$) != null ? "
-                       "jspb.Message.getField(this, $index$) : $defaultValue$",
-                       "index", JSFieldIndex(field),
-                       "defaultValue", JSFieldDefault(field));
-      } else {
-        printer->Print("jspb.Message.getField(this, $index$)",
-                       "index", JSFieldIndex(field));
-      }
+    bool use_default = !ReturnsNullWhenUnset(options, field);
+
+    // Raw fields with no default set should just return undefined.
+    if (untyped && !field->has_default_value()) {
+      use_default = false;
     }
 
-    {
+    // Repeated fields get initialized to their default in the constructor
+    // (why?), so we emit a plain getField() call for them.
+    if (field->is_repeated()) {
+      use_default = false;
+    }
+
+    GenerateFieldValueExpression(printer, "this", field, use_default);
+
+    if (untyped) {
+      printer->Print(
+          ";\n"
+          "};\n"
+          "\n"
+          "\n");
+    } else {
       printer->Print(
           ");\n"
           "};\n"
@@ -1914,58 +2616,211 @@
           "\n");
     }
 
-    {
+    if (field->type() == FieldDescriptor::TYPE_BYTES && !untyped) {
+      GenerateBytesWrapper(options, printer, field, BYTES_B64);
+      GenerateBytesWrapper(options, printer, field, BYTES_U8);
+    }
+
+    if (untyped) {
       printer->Print(
-          "/** @param {$optionaltype$} value $returndoc$ */\n",
-          "optionaltype",
-          JSFieldTypeAnnotation(options, field,
-                                /* force_optional = */ true,
-                                /* force_present = */ !HasFieldPresence(field),
-                                /* singular_if_not_packed = */ false,
-                                /* always_singular = */ false),
+          "/**\n"
+          " * @param {*} value$returndoc$\n"
+          " */\n",
+          "returndoc", JSReturnDoc(options, field));
+    } else {
+      printer->Print(
+          "/** @param {$optionaltype$} value$returndoc$ */\n", "optionaltype",
+          JSFieldTypeAnnotation(
+              options, field,
+              /* is_setter_argument = */ true,
+              /* force_present = */ false,
+              /* singular_if_not_packed = */ false),
           "returndoc", JSReturnDoc(options, field));
     }
 
-    printer->Print(
-        "$class$.prototype.set$name$ = function(value) {\n"
-        "  jspb.Message.set$oneoftag$Field(this, $index$",
-        "class", GetPath(options, field->containing_type()),
-        "name", JSGetterName(field),
-        "oneoftag", (field->containing_oneof() ? "Oneof" : ""),
-        "index", JSFieldIndex(field));
-    printer->Print(
-        "$oneofgroup$, $type$value$rptvalueinit$$typeclose$);$returnvalue$\n"
-        "};\n"
-        "\n"
-        "\n",
-        "type", "",
-        "typeclose", "",
-        "oneofgroup",
-        (field->containing_oneof() ? (", " + JSOneofArray(options, field))
-                                   : ""),
-        "returnvalue", JSReturnClause(field), "rptvalueinit",
-        (field->is_repeated() ? " || []" : ""));
-
-
-    if (HasFieldPresence(field)) {
+    if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
+        !field->is_repeated() && !field->is_map() &&
+        !HasFieldPresence(options, field)) {
+      // Proto3 non-repeated and non-map fields without presence use the
+      // setProto3*Field function.
       printer->Print(
-          "$class$.prototype.clear$name$ = function() {\n"
-          "  jspb.Message.set$oneoftag$Field(this, $index$$oneofgroup$, ",
-          "class", GetPath(options, field->containing_type()),
-          "name", JSGetterName(field),
-          "oneoftag", (field->containing_oneof() ? "Oneof" : ""),
-          "oneofgroup", (field->containing_oneof() ?
-                         (", " + JSOneofArray(options, field)) : ""),
-          "index", JSFieldIndex(field));
-      printer->Print(
-          "$clearedvalue$);$returnvalue$\n"
+          "$class$.prototype.$settername$ = function(value) {\n"
+          "  jspb.Message.setProto3$typetag$Field(this, $index$, "
+          "value);$returnvalue$\n"
           "};\n"
           "\n"
           "\n",
-          "clearedvalue", (field->is_repeated() ? "[]" : "undefined"),
-          "returnvalue", JSReturnClause(field));
+          "class", GetMessagePath(options, field->containing_type()),
+          "settername", "set" + JSGetterName(options, field), "typetag",
+          JSTypeTag(field), "index", JSFieldIndex(field), "returnvalue",
+          JSReturnClause(field));
+      printer->Annotate("settername", field);
+    } else {
+      // Otherwise, use the regular setField function.
+      printer->Print(
+          "$class$.prototype.$settername$ = function(value) {\n"
+          "  jspb.Message.set$oneoftag$Field(this, $index$",
+          "class", GetMessagePath(options, field->containing_type()),
+          "settername", "set" + JSGetterName(options, field), "oneoftag",
+          (field->containing_oneof() ? "Oneof" : ""), "index",
+          JSFieldIndex(field));
+      printer->Annotate("settername", field);
+      printer->Print(
+          "$oneofgroup$, $type$value$rptvalueinit$$typeclose$);$returnvalue$\n"
+          "};\n"
+          "\n"
+          "\n",
+          "type",
+          untyped ? "/** @type{string|number|boolean|Array|undefined} */(" : "",
+          "typeclose", untyped ? ")" : "", "oneofgroup",
+          (field->containing_oneof() ? (", " + JSOneofArray(options, field))
+                                     : ""),
+          "returnvalue", JSReturnClause(field), "rptvalueinit",
+          (field->is_repeated() ? " || []" : ""));
+    }
+
+    if (untyped) {
+      printer->Print(
+          "/**\n"
+          " * Clears the value.$returndoc$\n"
+          " */\n",
+          "returndoc", JSReturnDoc(options, field));
+    }
+
+
+    if (field->is_repeated()) {
+      GenerateRepeatedPrimitiveHelperMethods(options, printer, field, untyped);
     }
   }
+
+  // Generate clearFoo() method for map fields, repeated fields, and other
+  // fields with presence.
+  if (IsMap(options, field)) {
+    printer->Print(
+        "$class$.prototype.$clearername$ = function() {\n"
+        "  this.$gettername$().clear();$returnvalue$\n"
+        "};\n"
+        "\n"
+        "\n",
+        "class", GetMessagePath(options, field->containing_type()),
+        "clearername", "clear" + JSGetterName(options, field),
+        "gettername", "get" + JSGetterName(options, field),
+        "returnvalue", JSReturnClause(field));
+    printer->Annotate("clearername", field);
+  } else if (field->is_repeated() ||
+             (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+              !field->is_required())) {
+    // Fields where we can delegate to the regular setter.
+    printer->Print(
+        "$class$.prototype.$clearername$ = function() {\n"
+        "  this.$settername$($clearedvalue$);$returnvalue$\n"
+        "};\n"
+        "\n"
+        "\n",
+        "class", GetMessagePath(options, field->containing_type()),
+        "clearername", "clear" + JSGetterName(options, field),
+        "settername", "set" + JSGetterName(options, field),
+        "clearedvalue", (field->is_repeated() ? "[]" : "undefined"),
+        "returnvalue", JSReturnClause(field));
+    printer->Annotate("clearername", field);
+  } else if (HasFieldPresence(options, field)) {
+    // Fields where we can't delegate to the regular setter because it doesn't
+    // accept "undefined" as an argument.
+    printer->Print(
+        "$class$.prototype.$clearername$ = function() {\n"
+        "  jspb.Message.set$maybeoneof$Field(this, "
+        "$index$$maybeoneofgroup$, ",
+        "class", GetMessagePath(options, field->containing_type()),
+        "clearername", "clear" + JSGetterName(options, field),
+        "maybeoneof", (field->containing_oneof() ? "Oneof" : ""),
+        "maybeoneofgroup", (field->containing_oneof() ?
+                           (", " + JSOneofArray(options, field)) : ""),
+        "index", JSFieldIndex(field));
+    printer->Annotate("clearername", field);
+    printer->Print(
+        "$clearedvalue$);$returnvalue$\n"
+        "};\n"
+        "\n"
+        "\n",
+        "clearedvalue", (field->is_repeated() ? "[]" : "undefined"),
+        "returnvalue", JSReturnClause(field));
+  }
+
+  if (HasFieldPresence(options, field)) {
+    printer->Print(
+        "/**\n"
+        " * Returns whether this field is set.\n"
+        " * @return {!boolean}\n"
+        " */\n"
+        "$class$.prototype.$hasername$ = function() {\n"
+        "  return jspb.Message.getField(this, $index$) != null;\n"
+        "};\n"
+        "\n"
+        "\n",
+        "class", GetMessagePath(options, field->containing_type()),
+        "hasername", "has" + JSGetterName(options, field),
+        "index", JSFieldIndex(field));
+    printer->Annotate("hasername", field);
+  }
+}
+
+void Generator::GenerateRepeatedPrimitiveHelperMethods(
+    const GeneratorOptions& options, io::Printer* printer,
+    const FieldDescriptor* field, bool untyped) const {
+  // clang-format off
+  printer->Print(
+      "/**\n"
+      " * @param {!$optionaltype$} value\n"
+      " * @param {number=} opt_index$returndoc$\n"
+      " */\n"
+      "$class$.prototype.$addername$ = function(value, opt_index) {\n"
+      "  jspb.Message.addToRepeatedField(this, $index$",
+      "class", GetMessagePath(options, field->containing_type()), "addername",
+      "add" + JSGetterName(options, field, BYTES_DEFAULT,
+                           /* drop_list = */ true),
+      "optionaltype", JSTypeName(options, field, BYTES_DEFAULT),
+      "index", JSFieldIndex(field),
+      "returndoc", JSReturnDoc(options, field));
+  printer->Annotate("addername", field);
+  printer->Print(
+      "$oneofgroup$, $type$value$rptvalueinit$$typeclose$, "
+      "opt_index);$returnvalue$\n"
+      "};\n"
+      "\n"
+      "\n",
+      "type", untyped ? "/** @type{string|number|boolean|!Uint8Array} */(" : "",
+      "typeclose", untyped ? ")" : "", "oneofgroup",
+      (field->containing_oneof() ? (", " + JSOneofArray(options, field)) : ""),
+      "rptvalueinit", "",
+      "returnvalue", JSReturnClause(field));
+  // clang-format on
+}
+
+void Generator::GenerateRepeatedMessageHelperMethods(
+    const GeneratorOptions& options, io::Printer* printer,
+    const FieldDescriptor* field) const {
+  printer->Print(
+      "/**\n"
+      " * @param {!$optionaltype$=} opt_value\n"
+      " * @param {number=} opt_index\n"
+      " * @return {!$optionaltype$}\n"
+      " */\n"
+      "$class$.prototype.add$name$ = function(opt_value, opt_index) {\n"
+      "  return jspb.Message.addTo$repeatedtag$WrapperField(",
+      "optionaltype", JSTypeName(options, field, BYTES_DEFAULT),
+      "class", GetMessagePath(options, field->containing_type()),
+      "name", JSGetterName(options, field, BYTES_DEFAULT,
+                   /* drop_list = */ true),
+      "repeatedtag", (field->is_repeated() ? "Repeated" : ""));
+
+  printer->Print(
+      "this, $index$$oneofgroup$, opt_value, $ctor$, opt_index);\n"
+      "};\n"
+      "\n"
+      "\n",
+      "index", JSFieldIndex(field), "oneofgroup",
+      (field->containing_oneof() ? (", " + JSOneofArray(options, field)) : ""),
+      "ctor", GetMessagePath(options, field->message_type()));
 }
 
 void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options,
@@ -1987,11 +2842,32 @@
         "so that it\n"
         " * works in OPTIMIZED mode.\n"
         " *\n"
-        " * @type {!Object.<number, jspb.ExtensionFieldInfo>}\n"
+        " * @type {!Object<number, jspb.ExtensionFieldInfo>}\n"
         " */\n"
         "$class$.extensions = {};\n"
         "\n",
-        "class", GetPath(options, desc));
+        "class", GetMessagePath(options, desc));
+
+    printer->Print(
+        "\n"
+        "/**\n"
+        " * The extensions registered with this message class. This is a "
+        "map of\n"
+        " * extension field number to fieldInfo object.\n"
+        " *\n"
+        " * For example:\n"
+        " *     { 123: {fieldIndex: 123, fieldName: {my_field_name: 0}, "
+        "ctor: proto.example.MyMessage} }\n"
+        " *\n"
+        " * fieldName contains the JsCompiler renamed field name property "
+        "so that it\n"
+        " * works in OPTIMIZED mode.\n"
+        " *\n"
+        " * @type {!Object<number, jspb.ExtensionFieldBinaryInfo>}\n"
+        " */\n"
+        "$class$.extensionsBinary = {};\n"
+        "\n",
+        "class", GetMessagePath(options, desc));
   }
 }
 
@@ -2029,22 +2905,24 @@
       "    }\n"
       "    var field = reader.getFieldNumber();\n"
       "    switch (field) {\n",
-      "class", GetPath(options, desc));
+      "class", GetMessagePath(options, desc));
 
   for (int i = 0; i < desc->field_count(); i++) {
-    GenerateClassDeserializeBinaryField(options, printer, desc->field(i));
+    if (!IgnoreField(desc->field(i))) {
+      GenerateClassDeserializeBinaryField(options, printer, desc->field(i));
+    }
   }
 
   printer->Print(
       "    default:\n");
   if (IsExtendable(desc)) {
     printer->Print(
-        "      jspb.Message.readBinaryExtension(msg, reader, $extobj$,\n"
+        "      jspb.Message.readBinaryExtension(msg, reader, $extobj$Binary,\n"
         "        $class$.prototype.getExtension,\n"
         "        $class$.prototype.setExtension);\n"
         "      break;\n",
-        "extobj", JSExtensionsObjectName(options, desc),
-        "class", GetPath(options, desc));
+        "extobj", JSExtensionsObjectName(options, desc->file(), desc),
+        "class", GetMessagePath(options, desc));
   } else {
     printer->Print(
         "      reader.skipField();\n"
@@ -2068,38 +2946,64 @@
   printer->Print("    case $num$:\n",
                  "num", SimpleItoa(field->number()));
 
-  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+  if (IsMap(options, field)) {
+    const FieldDescriptor* key_field = MapFieldKey(field);
+    const FieldDescriptor* value_field = MapFieldValue(field);
     printer->Print(
-        "      var value = new $fieldclass$;\n"
-        "      reader.read$msgOrGroup$($grpfield$value,"
-        "$fieldclass$.deserializeBinaryFromReader);\n",
-        "fieldclass", GetPath(options, field->message_type()),
-        "msgOrGroup", (field->type() == FieldDescriptor::TYPE_GROUP) ?
-                      "Group" : "Message",
-        "grpfield", (field->type() == FieldDescriptor::TYPE_GROUP) ?
-                    (SimpleItoa(field->number()) + ", ") : "");
-  } else {
-    printer->Print(
-        "      var value = /** @type {$fieldtype$} */ (reader.$reader$());\n",
-        "fieldtype", JSFieldTypeAnnotation(options, field, false, true,
-                                           /* singular_if_not_packed = */ true,
-                                           /* always_singular = */ false),
-        "reader", JSBinaryReaderMethodName(field));
-  }
+        "      var value = msg.get$name$();\n"
+        "      reader.readMessage(value, function(message, reader) {\n",
+        "name", JSGetterName(options, field));
 
-  if (field->is_repeated() && !field->is_packed()) {
-    // Repeated fields receive a |value| one at at a time; append to array
-    // returned by get$name$().
-    printer->Print(
-        "      msg.get$name$().push(value);\n",
-        "name", JSGetterName(field));
+    printer->Print("        jspb.Map.deserializeBinary(message, reader, "
+                   "$keyReaderFn$, $valueReaderFn$",
+          "keyReaderFn", JSBinaryReaderMethodName(options, key_field),
+          "valueReaderFn", JSBinaryReaderMethodName(options, value_field));
+
+    if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
+      printer->Print(", $messageType$.deserializeBinaryFromReader",
+          "messageType", GetMessagePath(options, value_field->message_type()));
+    } else {
+      printer->Print(", null");
+    }
+    printer->Print(", $defaultKey$",
+          "defaultKey", JSFieldDefault(key_field)
+    );
+    printer->Print(");\n");
+    printer->Print("         });\n");
   } else {
-    // Singular fields, and packed repeated fields, receive a |value| either as
-    // the field's value or as the array of all the field's values; set this as
-    // the field's value directly.
-    printer->Print(
-        "      msg.set$name$(value);\n",
-        "name", JSGetterName(field));
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      printer->Print(
+          "      var value = new $fieldclass$;\n"
+          "      reader.read$msgOrGroup$($grpfield$value,"
+          "$fieldclass$.deserializeBinaryFromReader);\n",
+        "fieldclass", SubmessageTypeRef(options, field),
+          "msgOrGroup", (field->type() == FieldDescriptor::TYPE_GROUP) ?
+                        "Group" : "Message",
+          "grpfield", (field->type() == FieldDescriptor::TYPE_GROUP) ?
+                      (SimpleItoa(field->number()) + ", ") : "");
+    } else {
+      printer->Print(
+          "      var value = /** @type {$fieldtype$} */ "
+          "(reader.read$reader$());\n",
+          "fieldtype", JSFieldTypeAnnotation(options, field, false, true,
+                                             /* singular_if_not_packed */ true,
+                                             BYTES_U8),
+          "reader",
+          JSBinaryReadWriteMethodName(field, /* is_writer = */ false));
+    }
+
+    if (field->is_repeated() && !field->is_packed()) {
+      printer->Print(
+          "      msg.add$name$(value);\n", "name",
+          JSGetterName(options, field, BYTES_DEFAULT, /* drop_list = */ true));
+    } else {
+      // Singular fields, and packed repeated fields, receive a |value| either
+      // as the field's value or as the array of all the field's values; set
+      // this as the field's value directly.
+      printer->Print(
+          "      msg.set$name$(value);\n",
+          "name", JSGetterName(options, field));
+    }
   }
 
   printer->Print("      break;\n");
@@ -2110,47 +3014,40 @@
                                              const Descriptor* desc) const {
   printer->Print(
       "/**\n"
-      " * Class method variant: serializes the given message to binary data\n"
-      " * (in protobuf wire format), writing to the given BinaryWriter.\n"
-      " * @param {!$class$} message\n"
-      " * @param {!jspb.BinaryWriter} writer\n"
-      " */\n"
-      "$class$.serializeBinaryToWriter = function(message, "
-      "writer) {\n"
-      "  message.serializeBinaryToWriter(writer);\n"
-      "};\n"
-      "\n"
-      "\n"
-      "/**\n"
       " * Serializes the message to binary data (in protobuf wire format).\n"
       " * @return {!Uint8Array}\n"
       " */\n"
       "$class$.prototype.serializeBinary = function() {\n"
       "  var writer = new jspb.BinaryWriter();\n"
-      "  this.serializeBinaryToWriter(writer);\n"
+      "  $class$.serializeBinaryToWriter(this, writer);\n"
       "  return writer.getResultBuffer();\n"
       "};\n"
       "\n"
       "\n"
       "/**\n"
-      " * Serializes the message to binary data (in protobuf wire format),\n"
-      " * writing to the given BinaryWriter.\n"
+      " * Serializes the given message to binary data (in protobuf wire\n"
+      " * format), writing to the given BinaryWriter.\n"
+      " * @param {!$class$} message\n"
       " * @param {!jspb.BinaryWriter} writer\n"
+      " * @suppress {unusedLocalVariables} f is only used for nested messages\n"
       " */\n"
-      "$class$.prototype.serializeBinaryToWriter = function (writer) {\n"
+      "$class$.serializeBinaryToWriter = function(message, "
+      "writer) {\n"
       "  var f = undefined;\n",
-      "class", GetPath(options, desc));
+      "class", GetMessagePath(options, desc));
 
   for (int i = 0; i < desc->field_count(); i++) {
-    GenerateClassSerializeBinaryField(options, printer, desc->field(i));
+    if (!IgnoreField(desc->field(i))) {
+      GenerateClassSerializeBinaryField(options, printer, desc->field(i));
+    }
   }
 
   if (IsExtendable(desc)) {
     printer->Print(
-        "  jspb.Message.serializeBinaryExtensions(this, writer, $extobj$,\n"
-        "    $class$.prototype.getExtension);\n",
-        "extobj", JSExtensionsObjectName(options, desc),
-        "class", GetPath(options, desc));
+        "  jspb.Message.serializeBinaryExtensions(message, writer,\n"
+        "    $extobj$Binary, $class$.prototype.getExtension);\n",
+        "extobj", JSExtensionsObjectName(options, desc->file(), desc),
+        "class", GetMessagePath(options, desc));
   }
 
   printer->Print(
@@ -2163,15 +3060,37 @@
     const GeneratorOptions& options,
     io::Printer* printer,
     const FieldDescriptor* field) const {
-  printer->Print(
-      "  f = this.get$name$();\n",
-      "name", JSGetterName(field));
+  if (HasFieldPresence(options, field) &&
+      field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+    string typed_annotation = JSFieldTypeAnnotation(
+        options, field,
+        /* is_setter_argument = */ false,
+        /* force_present = */ false,
+        /* singular_if_not_packed = */ false,
+        /* bytes_mode = */ BYTES_DEFAULT);
+    printer->Print(
+        "  f = /** @type {$type$} */ "
+        "(jspb.Message.getField(message, $index$));\n",
+        "index", JSFieldIndex(field),
+        "type", typed_annotation);
+  } else {
+    printer->Print(
+        "  f = message.get$name$($nolazy$);\n",
+        "name", JSGetterName(options, field, BYTES_U8),
+        // No lazy creation for maps containers -- fastpath the empty case.
+        "nolazy", IsMap(options, field) ? "true" : "");
+  }
 
-  if (field->is_repeated()) {
+  // Print an `if (condition)` statement that evaluates to true if the field
+  // goes on the wire.
+  if (IsMap(options, field)) {
+    printer->Print(
+        "  if (f && f.getLength() > 0) {\n");
+  } else if (field->is_repeated()) {
     printer->Print(
         "  if (f.length > 0) {\n");
   } else {
-    if (HasFieldPresence(field)) {
+    if (HasFieldPresence(options, field)) {
       printer->Print(
           "  if (f != null) {\n");
     } else {
@@ -2183,7 +3102,13 @@
         case FieldDescriptor::CPPTYPE_INT64:
         case FieldDescriptor::CPPTYPE_UINT32:
         case FieldDescriptor::CPPTYPE_UINT64: {
-          {
+          if (IsIntegralFieldWithStringJSType(field)) {
+            // We can use `parseInt` here even though it will not be precise for
+            // 64-bit quantities because we are only testing for zero/nonzero,
+            // and JS numbers (64-bit floating point values, i.e., doubles) are
+            // integer-precise in the range that includes zero.
+            printer->Print("  if (parseInt(f, 10) !== 0) {\n");
+          } else {
             printer->Print("  if (f !== 0) {\n");
           }
           break;
@@ -2210,24 +3135,47 @@
     }
   }
 
-  printer->Print(
-      "    writer.$writer$(\n"
-      "      $index$,\n"
-      "      f",
-      "writer", JSBinaryWriterMethodName(field),
-      "name", JSGetterName(field),
-      "index", SimpleItoa(field->number()));
-
-  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+  // Write the field on the wire.
+  if (IsMap(options, field)) {
+    const FieldDescriptor* key_field = MapFieldKey(field);
+    const FieldDescriptor* value_field = MapFieldValue(field);
     printer->Print(
-        ",\n"
-        "      $submsg$.serializeBinaryToWriter\n",
-        "submsg", GetPath(options, field->message_type()));
+        "    f.serializeBinary($index$, writer, "
+                              "$keyWriterFn$, $valueWriterFn$",
+        "index", SimpleItoa(field->number()),
+        "keyWriterFn", JSBinaryWriterMethodName(options, key_field),
+        "valueWriterFn", JSBinaryWriterMethodName(options, value_field));
+
+    if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) {
+      printer->Print(", $messageType$.serializeBinaryToWriter",
+          "messageType", GetMessagePath(options, value_field->message_type()));
+    }
+
+    printer->Print(");\n");
   } else {
-    printer->Print("\n");
+    printer->Print(
+        "    writer.write$method$(\n"
+        "      $index$,\n"
+        "      f",
+        "method", JSBinaryReadWriteMethodName(field, /* is_writer = */ true),
+        "index", SimpleItoa(field->number()));
+
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+        !IsMap(options, field)) {
+      printer->Print(
+          ",\n"
+          "      $submsg$.serializeBinaryToWriter\n",
+        "submsg", SubmessageTypeRef(options, field));
+    } else {
+      printer->Print("\n");
+    }
+
+    printer->Print(
+        "    );\n");
   }
+
+  // Close the `if`.
   printer->Print(
-      "    );\n"
       "  }\n");
 }
 
@@ -2238,8 +3186,10 @@
       "/**\n"
       " * @enum {number}\n"
       " */\n"
-      "$name$ = {\n",
-      "name", GetPath(options, enumdesc));
+      "$enumprefix$$name$ = {\n",
+      "enumprefix", GetEnumPathPrefix(options, enumdesc),
+      "name", enumdesc->name());
+  printer->Annotate("name", enumdesc);
 
   for (int i = 0; i < enumdesc->value_count(); i++) {
     const EnumValueDescriptor* value = enumdesc->value(i);
@@ -2248,6 +3198,7 @@
         "name", ToEnumCase(value->name()),
         "value", SimpleItoa(value->number()),
         "comma", (i == enumdesc->value_count() - 1) ? "" : ",");
+    printer->Annotate("name", value);
   }
 
   printer->Print(
@@ -2259,26 +3210,28 @@
                                   io::Printer* printer,
                                   const FieldDescriptor* field) const {
   string extension_scope =
-      (field->extension_scope() ?
-       GetPath(options, field->extension_scope()) :
-       GetPath(options, field->file()));
+      (field->extension_scope()
+           ? GetMessagePath(options, field->extension_scope())
+           : GetFilePath(options, field->file()));
 
+  const string extension_object_name = JSObjectFieldName(options, field);
   printer->Print(
       "\n"
       "/**\n"
       " * A tuple of {field number, class constructor} for the extension\n"
-      " * field named `$name$`.\n"
-      " * @type {!jspb.ExtensionFieldInfo.<$extensionType$>}\n"
+      " * field named `$nameInComment$`.\n"
+      " * @type {!jspb.ExtensionFieldInfo<$extensionType$>}\n"
       " */\n"
       "$class$.$name$ = new jspb.ExtensionFieldInfo(\n",
-      "name", JSObjectFieldName(field),
+      "nameInComment", extension_object_name,
+      "name", extension_object_name,
       "class", extension_scope,
       "extensionType", JSFieldTypeAnnotation(
           options, field,
-          /* force_optional = */ false,
+          /* is_setter_argument = */ false,
           /* force_present = */ true,
-          /* singular_if_not_packed = */ false,
-          /* always_singular = */ false));
+          /* singular_if_not_packed = */ false));
+  printer->Annotate("name", field);
   printer->Print(
       "    $index$,\n"
       "    {$name$: 0},\n"
@@ -2286,52 +3239,55 @@
       "     /** @type {?function((boolean|undefined),!jspb.Message=): "
       "!Object} */ (\n"
       "         $toObject$),\n"
-      "    $repeated$",
+      "    $repeated$);\n",
       "index", SimpleItoa(field->number()),
-      "name", JSObjectFieldName(field),
+      "name", extension_object_name,
       "ctor", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ?
-               GetPath(options, field->message_type()) : string("null")),
+               SubmessageTypeRef(options, field) : string("null")),
       "toObject", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ?
-                   (GetPath(options, field->message_type()) + ".toObject") :
+                   (SubmessageTypeRef(options, field) + ".toObject") :
                    string("null")),
       "repeated", (field->is_repeated() ? "1" : "0"));
 
-  if (options.binary) {
-    printer->Print(
-        ",\n"
-        "    jspb.BinaryReader.prototype.$binaryReaderFn$,\n"
-        "    jspb.BinaryWriter.prototype.$binaryWriterFn$,\n"
-        "    $binaryMessageSerializeFn$,\n"
-        "    $binaryMessageDeserializeFn$,\n"
-        "    $isPacked$);\n",
-        "binaryReaderFn", JSBinaryReaderMethodName(field),
-        "binaryWriterFn", JSBinaryWriterMethodName(field),
-        "binaryMessageSerializeFn",
-        (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ?
-        (GetPath(options, field->message_type()) +
-         ".serializeBinaryToWriter") : "null",
-        "binaryMessageDeserializeFn",
-        (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ?
-        (GetPath(options, field->message_type()) +
-         ".deserializeBinaryFromReader") : "null",
-        "isPacked", (field->is_packed() ? "true" : "false"));
-  } else {
-    printer->Print(");\n");
-  }
+  printer->Print(
+      "\n"
+      "$extendName$Binary[$index$] = new jspb.ExtensionFieldBinaryInfo(\n"
+      "    $class$.$name$,\n"
+      "    $binaryReaderFn$,\n"
+      "    $binaryWriterFn$,\n"
+      "    $binaryMessageSerializeFn$,\n"
+      "    $binaryMessageDeserializeFn$,\n",
+      "extendName",
+      JSExtensionsObjectName(options, field->file(), field->containing_type()),
+      "index", SimpleItoa(field->number()), "class", extension_scope, "name",
+      extension_object_name, "binaryReaderFn",
+      JSBinaryReaderMethodName(options, field), "binaryWriterFn",
+      JSBinaryWriterMethodName(options, field), "binaryMessageSerializeFn",
+      (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE)
+          ? (SubmessageTypeRef(options, field) + ".serializeBinaryToWriter")
+          : "undefined",
+      "binaryMessageDeserializeFn",
+      (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE)
+          ? (SubmessageTypeRef(options, field) + ".deserializeBinaryFromReader")
+          : "undefined");
+
+  printer->Print("    $isPacked$);\n", "isPacked",
+                 (field->is_packed() ? "true" : "false"));
 
   printer->Print(
       "// This registers the extension field with the extended class, so that\n"
       "// toObject() will function correctly.\n"
       "$extendName$[$index$] = $class$.$name$;\n"
       "\n",
-      "extendName", JSExtensionsObjectName(options, field->containing_type()),
+      "extendName", JSExtensionsObjectName(options, field->file(),
+                                           field->containing_type()),
       "index", SimpleItoa(field->number()),
       "class", extension_scope,
-      "name", JSObjectFieldName(field));
+      "name", extension_object_name);
 }
 
 bool GeneratorOptions::ParseFromOptions(
-    const vector< pair< string, string > >& options,
+    const std::vector< std::pair< string, string > >& options,
     string* error) {
   for (int i = 0; i < options.size(); i++) {
     if (options[i].first == "add_require_for_enums") {
@@ -2364,6 +3320,33 @@
       namespace_prefix = options[i].second;
     } else if (options[i].first == "library") {
       library = options[i].second;
+    } else if (options[i].first == "import_style") {
+      if (options[i].second == "closure") {
+        import_style = kImportClosure;
+      } else if (options[i].second == "commonjs") {
+        import_style = kImportCommonJs;
+      } else if (options[i].second == "browser") {
+        import_style = kImportBrowser;
+      } else if (options[i].second == "es6") {
+        import_style = kImportEs6;
+      } else {
+        *error = "Unknown import style " + options[i].second + ", expected " +
+                 "one of: closure, commonjs, browser, es6.";
+      }
+    } else if (options[i].first == "extension") {
+      extension = options[i].second;
+    } else if (options[i].first == "one_output_file_per_input_file") {
+      if (!options[i].second.empty()) {
+        *error = "Unexpected option value for one_output_file_per_input_file";
+        return false;
+      }
+      one_output_file_per_input_file = true;
+    } else if (options[i].first == "annotate_code") {
+      if (!options[i].second.empty()) {
+        *error = "Unexpected option value for annotate_code";
+        return false;
+      }
+      annotate_code = true;
     } else {
       // Assume any other option is an output directory, as long as it is a bare
       // `key` rather than a `key=value` option.
@@ -2375,13 +3358,40 @@
     }
   }
 
+  if (import_style != kImportClosure &&
+      (add_require_for_enums || testonly || !library.empty() ||
+       error_on_name_conflict || extension != ".js" ||
+       one_output_file_per_input_file)) {
+    *error =
+        "The add_require_for_enums, testonly, library, error_on_name_conflict, "
+        "extension, and one_output_file_per_input_file options should only be "
+        "used for import_style=closure";
+    return false;
+  }
+
   return true;
 }
 
+GeneratorOptions::OutputMode GeneratorOptions::output_mode() const {
+  // We use one output file per input file if we are not using Closure or if
+  // this is explicitly requested.
+  if (import_style != kImportClosure || one_output_file_per_input_file) {
+    return kOneOutputFilePerInputFile;
+  }
+
+  // If a library name is provided, we put everything in that one file.
+  if (!library.empty()) {
+    return kEverythingInOneFile;
+  }
+
+  // Otherwise, we create one output file per type.
+  return kOneOutputFilePerType;
+}
+
 void Generator::GenerateFilesInDepOrder(
     const GeneratorOptions& options,
     io::Printer* printer,
-    const vector<const FileDescriptor*>& files) const {
+    const std::vector<const FileDescriptor*>& files) const {
   // Build a std::set over all files so that the DFS can detect when it recurses
   // into a dep not specified in the user's command line.
   std::set<const FileDescriptor*> all_files(files.begin(), files.end());
@@ -2418,11 +3428,78 @@
   }
 }
 
-bool Generator::GenerateAll(const vector<const FileDescriptor*>& files,
+void Generator::GenerateFile(const GeneratorOptions& options,
+                             io::Printer* printer,
+                             const FileDescriptor* file) const {
+  GenerateHeader(options, printer);
+
+  // Generate "require" statements.
+  if (options.import_style == GeneratorOptions::kImportCommonJs) {
+    printer->Print("var jspb = require('google-protobuf');\n");
+    printer->Print("var goog = jspb;\n");
+    printer->Print("var global = Function('return this')();\n\n");
+
+    for (int i = 0; i < file->dependency_count(); i++) {
+      const string& name = file->dependency(i)->name();
+      printer->Print(
+          "var $alias$ = require('$file$');\n",
+          "alias", ModuleAlias(name),
+          "file",
+          GetRootPath(file->name(), name) + GetJSFilename(options, name));
+    }
+  }
+
+  std::set<string> provided;
+  std::set<const FieldDescriptor*> extensions;
+  for (int i = 0; i < file->extension_count(); i++) {
+    // We honor the jspb::ignore option here only when working with
+    // Closure-style imports. Use of this option is discouraged and so we want
+    // to avoid adding new support for it.
+    if (options.import_style == GeneratorOptions::kImportClosure &&
+        IgnoreField(file->extension(i))) {
+      continue;
+    }
+    provided.insert(GetFilePath(options, file) + "." +
+                    JSObjectFieldName(options, file->extension(i)));
+    extensions.insert(file->extension(i));
+  }
+
+  FindProvidesForFile(options, printer, file, &provided);
+  GenerateProvides(options, printer, &provided);
+  std::vector<const FileDescriptor*> files;
+  files.push_back(file);
+  if (options.import_style == GeneratorOptions::kImportClosure) {
+    GenerateRequiresForLibrary(options, printer, files, &provided);
+  }
+
+  GenerateClassesAndEnums(options, printer, file);
+
+  // Generate code for top-level extensions. Extensions nested inside messages
+  // are emitted inside GenerateClassesAndEnums().
+  for (std::set<const FieldDescriptor*>::const_iterator it = extensions.begin();
+       it != extensions.end(); ++it) {
+    GenerateExtension(options, printer, *it);
+  }
+
+  if (options.import_style == GeneratorOptions::kImportCommonJs) {
+    printer->Print("goog.object.extend(exports, $package$);\n",
+                   "package", GetFilePath(options, file));
+  }
+
+  // Emit well-known type methods.
+  for (FileToc* toc = well_known_types_js; toc->name != NULL; toc++) {
+    string name = string("google/protobuf/") + toc->name;
+    if (name == StripProto(file->name()) + ".js") {
+      printer->Print(toc->data);
+    }
+  }
+}
+
+bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files,
                             const string& parameter,
                             GeneratorContext* context,
                             string* error) const {
-  vector< pair< string, string > > option_pairs;
+  std::vector< std::pair< string, string > > option_pairs;
   ParseGeneratorParameter(parameter, &option_pairs);
   GeneratorOptions options;
   if (!options.ParseFromOptions(option_pairs, error)) {
@@ -2430,18 +3507,17 @@
   }
 
 
-  // We're either generating a single library file with definitions for message
-  // and enum types in *all* FileDescriptor inputs, or we're generating a single
-  // file for each type.
-  if (options.library != "") {
-    string filename = options.output_dir + "/" + options.library + ".js";
-    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+  if (options.output_mode() == GeneratorOptions::kEverythingInOneFile) {
+    // All output should go in a single file.
+    string filename = options.output_dir + "/" + options.library +
+                      options.GetFileNameExtension();
+    std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
     GOOGLE_CHECK(output.get());
     io::Printer printer(output.get(), '$');
 
     // Pull out all extensions -- we need these to generate all
     // provides/requires.
-    vector<const FieldDescriptor*> extensions;
+    std::vector<const FieldDescriptor*> extensions;
     for (int i = 0; i < files.size(); i++) {
       for (int j = 0; j < files[i]->extension_count(); j++) {
         const FieldDescriptor* extension = files[i]->extension(j);
@@ -2456,7 +3532,7 @@
     FindProvidesForFields(options, &printer, extensions, &provided);
     GenerateProvides(options, &printer, &provided);
     GenerateTestOnly(options, &printer);
-    GenerateRequires(options, &printer, files, &provided);
+    GenerateRequiresForLibrary(options, &printer, files, &provided);
 
     GenerateFilesInDepOrder(options, &printer, files);
 
@@ -2469,68 +3545,22 @@
     if (printer.failed()) {
       return false;
     }
-  } else {
-    // Collect all types, and print each type to a separate file. Pull out
-    // free-floating extensions while we make this pass.
-    map< string, vector<const FieldDescriptor*> > extensions_by_namespace;
-
-    // If we're generating code in file-per-type mode, avoid overwriting files
-    // by choosing the last descriptor that writes each filename and permitting
-    // only those to generate code.
-
-    // Current descriptor that will generate each filename, indexed by filename.
-    map<string, const void*> desc_by_filename;
-    // Set of descriptors allowed to generate files.
-    set<const void*> allowed_descs;
-
-    for (int i = 0; i < files.size(); i++) {
-      // Collect all (descriptor, filename) pairs.
-      map<const void*, string> descs_in_file;
-      for (int j = 0; j < files[i]->message_type_count(); j++) {
-        const Descriptor* desc = files[i]->message_type(j);
-        string filename =
-            options.output_dir + "/" + ToFileName(desc->name()) + ".js";
-        descs_in_file[desc] = filename;
-      }
-      for (int j = 0; j < files[i]->enum_type_count(); j++) {
-        const EnumDescriptor* desc = files[i]->enum_type(j);
-        string filename =
-            options.output_dir + "/" + ToFileName(desc->name()) + ".js";
-        descs_in_file[desc] = filename;
-      }
-
-      // For each (descriptor, filename) pair, update the
-      // descriptors-by-filename map, and if a previous descriptor was already
-      // writing the filename, remove it from the allowed-descriptors set.
-      map<const void*, string>::iterator it;
-      for (it = descs_in_file.begin(); it != descs_in_file.end(); ++it) {
-        const void* desc = it->first;
-        const string& filename = it->second;
-        if (desc_by_filename.find(filename) != desc_by_filename.end()) {
-          if (options.error_on_name_conflict) {
-            *error = "Name conflict: file name " + filename +
-                     " would be generated by two descriptors";
-            return false;
-          }
-          allowed_descs.erase(desc_by_filename[filename]);
-        }
-        desc_by_filename[filename] = desc;
-        allowed_descs.insert(desc);
-      }
+  } else if (options.output_mode() == GeneratorOptions::kOneOutputFilePerType) {
+    std::set<const void*> allowed_set;
+    if (!GenerateJspbAllowedSet(options, files, &allowed_set, error)) {
+      return false;
     }
 
-    // Generate code.
     for (int i = 0; i < files.size(); i++) {
       const FileDescriptor* file = files[i];
       for (int j = 0; j < file->message_type_count(); j++) {
         const Descriptor* desc = file->message_type(j);
-        if (allowed_descs.find(desc) == allowed_descs.end()) {
+        if (allowed_set.count(desc) == 0) {
           continue;
         }
 
-        string filename = options.output_dir + "/" +
-            ToFileName(desc->name()) + ".js";
-        google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+        string filename = GetMessageFileName(options, desc);
+        std::unique_ptr<io::ZeroCopyOutputStream> output(
             context->Open(filename));
         GOOGLE_CHECK(output.get());
         io::Printer printer(output.get(), '$');
@@ -2541,7 +3571,7 @@
         FindProvidesForMessage(options, &printer, desc, &provided);
         GenerateProvides(options, &printer, &provided);
         GenerateTestOnly(options, &printer);
-        GenerateRequires(options, &printer, desc, &provided);
+        GenerateRequiresForMessage(options, &printer, desc, &provided);
 
         GenerateClass(options, &printer, desc);
 
@@ -2551,14 +3581,12 @@
       }
       for (int j = 0; j < file->enum_type_count(); j++) {
         const EnumDescriptor* enumdesc = file->enum_type(j);
-        if (allowed_descs.find(enumdesc) == allowed_descs.end()) {
+        if (allowed_set.count(enumdesc) == 0) {
           continue;
         }
 
-        string filename = options.output_dir + "/" +
-            ToFileName(enumdesc->name()) + ".js";
-
-        google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+        string filename = GetEnumFileName(options, enumdesc);
+        std::unique_ptr<io::ZeroCopyOutputStream> output(
             context->Open(filename));
         GOOGLE_CHECK(output.get());
         io::Printer printer(output.get(), '$');
@@ -2576,43 +3604,67 @@
           return false;
         }
       }
-      // Pull out all free-floating extensions and generate files for those too.
-      for (int j = 0; j < file->extension_count(); j++) {
-        const FieldDescriptor* extension = file->extension(j);
-        extensions_by_namespace[GetPath(options, files[i])]
-            .push_back(extension);
-      }
-    }
+      // File-level extensions (message-level extensions are generated under
+      // the enclosing message).
+      if (allowed_set.count(file) == 1) {
+        string filename = GetExtensionFileName(options, file);
 
-    // Generate extensions in separate files.
-    map< string, vector<const FieldDescriptor*> >::iterator it;
-    for (it = extensions_by_namespace.begin();
-         it != extensions_by_namespace.end();
-         ++it) {
-      string filename = options.output_dir + "/" +
-          ToFileName(it->first) + ".js";
+        std::unique_ptr<io::ZeroCopyOutputStream> output(
+            context->Open(filename));
+        GOOGLE_CHECK(output.get());
+        io::Printer printer(output.get(), '$');
 
-      google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
-          context->Open(filename));
-      GOOGLE_CHECK(output.get());
-      io::Printer printer(output.get(), '$');
+        GenerateHeader(options, &printer);
 
-      GenerateHeader(options, &printer);
+        std::set<string> provided;
+        std::vector<const FieldDescriptor*> fields;
 
-      std::set<string> provided;
-      FindProvidesForFields(options, &printer, it->second, &provided);
-      GenerateProvides(options, &printer, &provided);
-      GenerateTestOnly(options, &printer);
-      GenerateRequires(options, &printer, it->second, &provided);
+        for (int j = 0; j < files[i]->extension_count(); j++) {
+          if (ShouldGenerateExtension(files[i]->extension(j))) {
+            fields.push_back(files[i]->extension(j));
+          }
+        }
 
-      for (int j = 0; j < it->second.size(); j++) {
-        if (ShouldGenerateExtension(it->second[j])) {
-          GenerateExtension(options, &printer, it->second[j]);
+        FindProvidesForFields(options, &printer, fields, &provided);
+        GenerateProvides(options, &printer, &provided);
+        GenerateTestOnly(options, &printer);
+        GenerateRequiresForExtensions(options, &printer, fields, &provided);
+
+        for (int j = 0; j < files[i]->extension_count(); j++) {
+          if (ShouldGenerateExtension(files[i]->extension(j))) {
+            GenerateExtension(options, &printer, files[i]->extension(j));
+          }
         }
       }
     }
-  }
+  } else /* options.output_mode() == kOneOutputFilePerInputFile */ {
+    // Generate one output file per input (.proto) file.
 
+    for (int i = 0; i < files.size(); i++) {
+      const google::protobuf::FileDescriptor* file = files[i];
+
+      string filename =
+          options.output_dir + "/" + GetJSFilename(options, file->name());
+      std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+      GOOGLE_CHECK(output.get());
+      GeneratedCodeInfo annotations;
+      io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+          &annotations);
+      io::Printer printer(output.get(), '$',
+                          options.annotate_code ? &annotation_collector : NULL);
+
+
+      GenerateFile(options, &printer, file);
+
+      if (printer.failed()) {
+        return false;
+      }
+
+      if (options.annotate_code) {
+        EmbedCodeAnnotations(annotations, &printer);
+      }
+    }
+  }
   return true;
 }
 
diff --git a/src/google/protobuf/compiler/js/js_generator.h b/src/google/protobuf/compiler/js/js_generator.h
index db2dceb..3cc60e2 100755
--- a/src/google/protobuf/compiler/js/js_generator.h
+++ b/src/google/protobuf/compiler/js/js_generator.h
@@ -28,12 +28,16 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+// Generates JavaScript code for a given .proto file.
+//
 #ifndef GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__
 #define GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__
 
 #include <string>
 #include <set>
 
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/code_generator.h>
 
 namespace google {
@@ -51,37 +55,79 @@
 namespace js {
 
 struct GeneratorOptions {
-  // Add a `goog.requires()` call for each enum type used. If not set, a forward
-  // declaration with `goog.forwardDeclare` is produced instead.
-  bool add_require_for_enums;
-  // Set this as a test-only module via `goog.setTestOnly();`.
-  bool testonly;
   // Output path.
   string output_dir;
   // Namespace prefix.
   string namespace_prefix;
+  // Enable binary-format support?
+  bool binary;
+  // What style of imports should be used.
+  enum ImportStyle {
+    kImportClosure,   // goog.require()
+    kImportCommonJs,  // require()
+    kImportBrowser,   // no import statements
+    kImportEs6,       // import { member } from ''
+  } import_style;
+
+  GeneratorOptions()
+      : output_dir("."),
+        namespace_prefix(""),
+        binary(false),
+        import_style(kImportClosure),
+        add_require_for_enums(false),
+        testonly(false),
+        library(""),
+        error_on_name_conflict(false),
+        extension(".js"),
+        one_output_file_per_input_file(false),
+        annotate_code(false) {}
+
+  bool ParseFromOptions(
+      const std::vector< std::pair< string, string > >& options,
+      string* error);
+
+  // Returns the file name extension to use for generated code.
+  string GetFileNameExtension() const {
+    return import_style == kImportClosure ? extension : "_pb.js";
+  }
+
+  enum OutputMode {
+    // Create an output file for each input .proto file.
+    kOneOutputFilePerInputFile,
+    // Create an output file for each type.
+    kOneOutputFilePerType,
+    // Put everything in a single file named by the library option.
+    kEverythingInOneFile,
+  };
+
+  // Indicates how to output the generated code based on the provided options.
+  OutputMode output_mode() const;
+
+  // The remaining options are only relevant when we are using kImportClosure.
+
+  // Add a `goog.requires()` call for each enum type used. If not set, a
+  // forward declaration with `goog.forwardDeclare` is produced instead.
+  bool add_require_for_enums;
+  // Set this as a test-only module via `goog.setTestOnly();`.
+  bool testonly;
   // Create a library with name <name>_lib.js rather than a separate .js file
   // per type?
   string library;
   // Error if there are two types that would generate the same output file?
   bool error_on_name_conflict;
-  // Enable binary-format support?
-  bool binary;
-
-  GeneratorOptions()
-      : add_require_for_enums(false),
-        testonly(false),
-        output_dir("."),
-        namespace_prefix(""),
-        library(""),
-        error_on_name_conflict(false),
-        binary(false) {}
-
-  bool ParseFromOptions(
-      const vector< pair< string, string > >& options,
-      string* error);
+  // The extension to use for output file names.
+  string extension;
+  // Create a separate output file for each input file?
+  bool one_output_file_per_input_file;
+  // If true, we should build .meta files that contain annotations for
+  // generated code. See GeneratedCodeInfo in descriptor.proto.
+  bool annotate_code;
 };
 
+// CodeGenerator implementation which generates a JavaScript source file and
+// header.  If you create your own protocol compiler binary and you want it to
+// support JavaScript output, you can do so by registering an instance of this
+// CodeGenerator with the CommandLineInterface in your main() function.
 class LIBPROTOC_EXPORT Generator : public CodeGenerator {
  public:
   Generator() {}
@@ -97,7 +143,7 @@
 
   virtual bool HasGenerateAll() const { return true; }
 
-  virtual bool GenerateAll(const vector<const FileDescriptor*>& files,
+  virtual bool GenerateAll(const std::vector<const FileDescriptor*>& files,
                            const string& parameter,
                            GeneratorContext* context,
                            string* error) const;
@@ -109,8 +155,12 @@
   // Generate goog.provides() calls.
   void FindProvides(const GeneratorOptions& options,
                     io::Printer* printer,
-                    const vector<const FileDescriptor*>& file,
+                    const std::vector<const FileDescriptor*>& file,
                     std::set<string>* provided) const;
+  void FindProvidesForFile(const GeneratorOptions& options,
+                           io::Printer* printer,
+                           const FileDescriptor* file,
+                           std::set<string>* provided) const;
   void FindProvidesForMessage(const GeneratorOptions& options,
                               io::Printer* printer,
                               const Descriptor* desc,
@@ -122,7 +172,7 @@
   // For extension fields at file scope.
   void FindProvidesForFields(const GeneratorOptions& options,
                              io::Printer* printer,
-                             const vector<const FieldDescriptor*>& fields,
+                             const std::vector<const FieldDescriptor*>& fields,
                              std::set<string>* provided) const;
   // Print the goog.provides() found by the methods above.
   void GenerateProvides(const GeneratorOptions& options,
@@ -134,26 +184,24 @@
                         io::Printer* printer) const;
 
   // Generate goog.requires() calls.
-  void GenerateRequires(const GeneratorOptions& options,
-                        io::Printer* printer,
-                        const vector<const FileDescriptor*>& file,
-                        std::set<string>* provided) const;
-  void GenerateRequires(const GeneratorOptions& options,
+  void GenerateRequiresForLibrary(
+      const GeneratorOptions& options, io::Printer* printer,
+      const std::vector<const FileDescriptor*>& files,
+      std::set<string>* provided) const;
+  void GenerateRequiresForMessage(const GeneratorOptions& options,
                         io::Printer* printer,
                         const Descriptor* desc,
                         std::set<string>* provided) const;
   // For extension fields at file scope.
-  void GenerateRequires(const GeneratorOptions& options,
-                        io::Printer* printer,
-                        const vector<const FieldDescriptor*>& fields,
-                        std::set<string>* provided) const;
+  void GenerateRequiresForExtensions(
+      const GeneratorOptions& options, io::Printer* printer,
+      const std::vector<const FieldDescriptor*>& fields,
+      std::set<string>* provided) const;
   void GenerateRequiresImpl(const GeneratorOptions& options,
-                            io::Printer* printer,
-                            std::set<string>* required,
+                            io::Printer* printer, std::set<string>* required,
                             std::set<string>* forwards,
-                            std::set<string>* provided,
-                            bool require_jspb,
-                            bool require_extension) const;
+                            std::set<string>* provided, bool require_jspb,
+                            bool require_extension, bool require_map) const;
   void FindRequiresForMessage(const GeneratorOptions& options,
                               const Descriptor* desc,
                               std::set<string>* required,
@@ -168,11 +216,15 @@
                                 std::set<string>* required,
                                 std::set<string>* forwards) const;
 
+  void GenerateFile(const GeneratorOptions& options,
+                    io::Printer* printer,
+                    const FileDescriptor* file) const;
+
   // Generate definitions for all message classes and enums in all files,
   // processing the files in dependence order.
-  void GenerateFilesInDepOrder(const GeneratorOptions& options,
-                               io::Printer* printer,
-                               const vector<const FileDescriptor*>& file) const;
+  void GenerateFilesInDepOrder(
+      const GeneratorOptions& options, io::Printer* printer,
+      const std::vector<const FileDescriptor*>& file) const;
   // Helper for above.
   void GenerateFileAndDeps(const GeneratorOptions& options,
                            io::Printer* printer,
@@ -185,6 +237,11 @@
                                io::Printer* printer,
                                const FileDescriptor* file) const;
 
+  void GenerateFieldValueExpression(io::Printer* printer,
+                                    const char* obj_reference,
+                                    const FieldDescriptor* field,
+                                    bool use_default) const;
+
   // Generate definition for one class.
   void GenerateClass(const GeneratorOptions& options,
                      io::Printer* printer,
@@ -254,6 +311,17 @@
                          io::Printer* printer,
                          const FieldDescriptor* field) const;
 
+  // Generate addFoo() method for repeated primitive fields.
+  void GenerateRepeatedPrimitiveHelperMethods(const GeneratorOptions& options,
+                                              io::Printer* printer,
+                                              const FieldDescriptor* field,
+                                              bool untyped) const;
+
+  // Generate addFoo() method for repeated message fields.
+  void GenerateRepeatedMessageHelperMethods(const GeneratorOptions& options,
+                                            io::Printer* printer,
+                                            const FieldDescriptor* field) const;
+
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator);
 };
 
diff --git a/src/google/protobuf/compiler/js/well_known_types/any.js b/src/google/protobuf/compiler/js/well_known_types/any.js
new file mode 100644
index 0000000..d7ca6e3
--- /dev/null
+++ b/src/google/protobuf/compiler/js/well_known_types/any.js
@@ -0,0 +1,80 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/* This code will be inserted into generated code for
+ * google/protobuf/any.proto. */
+
+/**
+ * Returns the type name contained in this instance, if any.
+ * @return {string|undefined}
+ */
+proto.google.protobuf.Any.prototype.getTypeName = function() {
+  return this.getTypeUrl().split('/').pop();
+};
+
+
+/**
+ * Packs the given message instance into this Any.
+ * @param {!Uint8Array} serialized The serialized data to pack.
+ * @param {string} name The type name of this message object.
+ * @param {string=} opt_typeUrlPrefix the type URL prefix.
+ */
+proto.google.protobuf.Any.prototype.pack = function(serialized, name,
+                                                    opt_typeUrlPrefix) {
+  if (!opt_typeUrlPrefix) {
+    opt_typeUrlPrefix = 'type.googleapis.com/';
+  }
+
+  if (opt_typeUrlPrefix.substr(-1) != '/') {
+    this.setTypeUrl(opt_typeUrlPrefix + '/' + name);
+  } else {
+    this.setTypeUrl(opt_typeUrlPrefix + name);
+  }
+
+  this.setValue(serialized);
+};
+
+
+/**
+ * @template T
+ * Unpacks this Any into the given message object.
+ * @param {function(Uint8Array):T} deserialize Function that will deserialize
+ *     the binary data properly.
+ * @param {string} name The expected type name of this message object.
+ * @return {?T} If the name matched the expected name, returns the deserialized
+ *     object, otherwise returns null.
+ */
+proto.google.protobuf.Any.prototype.unpack = function(deserialize, name) {
+  if (this.getTypeName() == name) {
+    return deserialize(this.getValue_asU8());
+  } else {
+    return null;
+  }
+};
diff --git a/src/google/protobuf/compiler/js/well_known_types/struct.js b/src/google/protobuf/compiler/js/well_known_types/struct.js
new file mode 100644
index 0000000..30e3d02
--- /dev/null
+++ b/src/google/protobuf/compiler/js/well_known_types/struct.js
@@ -0,0 +1,168 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/* This code will be inserted into generated code for
+ * google/protobuf/struct.proto. */
+
+/**
+ * Typedef representing plain JavaScript values that can go into a
+ *     Struct.
+ * @typedef {null|number|string|boolean|Array|Object}
+ */
+proto.google.protobuf.JavaScriptValue;
+
+
+/**
+ * Converts this Value object to a plain JavaScript value.
+ * @return {?proto.google.protobuf.JavaScriptValue} a plain JavaScript
+ *     value representing this Struct.
+ */
+proto.google.protobuf.Value.prototype.toJavaScript = function() {
+  var kindCase = proto.google.protobuf.Value.KindCase;
+  switch (this.getKindCase()) {
+    case kindCase.NULL_VALUE:
+      return null;
+    case kindCase.NUMBER_VALUE:
+      return this.getNumberValue();
+    case kindCase.STRING_VALUE:
+      return this.getStringValue();
+    case kindCase.BOOL_VALUE:
+      return this.getBoolValue();
+    case kindCase.STRUCT_VALUE:
+      return this.getStructValue().toJavaScript();
+    case kindCase.LIST_VALUE:
+      return this.getListValue().toJavaScript();
+    default:
+      throw new Error('Unexpected struct type');
+  }
+};
+
+
+/**
+ * Converts this JavaScript value to a new Value proto.
+ * @param {!proto.google.protobuf.JavaScriptValue} value The value to
+ *     convert.
+ * @return {!proto.google.protobuf.Value} The newly constructed value.
+ */
+proto.google.protobuf.Value.fromJavaScript = function(value) {
+  var ret = new proto.google.protobuf.Value();
+  switch (goog.typeOf(value)) {
+    case 'string':
+      ret.setStringValue(/** @type {string} */ (value));
+      break;
+    case 'number':
+      ret.setNumberValue(/** @type {number} */ (value));
+      break;
+    case 'boolean':
+      ret.setBoolValue(/** @type {boolean} */ (value));
+      break;
+    case 'null':
+      ret.setNullValue(proto.google.protobuf.NullValue.NULL_VALUE);
+      break;
+    case 'array':
+      ret.setListValue(proto.google.protobuf.ListValue.fromJavaScript(
+          /** @type{!Array} */ (value)));
+      break;
+    case 'object':
+      ret.setStructValue(proto.google.protobuf.Struct.fromJavaScript(
+          /** @type{!Object} */ (value)));
+      break;
+    default:
+      throw new Error('Unexpected struct type.');
+  }
+
+  return ret;
+};
+
+
+/**
+ * Converts this ListValue object to a plain JavaScript array.
+ * @return {!Array} a plain JavaScript array representing this List.
+ */
+proto.google.protobuf.ListValue.prototype.toJavaScript = function() {
+  var ret = [];
+  var values = this.getValuesList();
+
+  for (var i = 0; i < values.length; i++) {
+    ret[i] = values[i].toJavaScript();
+  }
+
+  return ret;
+};
+
+
+/**
+ * Constructs a ListValue protobuf from this plain JavaScript array.
+ * @param {!Array} array a plain JavaScript array
+ * @return {proto.google.protobuf.ListValue} a new ListValue object
+ */
+proto.google.protobuf.ListValue.fromJavaScript = function(array) {
+  var ret = new proto.google.protobuf.ListValue();
+
+  for (var i = 0; i < array.length; i++) {
+    ret.addValues(proto.google.protobuf.Value.fromJavaScript(array[i]));
+  }
+
+  return ret;
+};
+
+
+/**
+ * Converts this Struct object to a plain JavaScript object.
+ * @return {!Object<string, !proto.google.protobuf.JavaScriptValue>} a plain
+ *     JavaScript object representing this Struct.
+ */
+proto.google.protobuf.Struct.prototype.toJavaScript = function() {
+  var ret = {};
+
+  this.getFieldsMap().forEach(function(value, key) {
+    ret[key] = value.toJavaScript();
+  });
+
+  return ret;
+};
+
+
+/**
+ * Constructs a Struct protobuf from this plain JavaScript object.
+ * @param {!Object} obj a plain JavaScript object
+ * @return {proto.google.protobuf.Struct} a new Struct object
+ */
+proto.google.protobuf.Struct.fromJavaScript = function(obj) {
+  var ret = new proto.google.protobuf.Struct();
+  var map = ret.getFieldsMap();
+
+  for (var property in obj) {
+    var val = obj[property];
+    map.set(property, proto.google.protobuf.Value.fromJavaScript(val));
+  }
+
+  return ret;
+};
diff --git a/src/google/protobuf/compiler/js/well_known_types/timestamp.js b/src/google/protobuf/compiler/js/well_known_types/timestamp.js
new file mode 100644
index 0000000..b7e43f1
--- /dev/null
+++ b/src/google/protobuf/compiler/js/well_known_types/timestamp.js
@@ -0,0 +1,53 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/* This code will be inserted into generated code for
+ * google/protobuf/timestamp.proto. */
+
+/**
+ * Returns a JavaScript 'Date' object corresponding to this Timestamp.
+ * @return {!Date}
+ */
+proto.google.protobuf.Timestamp.prototype.toDate = function() {
+  var seconds = this.getSeconds();
+  var nanos = this.getNanos();
+
+  return new Date((seconds * 1000) + (nanos / 1000000));
+};
+
+
+/**
+ * Sets the value of this Timestamp object to be the given Date.
+ * @param {!Date} value The value to set.
+ */
+proto.google.protobuf.Timestamp.prototype.fromDate = function(value) {
+  this.setSeconds(Math.floor(value.getTime() / 1000));
+  this.setNanos(value.getMilliseconds() * 1000000);
+};
diff --git a/src/google/protobuf/compiler/js/well_known_types_embed.cc b/src/google/protobuf/compiler/js/well_known_types_embed.cc
new file mode 100644
index 0000000..e5ee551
--- /dev/null
+++ b/src/google/protobuf/compiler/js/well_known_types_embed.cc
@@ -0,0 +1,225 @@
+#include <google/protobuf/compiler/js/well_known_types_embed.h>
+
+struct FileToc well_known_types_js[] = {
+    {"any.js",
+     "/* This code will be inserted into generated code for\n"
+     " * google/protobuf/any.proto. */\n"
+     "\n"
+     "/**\n"
+     " * Returns the type name contained in this instance, if any.\n"
+     " * @return {string|undefined}\n"
+     " */\n"
+     "proto.google.protobuf.Any.prototype.getTypeName = function() {\n"
+     "  return this.getTypeUrl().split('/').pop();\n"
+     "};\n"
+     "\n"
+     "\n"
+     "/**\n"
+     " * Packs the given message instance into this Any.\n"
+     " * @param {!Uint8Array} serialized The serialized data to pack.\n"
+     " * @param {string} name The type name of this message object.\n"
+     " * @param {string=} opt_typeUrlPrefix the type URL prefix.\n"
+     " */\n"
+     "proto.google.protobuf.Any.prototype.pack = function(serialized, name,\n"
+     "                                                    opt_typeUrlPrefix) "
+     "{\n"
+     "  if (!opt_typeUrlPrefix) {\n"
+     "    opt_typeUrlPrefix = 'type.googleapis.com/';\n"
+     "  }\n"
+     "\n"
+     "  if (opt_typeUrlPrefix.substr(-1) != '/') {\n"
+     "    this.setTypeUrl(opt_typeUrlPrefix + '/' + name);\n"
+     "  } else {\n"
+     "    this.setTypeUrl(opt_typeUrlPrefix + name);\n"
+     "  }\n"
+     "\n"
+     "  this.setValue(serialized);\n"
+     "};\n"
+     "\n"
+     "\n"
+     "/**\n"
+     " * @template T\n"
+     " * Unpacks this Any into the given message object.\n"
+     " * @param {function(Uint8Array):T} deserialize Function that will "
+     "deserialize\n"
+     " *     the binary data properly.\n"
+     " * @param {string} name The expected type name of this message object.\n"
+     " * @return {?T} If the name matched the expected name, returns the "
+     "deserialized\n"
+     " *     object, otherwise returns null.\n"
+     " */\n"
+     "proto.google.protobuf.Any.prototype.unpack = function(deserialize, name) "
+     "{\n"
+     "  if (this.getTypeName() == name) {\n"
+     "    return deserialize(this.getValue_asU8());\n"
+     "  } else {\n"
+     "    return null;\n"
+     "  }\n"
+     "};\n"},
+    {"timestamp.js",
+     "/* This code will be inserted into generated code for\n"
+     " * google/protobuf/timestamp.proto. */\n"
+     "\n"
+     "/**\n"
+     " * Returns a JavaScript 'Date' object corresponding to this Timestamp.\n"
+     " * @return {!Date}\n"
+     " */\n"
+     "proto.google.protobuf.Timestamp.prototype.toDate = function() {\n"
+     "  var seconds = this.getSeconds();\n"
+     "  var nanos = this.getNanos();\n"
+     "\n"
+     "  return new Date((seconds * 1000) + (nanos / 1000000));\n"
+     "};\n"
+     "\n"
+     "\n"
+     "/**\n"
+     " * Sets the value of this Timestamp object to be the given Date.\n"
+     " * @param {!Date} value The value to set.\n"
+     " */\n"
+     "proto.google.protobuf.Timestamp.prototype.fromDate = function(value) {\n"
+     "  this.setSeconds(Math.floor(value.getTime() / 1000));\n"
+     "  this.setNanos(value.getMilliseconds() * 1000000);\n"
+     "};\n"},
+    {"struct.js",
+     "/* This code will be inserted into generated code for\n"
+     " * google/protobuf/struct.proto. */\n"
+     "\n"
+     "/**\n"
+     " * Typedef representing plain JavaScript values that can go into a\n"
+     " *     Struct.\n"
+     " * @typedef {null|number|string|boolean|Array|Object}\n"
+     " */\n"
+     "proto.google.protobuf.JavaScriptValue;\n"
+     "\n"
+     "\n"
+     "/**\n"
+     " * Converts this Value object to a plain JavaScript value.\n"
+     " * @return {?proto.google.protobuf.JavaScriptValue} a plain JavaScript\n"
+     " *     value representing this Struct.\n"
+     " */\n"
+     "proto.google.protobuf.Value.prototype.toJavaScript = function() {\n"
+     "  var kindCase = proto.google.protobuf.Value.KindCase;\n"
+     "  switch (this.getKindCase()) {\n"
+     "    case kindCase.NULL_VALUE:\n"
+     "      return null;\n"
+     "    case kindCase.NUMBER_VALUE:\n"
+     "      return this.getNumberValue();\n"
+     "    case kindCase.STRING_VALUE:\n"
+     "      return this.getStringValue();\n"
+     "    case kindCase.BOOL_VALUE:\n"
+     "      return this.getBoolValue();\n"
+     "    case kindCase.STRUCT_VALUE:\n"
+     "      return this.getStructValue().toJavaScript();\n"
+     "    case kindCase.LIST_VALUE:\n"
+     "      return this.getListValue().toJavaScript();\n"
+     "    default:\n"
+     "      throw new Error('Unexpected struct type');\n"
+     "  }\n"
+     "};\n"
+     "\n"
+     "\n"
+     "/**\n"
+     " * Converts this JavaScript value to a new Value proto.\n"
+     " * @param {!proto.google.protobuf.JavaScriptValue} value The value to\n"
+     " *     convert.\n"
+     " * @return {!proto.google.protobuf.Value} The newly constructed value.\n"
+     " */\n"
+     "proto.google.protobuf.Value.fromJavaScript = function(value) {\n"
+     "  var ret = new proto.google.protobuf.Value();\n"
+     "  switch (goog.typeOf(value)) {\n"
+     "    case 'string':\n"
+     "      ret.setStringValue(/** @type {string} */ (value));\n"
+     "      break;\n"
+     "    case 'number':\n"
+     "      ret.setNumberValue(/** @type {number} */ (value));\n"
+     "      break;\n"
+     "    case 'boolean':\n"
+     "      ret.setBoolValue(/** @type {boolean} */ (value));\n"
+     "      break;\n"
+     "    case 'null':\n"
+     "      ret.setNullValue(proto.google.protobuf.NullValue.NULL_VALUE);\n"
+     "      break;\n"
+     "    case 'array':\n"
+     "      ret.setListValue(proto.google.protobuf.ListValue.fromJavaScript(\n"
+     "          /** @type{!Array} */ (value)));\n"
+     "      break;\n"
+     "    case 'object':\n"
+     "      ret.setStructValue(proto.google.protobuf.Struct.fromJavaScript(\n"
+     "          /** @type{!Object} */ (value)));\n"
+     "      break;\n"
+     "    default:\n"
+     "      throw new Error('Unexpected struct type.');\n"
+     "  }\n"
+     "\n"
+     "  return ret;\n"
+     "};\n"
+     "\n"
+     "\n"
+     "/**\n"
+     " * Converts this ListValue object to a plain JavaScript array.\n"
+     " * @return {!Array} a plain JavaScript array representing this List.\n"
+     " */\n"
+     "proto.google.protobuf.ListValue.prototype.toJavaScript = function() {\n"
+     "  var ret = [];\n"
+     "  var values = this.getValuesList();\n"
+     "\n"
+     "  for (var i = 0; i < values.length; i++) {\n"
+     "    ret[i] = values[i].toJavaScript();\n"
+     "  }\n"
+     "\n"
+     "  return ret;\n"
+     "};\n"
+     "\n"
+     "\n"
+     "/**\n"
+     " * Constructs a ListValue protobuf from this plain JavaScript array.\n"
+     " * @param {!Array} array a plain JavaScript array\n"
+     " * @return {proto.google.protobuf.ListValue} a new ListValue object\n"
+     " */\n"
+     "proto.google.protobuf.ListValue.fromJavaScript = function(array) {\n"
+     "  var ret = new proto.google.protobuf.ListValue();\n"
+     "\n"
+     "  for (var i = 0; i < array.length; i++) {\n"
+     "    "
+     "ret.addValues(proto.google.protobuf.Value.fromJavaScript(array[i]));\n"
+     "  }\n"
+     "\n"
+     "  return ret;\n"
+     "};\n"
+     "\n"
+     "\n"
+     "/**\n"
+     " * Converts this Struct object to a plain JavaScript object.\n"
+     " * @return {!Object<string, !proto.google.protobuf.JavaScriptValue>} a "
+     "plain\n"
+     " *     JavaScript object representing this Struct.\n"
+     " */\n"
+     "proto.google.protobuf.Struct.prototype.toJavaScript = function() {\n"
+     "  var ret = {};\n"
+     "\n"
+     "  this.getFieldsMap().forEach(function(value, key) {\n"
+     "    ret[key] = value.toJavaScript();\n"
+     "  });\n"
+     "\n"
+     "  return ret;\n"
+     "};\n"
+     "\n"
+     "\n"
+     "/**\n"
+     " * Constructs a Struct protobuf from this plain JavaScript object.\n"
+     " * @param {!Object} obj a plain JavaScript object\n"
+     " * @return {proto.google.protobuf.Struct} a new Struct object\n"
+     " */\n"
+     "proto.google.protobuf.Struct.fromJavaScript = function(obj) {\n"
+     "  var ret = new proto.google.protobuf.Struct();\n"
+     "  var map = ret.getFieldsMap();\n"
+     "\n"
+     "  for (var property in obj) {\n"
+     "    var val = obj[property];\n"
+     "    map.set(property, proto.google.protobuf.Value.fromJavaScript(val));\n"
+     "  }\n"
+     "\n"
+     "  return ret;\n"
+     "};\n"},
+    {NULL, NULL}  // Terminate the list.
+};
diff --git a/src/google/protobuf/compiler/js/well_known_types_embed.h b/src/google/protobuf/compiler/js/well_known_types_embed.h
new file mode 100644
index 0000000..174c665
--- /dev/null
+++ b/src/google/protobuf/compiler/js/well_known_types_embed.h
@@ -0,0 +1,43 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JS_WELL_KNOWN_TYPES_EMBED_H__
+#define GOOGLE_PROTOBUF_COMPILER_JS_WELL_KNOWN_TYPES_EMBED_H__
+
+#include <stddef.h>
+
+struct FileToc {
+  const char* name;
+  const char* data;
+};
+
+extern struct FileToc well_known_types_js[];
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_JS_WELL_KNOWN_TYPES_EMBED_H__
diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc
index 97df536..1db3544 100644
--- a/src/google/protobuf/compiler/main.cc
+++ b/src/google/protobuf/compiler/main.cc
@@ -32,13 +32,19 @@
 
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/compiler/cpp/cpp_generator.h>
+
+#ifndef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP
 #include <google/protobuf/compiler/python/python_generator.h>
 #include <google/protobuf/compiler/java/java_generator.h>
-#include <google/protobuf/compiler/javanano/javanano_generator.h>
-#include <google/protobuf/compiler/ruby/ruby_generator.h>
+#endif  // ! OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP
+
+#ifndef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP
 #include <google/protobuf/compiler/csharp/csharp_generator.h>
-#include <google/protobuf/compiler/objectivec/objectivec_generator.h>
 #include <google/protobuf/compiler/js/js_generator.h>
+#include <google/protobuf/compiler/objectivec/objectivec_generator.h>
+#include <google/protobuf/compiler/php/php_generator.h>
+#include <google/protobuf/compiler/ruby/ruby_generator.h>
+#endif  // ! OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP
 
 int main(int argc, char* argv[]) {
 
@@ -50,21 +56,24 @@
   cli.RegisterGenerator("--cpp_out", "--cpp_opt", &cpp_generator,
                         "Generate C++ header and source.");
 
+#ifndef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP
   // Proto2 Java
   google::protobuf::compiler::java::JavaGenerator java_generator;
-  cli.RegisterGenerator("--java_out", &java_generator,
+  cli.RegisterGenerator("--java_out", "--java_opt", &java_generator,
                         "Generate Java source file.");
+#endif  // !OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP
 
 
+#ifndef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP
   // Proto2 Python
   google::protobuf::compiler::python::Generator py_generator;
   cli.RegisterGenerator("--python_out", &py_generator,
                         "Generate Python source file.");
 
-  // Java Nano
-  google::protobuf::compiler::javanano::JavaNanoGenerator javanano_generator;
-  cli.RegisterGenerator("--javanano_out", &javanano_generator,
-                        "Generate Java Nano source file.");
+  // PHP
+  google::protobuf::compiler::php::Generator php_generator;
+  cli.RegisterGenerator("--php_out", &php_generator,
+                        "Generate PHP source file.");
 
   // Ruby
   google::protobuf::compiler::ruby::Generator rb_generator;
@@ -78,13 +87,14 @@
 
   // Objective C
   google::protobuf::compiler::objectivec::ObjectiveCGenerator objc_generator;
-  cli.RegisterGenerator("--objc_out", &objc_generator,
+  cli.RegisterGenerator("--objc_out", "--objc_opt", &objc_generator,
                         "Generate Objective C header and source.");
 
   // JavaScript
   google::protobuf::compiler::js::Generator js_generator;
   cli.RegisterGenerator("--js_out", &js_generator,
                         "Generate JavaScript source.");
+#endif  // !OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP
 
   return cli.Run(argc, argv);
 }
diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc
index 121d917..e150f97 100644
--- a/src/google/protobuf/compiler/mock_code_generator.cc
+++ b/src/google/protobuf/compiler/mock_code_generator.cc
@@ -32,20 +32,34 @@
 
 #include <google/protobuf/compiler/mock_code_generator.h>
 
+#include <stdlib.h>
+#include <iostream>
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
+#include <vector>
 
+
+#include <google/protobuf/stubs/strutil.h>
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/compiler/plugin.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/text_format.h>
 #include <google/protobuf/stubs/substitute.h>
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util.h>
+
+#ifdef major
+#undef major
+#endif
+#ifdef minor
+#undef minor
+#endif
 
 namespace google {
 namespace protobuf {
@@ -53,9 +67,9 @@
 
 // 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++) {
+string CommaSeparatedList(const std::vector<const FileDescriptor*>& all_files) {
+  std::vector<string> names;
+  for (size_t i = 0; i < all_files.size(); i++) {
     names.push_back(all_files[i]->name());
   }
   return Join(names, ",");
@@ -86,16 +100,16 @@
       File::GetContents(output_directory + "/" + GetOutputFileName(name, file),
                         &content, true));
 
-  vector<string> lines = Split(content, "\n", true);
+  std::vector<string> lines = Split(content, "\n", true);
 
   while (!lines.empty() && lines.back().empty()) {
     lines.pop_back();
   }
-  for (int i = 0; i < lines.size(); i++) {
+  for (size_t i = 0; i < lines.size(); i++) {
     lines[i] += "\n";
   }
 
-  vector<string> insertion_list;
+  std::vector<string> insertion_list;
   if (!insertions.empty()) {
     SplitStringUsing(insertions, ",", &insertion_list);
   }
@@ -108,7 +122,7 @@
   EXPECT_EQ(kFirstInsertionPoint, lines[1 + insertion_list.size()]);
   EXPECT_EQ(kSecondInsertionPoint, lines[2 + insertion_list.size() * 2]);
 
-  for (int i = 0; i < insertion_list.size(); i++) {
+  for (size_t i = 0; i < insertion_list.size(); i++) {
     EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert",
                                    file, file, first_message_name),
               lines[1 + i]);
@@ -120,11 +134,48 @@
   }
 }
 
+namespace {
+void CheckSingleAnnotation(const string& expected_file,
+                           const string& expected_text,
+                           const string& file_content,
+                           const GeneratedCodeInfo::Annotation& annotation) {
+  EXPECT_EQ(expected_file, annotation.source_file());
+  ASSERT_GE(file_content.size(), annotation.begin());
+  ASSERT_GE(file_content.size(), annotation.end());
+  ASSERT_LE(annotation.begin(), annotation.end());
+  EXPECT_EQ(expected_text.size(), annotation.end() - annotation.begin());
+  EXPECT_EQ(expected_text,
+            file_content.substr(annotation.begin(), expected_text.size()));
+}
+}  // anonymous namespace
+
+void MockCodeGenerator::CheckGeneratedAnnotations(
+    const string& name, const string& file, const string& output_directory) {
+  string file_content;
+  GOOGLE_CHECK_OK(
+      File::GetContents(output_directory + "/" + GetOutputFileName(name, file),
+                        &file_content, true));
+  string meta_content;
+  GOOGLE_CHECK_OK(File::GetContents(
+      output_directory + "/" + GetOutputFileName(name, file) + ".meta",
+      &meta_content, true));
+  GeneratedCodeInfo annotations;
+  GOOGLE_CHECK(TextFormat::ParseFromString(meta_content, &annotations));
+  ASSERT_EQ(3, annotations.annotation_size());
+  CheckSingleAnnotation("first_annotation", "first", file_content,
+                        annotations.annotation(0));
+  CheckSingleAnnotation("second_annotation", "second", file_content,
+                        annotations.annotation(1));
+  CheckSingleAnnotation("third_annotation", "third", file_content,
+                        annotations.annotation(2));
+}
+
 bool MockCodeGenerator::Generate(
     const FileDescriptor* file,
     const string& parameter,
     GeneratorContext* context,
     string* error) const {
+  bool annotate = false;
   for (int i = 0; i < file->message_type_count(); i++) {
     if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) {
       string command = StripPrefixString(file->message_type(i)->name(),
@@ -153,6 +204,17 @@
         std::cerr << "Saw json_name: "
                   << field_descriptor_proto.has_json_name() << std::endl;
         abort();
+      } else if (command == "Annotate") {
+        annotate = true;
+      } else if (command == "ShowVersionNumber") {
+        Version compiler_version;
+        context->GetCompilerVersion(&compiler_version);
+        std::cerr << "Saw compiler_version: "
+                  << compiler_version.major() * 1000000 +
+                     compiler_version.minor() * 1000 +
+                     compiler_version.patch()
+                  << " " << compiler_version.suffix() << std::endl;
+        abort();
       } else {
         GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command;
       }
@@ -160,13 +222,13 @@
   }
 
   if (HasPrefixString(parameter, "insert=")) {
-    vector<string> insert_into;
+    std::vector<string> insert_into;
     SplitStringUsing(StripPrefixString(parameter, "insert="),
                      ",", &insert_into);
 
-    for (int i = 0; i < insert_into.size(); i++) {
+    for (size_t i = 0; i < insert_into.size(); i++) {
       {
-        google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->OpenForInsert(
+        std::unique_ptr<io::ZeroCopyOutputStream> output(context->OpenForInsert(
             GetOutputFileName(insert_into[i], file), kFirstInsertionPointName));
         io::Printer printer(output.get(), '$');
         printer.PrintRaw(GetOutputFileContent(name_, "first_insert",
@@ -178,7 +240,7 @@
       }
 
       {
-        google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+        std::unique_ptr<io::ZeroCopyOutputStream> output(
             context->OpenForInsert(GetOutputFileName(insert_into[i], file),
                                    kSecondInsertionPointName));
         io::Printer printer(output.get(), '$');
@@ -191,19 +253,43 @@
       }
     }
   } else {
-    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+    std::unique_ptr<io::ZeroCopyOutputStream> output(
         context->Open(GetOutputFileName(name_, file)));
 
-    io::Printer printer(output.get(), '$');
-    printer.PrintRaw(GetOutputFileContent(name_, parameter,
-                                          file, context));
+    GeneratedCodeInfo annotations;
+    io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+        &annotations);
+    io::Printer printer(output.get(), '$',
+                        annotate ? &annotation_collector : NULL);
+    printer.PrintRaw(GetOutputFileContent(name_, parameter, file, context));
+    string annotate_suffix = "_annotation";
+    if (annotate) {
+      printer.Print("$p$", "p", "first");
+      printer.Annotate("p", "first" + annotate_suffix);
+    }
     printer.PrintRaw(kFirstInsertionPoint);
+    if (annotate) {
+      printer.Print("$p$", "p", "second");
+      printer.Annotate("p", "second" + annotate_suffix);
+    }
     printer.PrintRaw(kSecondInsertionPoint);
+    if (annotate) {
+      printer.Print("$p$", "p", "third");
+      printer.Annotate("p", "third" + annotate_suffix);
+    }
 
     if (printer.failed()) {
       *error = "MockCodeGenerator detected write error.";
       return false;
     }
+    if (annotate) {
+      std::unique_ptr<io::ZeroCopyOutputStream> meta_output(
+          context->Open(GetOutputFileName(name_, file) + ".meta"));
+      if (!TextFormat::Print(annotations, meta_output.get())) {
+        *error = "MockCodeGenerator couldn't write .meta";
+        return false;
+      }
+    }
   }
 
   return true;
@@ -224,7 +310,7 @@
     const string& parameter,
     const FileDescriptor* file,
     GeneratorContext *context) {
-  vector<const FileDescriptor*> all_files;
+  std::vector<const FileDescriptor*> all_files;
   context->ListParsedFiles(&all_files);
   return GetOutputFileContent(
       generator_name, parameter, file->name(),
diff --git a/src/google/protobuf/compiler/mock_code_generator.h b/src/google/protobuf/compiler/mock_code_generator.h
index 8c8348d..cdd9138 100644
--- a/src/google/protobuf/compiler/mock_code_generator.h
+++ b/src/google/protobuf/compiler/mock_code_generator.h
@@ -34,10 +34,15 @@
 #define GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__
 
 #include <string>
+
 #include <google/protobuf/compiler/code_generator.h>
 
 namespace google {
 namespace protobuf {
+class FileDescriptor;
+}  // namespace protobuf
+
+namespace protobuf {
 namespace compiler {
 
 // A mock CodeGenerator, used by command_line_interface_unittest.  This is in
@@ -63,6 +68,8 @@
 //     printing "Saw message type MockCodeGenerator_HasSourceCodeInfo: FOO." to
 //     stderr, where FOO is "1" if the supplied FileDescriptorProto has source
 //     code info, and "0" otherwise.
+//   MockCodeGenerator_Annotate:  Generate() will add annotations to its output
+//     that can later be verified with CheckGeneratedAnnotations.
 class MockCodeGenerator : public CodeGenerator {
  public:
   MockCodeGenerator(const string& name);
@@ -83,6 +90,12 @@
                               const string& parsed_file_list,
                               const string& output_directory);
 
+  // Checks that the correct text ranges were annotated by the
+  // MockCodeGenerator_Annotate directive.
+  static void CheckGeneratedAnnotations(const string& name,
+                                        const string& file,
+                                        const string& output_directory);
+
   // Get the name of the file which would be written by the given generator.
   static string GetOutputFileName(const string& generator_name,
                                   const FileDescriptor* file);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
index d6f01c6..978e985 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
@@ -62,7 +62,7 @@
   string enum_comments;
   SourceLocation location;
   if (descriptor_->GetSourceLocation(&location)) {
-    enum_comments = BuildCommentsString(location);
+    enum_comments = BuildCommentsString(location, true);
   } else {
     enum_comments = "";
   }
@@ -72,22 +72,27 @@
       "\n",
       "name", name_);
 
-  printer->Print("$comments$typedef GPB_ENUM($name$) {\n",
+  printer->Print("$comments$typedef$deprecated_attribute$ GPB_ENUM($name$) {\n",
                  "comments", enum_comments,
+                 "deprecated_attribute", GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file()),
                  "name", name_);
   printer->Indent();
 
   if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
     // Include the unknown value.
     printer->Print(
+      "/**\n"
+      " * Value used if any message's field encounters a value that is not defined\n"
+      " * by this enum. The message will also have C functions to get/set the rawValue\n"
+      " * of the field.\n"
+      " **/\n"
       "$name$_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,\n",
       "name", name_);
   }
-
   for (int i = 0; i < all_values_.size(); i++) {
     SourceLocation location;
     if (all_values_[i]->GetSourceLocation(&location)) {
-      string comments = BuildCommentsString(location).c_str();
+      string comments = BuildCommentsString(location, true).c_str();
       if (comments.length() > 0) {
         if (i > 0) {
           printer->Print("\n");
@@ -97,8 +102,9 @@
     }
 
     printer->Print(
-        "$name$ = $value$,\n",
+        "$name$$deprecated_attribute$ = $value$,\n",
         "name", EnumValueName(all_values_[i]),
+        "deprecated_attribute", GetOptionalDeprecatedAttribute(all_values_[i]),
         "value", SimpleItoa(all_values_[i]->number()));
   }
   printer->Outdent();
@@ -107,6 +113,10 @@
       "\n"
       "GPBEnumDescriptor *$name$_EnumDescriptor(void);\n"
       "\n"
+      "/**\n"
+      " * Checks to see if the given value is defined by the enum or was not known at\n"
+      " * the time this source was generated.\n"
+      " **/\n"
       "BOOL $name$_IsValidValue(int32_t value);\n"
       "\n",
       "name", name_);
@@ -118,16 +128,6 @@
       "\n",
       "name", name_);
 
-  printer->Print(
-      "GPBEnumDescriptor *$name$_EnumDescriptor(void) {\n"
-      "  static GPBEnumDescriptor *descriptor = NULL;\n"
-      "  if (!descriptor) {\n"
-      "    static GPBMessageEnumValueDescription values[] = {\n",
-      "name", name_);
-  printer->Indent();
-  printer->Indent();
-  printer->Indent();
-
   // Note: For the TextFormat decode info, we can't use the enum value as
   // the key because protocol buffer enums have 'allow_alias', which lets
   // a value be used more than once. Instead, the index into the list of
@@ -135,41 +135,67 @@
   // will be zero.
   TextFormatDecodeData text_format_decode_data;
   int enum_value_description_key = -1;
+  string text_blob;
 
   for (int i = 0; i < all_values_.size(); i++) {
     ++enum_value_description_key;
     string short_name(EnumValueShortName(all_values_[i]));
-    printer->Print("{ .name = \"$short_name$\", .number = $name$ },\n",
-                   "short_name", short_name,
-                   "name", EnumValueName(all_values_[i]));
+    text_blob += short_name + '\0';
     if (UnCamelCaseEnumShortName(short_name) != all_values_[i]->name()) {
       text_format_decode_data.AddString(enum_value_description_key, short_name,
                                         all_values_[i]->name());
     }
   }
-  printer->Outdent();
-  printer->Outdent();
-  printer->Outdent();
+
+  printer->Print(
+      "GPBEnumDescriptor *$name$_EnumDescriptor(void) {\n"
+      "  static _Atomic(GPBEnumDescriptor*) descriptor = nil;\n"
+      "  if (!descriptor) {\n",
+      "name", name_);
+
+  static const int kBytesPerLine = 40;  // allow for escaping
+  printer->Print(
+      "    static const char *valueNames =");
+  for (int i = 0; i < text_blob.size(); i += kBytesPerLine) {
+    printer->Print(
+        "\n        \"$data$\"",
+        "data", EscapeTrigraphs(CEscape(text_blob.substr(i, kBytesPerLine))));
+  }
+  printer->Print(
+      ";\n"
+      "    static const int32_t values[] = {\n");
+  for (int i = 0; i < all_values_.size(); i++) {
+    printer->Print("        $name$,\n",  "name", EnumValueName(all_values_[i]));
+  }
   printer->Print("    };\n");
+
   if (text_format_decode_data.num_entries() == 0) {
     printer->Print(
-        "    descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
-        "                                                   values:values\n"
-        "                                               valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)\n"
-        "                                             enumVerifier:$name$_IsValidValue];\n",
+        "    GPBEnumDescriptor *worker =\n"
+        "        [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
+        "                                       valueNames:valueNames\n"
+        "                                           values:values\n"
+        "                                            count:(uint32_t)(sizeof(values) / sizeof(int32_t))\n"
+        "                                     enumVerifier:$name$_IsValidValue];\n",
         "name", name_);
     } else {
       printer->Print(
         "    static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n"
-        "    descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
-        "                                                   values:values\n"
-        "                                               valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)\n"
-        "                                             enumVerifier:$name$_IsValidValue\n"
-        "                                      extraTextFormatInfo:extraTextFormatInfo];\n",
+        "    GPBEnumDescriptor *worker =\n"
+        "        [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
+        "                                       valueNames:valueNames\n"
+        "                                           values:values\n"
+        "                                            count:(uint32_t)(sizeof(values) / sizeof(int32_t))\n"
+        "                                     enumVerifier:$name$_IsValidValue\n"
+        "                              extraTextFormatInfo:extraTextFormatInfo];\n",
         "name", name_,
         "extraTextFormatInfo", CEscape(text_format_decode_data.Data()));
     }
     printer->Print(
+      "    GPBEnumDescriptor *expected = nil;\n"
+      "    if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) {\n"
+      "      [worker release];\n"
+      "    }\n"
       "  }\n"
       "  return descriptor;\n"
       "}\n\n");
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.h b/src/google/protobuf/compiler/objectivec/objectivec_enum.h
index 0b41cf7..f52e9e6 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.h
@@ -59,8 +59,8 @@
 
  private:
   const EnumDescriptor* descriptor_;
-  vector<const EnumValueDescriptor*> base_values_;
-  vector<const EnumValueDescriptor*> all_values_;
+  std::vector<const EnumValueDescriptor*> base_values_;
+  std::vector<const EnumValueDescriptor*> all_values_;
   const string name_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
index 30a13dd..8899a13 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
@@ -44,8 +44,9 @@
 namespace objectivec {
 
 namespace {
+
 void SetEnumVariables(const FieldDescriptor* descriptor,
-                      map<string, string>* variables) {
+                      std::map<string, string>* variables) {
   string type = EnumName(descriptor->enum_type());
   (*variables)["storage_type"] = type;
   // For non repeated fields, if it was defined in a different file, the
@@ -58,25 +59,22 @@
   (*variables)["enum_verifier"] = type + "_IsValidValue";
   (*variables)["enum_desc_func"] = type + "_EnumDescriptor";
 
+  (*variables)["dataTypeSpecific_name"] = "enumDescFunc";
+  (*variables)["dataTypeSpecific_value"] = (*variables)["enum_desc_func"];
+
   const Descriptor* msg_descriptor = descriptor->containing_type();
   (*variables)["owning_message_class"] = ClassName(msg_descriptor);
 }
 }  // namespace
 
-EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor)
-    : SingleFieldGenerator(descriptor) {
+EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
+                                       const Options& options)
+    : SingleFieldGenerator(descriptor, options) {
   SetEnumVariables(descriptor, &variables_);
 }
 
 EnumFieldGenerator::~EnumFieldGenerator() {}
 
-void EnumFieldGenerator::GenerateFieldDescriptionTypeSpecific(
-    io::Printer* printer) const {
-  printer->Print(
-      variables_,
-      "  .dataTypeSpecific.enumDescFunc = $enum_desc_func$,\n");
-}
-
 void EnumFieldGenerator::GenerateCFunctionDeclarations(
     io::Printer* printer) const {
   if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
@@ -85,7 +83,16 @@
 
   printer->Print(
       variables_,
+      "/**\n"
+      " * Fetches the raw value of a @c $owning_message_class$'s @c $name$ property, even\n"
+      " * if the value was not defined by the enum at the time the code was generated.\n"
+      " **/\n"
       "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message);\n"
+      "/**\n"
+      " * Sets the raw value of an @c $owning_message_class$'s @c $name$ property, allowing\n"
+      " * it to be set to a value that was not defined by the enum at the time the code\n"
+      " * was generated.\n"
+      " **/\n"
       "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value);\n"
       "\n");
 }
@@ -111,7 +118,8 @@
 }
 
 void EnumFieldGenerator::DetermineForwardDeclarations(
-    set<string>* fwd_decls) const {
+    std::set<string>* fwd_decls) const {
+  SingleFieldGenerator::DetermineForwardDeclarations(fwd_decls);
   // If it is an enum defined in a different file, then we'll need a forward
   // declaration for it.  When it is in our file, all the enums are output
   // before the message, so it will be declared before it is needed.
@@ -123,19 +131,18 @@
 }
 
 RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
-    const FieldDescriptor* descriptor)
-    : RepeatedFieldGenerator(descriptor) {
+    const FieldDescriptor* descriptor, const Options& options)
+    : RepeatedFieldGenerator(descriptor, options) {
   SetEnumVariables(descriptor, &variables_);
   variables_["array_storage_type"] = "GPBEnumArray";
 }
 
 RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
 
-void RepeatedEnumFieldGenerator::GenerateFieldDescriptionTypeSpecific(
-    io::Printer* printer) const {
-  printer->Print(
-      variables_,
-      "  .dataTypeSpecific.enumDescFunc = $enum_desc_func$,\n");
+void RepeatedEnumFieldGenerator::FinishInitialization(void) {
+  RepeatedFieldGenerator::FinishInitialization();
+  variables_["array_comment"] =
+      "// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n";
 }
 
 }  // namespace objectivec
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
index b629eae..ae56c06 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
@@ -41,16 +41,16 @@
 namespace objectivec {
 
 class EnumFieldGenerator : public SingleFieldGenerator {
-  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
 
  public:
-  virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
   virtual void GenerateCFunctionDeclarations(io::Printer* printer) const;
   virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
-  virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+  virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
 
  protected:
-  explicit EnumFieldGenerator(const FieldDescriptor* descriptor);
+  EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
   virtual ~EnumFieldGenerator();
 
  private:
@@ -58,13 +58,15 @@
 };
 
 class RepeatedEnumFieldGenerator : public RepeatedFieldGenerator {
-  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
 
  public:
-  virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
+  virtual void FinishInitialization();
 
  protected:
-  RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor);
+  RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+                             const Options& options);
   virtual ~RepeatedEnumFieldGenerator();
 
  private:
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
index 4e34839..b788d0a 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
@@ -49,9 +49,9 @@
   if (descriptor->is_map()) {
     // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
     // error cases, so it seems to be ok to use as a back door for errors.
-    cerr << "error: Extension is a map<>!"
-         << " That used to be blocked by the compiler." << endl;
-    cerr.flush();
+    std::cerr << "error: Extension is a map<>!"
+         << " That used to be blocked by the compiler." << std::endl;
+    std::cerr.flush();
     abort();
   }
 }
@@ -59,22 +59,25 @@
 ExtensionGenerator::~ExtensionGenerator() {}
 
 void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) {
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["method_name"] = method_name_;
   SourceLocation location;
   if (descriptor_->GetSourceLocation(&location)) {
-    vars["comments"] = BuildCommentsString(location);
+    vars["comments"] = BuildCommentsString(location, true);
   } else {
     vars["comments"] = "";
   }
+  // Unlike normal message fields, check if the file for the extension was
+  // deprecated.
+  vars["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file());
   printer->Print(vars,
                  "$comments$"
-                 "+ (GPBExtensionDescriptor *)$method_name$;\n");
+                 "+ (GPBExtensionDescriptor *)$method_name$$deprecated_attribute$;\n");
 }
 
 void ExtensionGenerator::GenerateStaticVariablesInitialization(
     io::Printer* printer) {
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["root_class_and_method_name"] = root_class_and_method_name_;
   vars["extended_type"] = ClassName(descriptor_->containing_type());
   vars["number"] = SimpleItoa(descriptor_->number());
@@ -85,7 +88,7 @@
   if (descriptor_->containing_type()->options().message_set_wire_format())
     options.push_back("GPBExtensionSetWireFormat");
 
-  vars["options"] = BuildFlagsString(options);
+  vars["options"] = BuildFlagsString(FLAGTYPE_EXTENSION, options);
 
   ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
   string singular_type;
@@ -114,14 +117,14 @@
 
   printer->Print(vars,
                  "{\n"
-                 "  .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n"
-                 "  .dataType = $extension_type$,\n"
-                 "  .extendedClass = GPBStringifySymbol($extended_type$),\n"
-                 "  .fieldNumber = $number$,\n"
                  "  .defaultValue.$default_name$ = $default$,\n"
+                 "  .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n"
+                 "  .extendedClass = GPBStringifySymbol($extended_type$),\n"
                  "  .messageOrGroupClassName = $type$,\n"
-                 "  .options = $options$,\n"
                  "  .enumDescriptorFunc = $enum_desc_func_name$,\n"
+                 "  .fieldNumber = $number$,\n"
+                 "  .dataType = $extension_type$,\n"
+                 "  .options = $options$,\n"
                  "},\n");
 }
 
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
index cf5d8cf..f74599b 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
@@ -28,6 +28,8 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#include <iostream>
+
 #include <google/protobuf/compiler/objectivec/objectivec_field.h>
 #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
 #include <google/protobuf/compiler/objectivec/objectivec_enum_field.h>
@@ -45,8 +47,9 @@
 namespace objectivec {
 
 namespace {
+
 void SetCommonFieldVariables(const FieldDescriptor* descriptor,
-                             map<string, string>* variables) {
+                             std::map<string, string>* variables) {
   string camel_case_name = FieldName(descriptor);
   string raw_field_name;
   if (descriptor->type() == FieldDescriptor::TYPE_GROUP) {
@@ -61,7 +64,7 @@
 
   SourceLocation location;
   if (descriptor->GetSourceLocation(&location)) {
-    (*variables)["comments"] = BuildCommentsString(location);
+    (*variables)["comments"] = BuildCommentsString(location, true);
   } else {
     (*variables)["comments"] = "\n";
   }
@@ -74,8 +77,8 @@
   (*variables)["field_number_name"] =
       classname + "_FieldNumber_" + capitalized_name;
   (*variables)["field_number"] = SimpleItoa(descriptor->number());
-  (*variables)["has_index"] = SimpleItoa(descriptor->index());
   (*variables)["field_type"] = GetCapitalizedType(descriptor);
+  (*variables)["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor);
   std::vector<string> field_flags;
   if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated");
   if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired");
@@ -90,7 +93,7 @@
     field_flags.push_back("GPBFieldHasEnumDescriptor");
   }
 
-  (*variables)["fieldflags"] = BuildFlagsString(field_flags);
+  (*variables)["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags);
 
   (*variables)["default"] = DefaultValue(descriptor);
   (*variables)["default_name"] = GPBGenericValueFieldName(descriptor);
@@ -98,18 +101,9 @@
   (*variables)["dataTypeSpecific_name"] = "className";
   (*variables)["dataTypeSpecific_value"] = "NULL";
 
-  string field_options = descriptor->options().SerializeAsString();
-  // Must convert to a standard byte order for packing length into
-  // a cstring.
-  uint32 length = ghtonl(field_options.length());
-  if (length > 0) {
-    string bytes((const char*)&length, sizeof(length));
-    bytes.append(field_options);
-    string options_str = "\"" + CEscape(bytes) + "\"";
-    (*variables)["fieldoptions"] = "\"" + CEscape(bytes) + "\"";
-  } else {
-    (*variables)["fieldoptions"] = "";
-  }
+  (*variables)["storage_offset_value"] =
+      "(uint32_t)offsetof(" + classname + "__storage_, " + camel_case_name + ")";
+  (*variables)["storage_offset_comment"] = "";
 
   // Clear some common things so they can be set just when needed.
   (*variables)["storage_attribute"] = "";
@@ -117,39 +111,40 @@
 
 }  // namespace
 
-FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) {
+FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                     const Options& options) {
   FieldGenerator* result = NULL;
   if (field->is_repeated()) {
     switch (GetObjectiveCType(field)) {
       case OBJECTIVECTYPE_MESSAGE: {
         if (field->is_map()) {
-          result = new MapFieldGenerator(field);
+          result = new MapFieldGenerator(field, options);
         } else {
-          result = new RepeatedMessageFieldGenerator(field);
+          result = new RepeatedMessageFieldGenerator(field, options);
         }
         break;
       }
       case OBJECTIVECTYPE_ENUM:
-        result = new RepeatedEnumFieldGenerator(field);
+        result = new RepeatedEnumFieldGenerator(field, options);
         break;
       default:
-        result = new RepeatedPrimitiveFieldGenerator(field);
+        result = new RepeatedPrimitiveFieldGenerator(field, options);
         break;
     }
   } else {
     switch (GetObjectiveCType(field)) {
       case OBJECTIVECTYPE_MESSAGE: {
-        result = new MessageFieldGenerator(field);
+        result = new MessageFieldGenerator(field, options);
         break;
       }
       case OBJECTIVECTYPE_ENUM:
-        result = new EnumFieldGenerator(field);
+        result = new EnumFieldGenerator(field, options);
         break;
       default:
         if (IsReferenceType(field)) {
-          result = new PrimitiveObjFieldGenerator(field);
+          result = new PrimitiveObjFieldGenerator(field, options);
         } else {
-          result = new PrimitiveFieldGenerator(field);
+          result = new PrimitiveFieldGenerator(field, options);
         }
         break;
     }
@@ -158,8 +153,8 @@
   return result;
 }
 
-
-FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor)
+FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor,
+                               const Options& options)
     : descriptor_(descriptor) {
   SetCommonFieldVariables(descriptor, &variables_);
 }
@@ -183,57 +178,59 @@
 }
 
 void FieldGenerator::DetermineForwardDeclarations(
-    set<string>* fwd_decls) const {
+    std::set<string>* fwd_decls) const {
   // Nothing
 }
 
 void FieldGenerator::GenerateFieldDescription(
-    io::Printer* printer) const {
-  printer->Print(
-      variables_,
-      "{\n"
-      "  .name = \"$name$\",\n"
-      "  .number = $field_number_name$,\n"
-      "  .hasIndex = $has_index$,\n"
-      "  .flags = $fieldflags$,\n"
-      "  .dataType = GPBDataType$field_type$,\n"
-      "  .offset = offsetof($classname$__storage_, $name$),\n"
-      "  .defaultValue.$default_name$ = $default$,\n");
-
-  // TODO(thomasvl): It might be useful to add a CPP wrapper to support
-  // compiling away the EnumDescriptors.  To do that, we'd need a #if here
-  // to control setting the descriptor vs. the validator, and above in
-  // SetCommonFieldVariables() we'd want to wrap how we add
-  // GPBFieldHasDefaultValue to the flags.
-
-  // "  .dataTypeSpecific.value* = [something],"
-  GenerateFieldDescriptionTypeSpecific(printer);
-
-  const string& field_options(variables_.find("fieldoptions")->second);
-  if (field_options.empty()) {
-    printer->Print("  .fieldOptions = NULL,\n");
-  } else {
-    // Can't use PrintRaw() here to get the #if/#else/#endif lines completely
-    // outdented because the need for indent captured on the previous
-    // printing of a \n and there is no way to get the current indent level
-    // to call the right number of Outdent()/Indents() to maintain state.
+    io::Printer* printer, bool include_default) const {
+  // Printed in the same order as the structure decl.
+  if (include_default) {
     printer->Print(
         variables_,
-        "#if GPBOBJC_INCLUDE_FIELD_OPTIONS\n"
-        "  .fieldOptions = $fieldoptions$,\n"
-        "#else\n"
-        "  .fieldOptions = NULL,\n"
-        "#endif  // GPBOBJC_INCLUDE_FIELD_OPTIONS\n");
+        "{\n"
+        "  .defaultValue.$default_name$ = $default$,\n"
+        "  .core.name = \"$name$\",\n"
+        "  .core.dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"
+        "  .core.number = $field_number_name$,\n"
+        "  .core.hasIndex = $has_index$,\n"
+        "  .core.offset = $storage_offset_value$,$storage_offset_comment$\n"
+        "  .core.flags = $fieldflags$,\n"
+        "  .core.dataType = GPBDataType$field_type$,\n"
+        "},\n");
+  } else {
+    printer->Print(
+        variables_,
+        "{\n"
+        "  .name = \"$name$\",\n"
+        "  .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"
+        "  .number = $field_number_name$,\n"
+        "  .hasIndex = $has_index$,\n"
+        "  .offset = $storage_offset_value$,$storage_offset_comment$\n"
+        "  .flags = $fieldflags$,\n"
+        "  .dataType = GPBDataType$field_type$,\n"
+        "},\n");
   }
-
-  printer->Print("},\n");
 }
 
-void FieldGenerator::GenerateFieldDescriptionTypeSpecific(
-    io::Printer* printer) const {
-  printer->Print(
-      variables_,
-      "  .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n");
+void FieldGenerator::SetRuntimeHasBit(int has_index) {
+  variables_["has_index"] = SimpleItoa(has_index);
+}
+
+void FieldGenerator::SetNoHasBit(void) {
+  variables_["has_index"] = "GPBNoHasBit";
+}
+
+int FieldGenerator::ExtraRuntimeHasBitsNeeded(void) const {
+  return 0;
+}
+
+void FieldGenerator::SetExtraRuntimeHasBitsBase(int index_base) {
+  // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
+  // error cases, so it seems to be ok to use as a back door for errors.
+  std::cerr << "Error: should have overridden SetExtraRuntimeHasBitsBase()." << std::endl;
+  std::cerr.flush();
+  abort();
 }
 
 void FieldGenerator::SetOneofIndexBase(int index_base) {
@@ -252,9 +249,9 @@
   }
 }
 
-SingleFieldGenerator::SingleFieldGenerator(
-    const FieldDescriptor* descriptor)
-    : FieldGenerator(descriptor) {
+SingleFieldGenerator::SingleFieldGenerator(const FieldDescriptor* descriptor,
+                                           const Options& options)
+    : FieldGenerator(descriptor, options) {
   // Nothing
 }
 
@@ -268,15 +265,15 @@
 void SingleFieldGenerator::GeneratePropertyDeclaration(
     io::Printer* printer) const {
   printer->Print(variables_, "$comments$");
+  printer->Print(
+      variables_,
+      "@property(nonatomic, readwrite) $property_type$ $name$$deprecated_attribute$;\n"
+      "\n");
   if (WantsHasProperty()) {
     printer->Print(
         variables_,
-        "@property(nonatomic, readwrite) BOOL has$capitalized_name$;\n");
+        "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
   }
-  printer->Print(
-      variables_,
-      "@property(nonatomic, readwrite) $property_type$ $name$;\n"
-      "\n");
 }
 
 void SingleFieldGenerator::GeneratePropertyImplementation(
@@ -300,9 +297,17 @@
   return false;
 }
 
-ObjCObjFieldGenerator::ObjCObjFieldGenerator(
-    const FieldDescriptor* descriptor)
-    : SingleFieldGenerator(descriptor) {
+bool SingleFieldGenerator::RuntimeUsesHasBit(void) const {
+  if (descriptor_->containing_oneof() != NULL) {
+    // The oneof tracks what is set instead.
+    return false;
+  }
+  return true;
+}
+
+ObjCObjFieldGenerator::ObjCObjFieldGenerator(const FieldDescriptor* descriptor,
+                                             const Options& options)
+    : SingleFieldGenerator(descriptor, options) {
   variables_["property_storage_attribute"] = "strong";
   if (IsRetainedName(variables_["name"])) {
     variables_["storage_attribute"] = " NS_RETURNS_NOT_RETAINED";
@@ -324,36 +329,38 @@
   // conventions (init*, new*, etc.)
 
   printer->Print(variables_, "$comments$");
+  printer->Print(
+      variables_,
+      "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n");
   if (WantsHasProperty()) {
     printer->Print(
         variables_,
-        "@property(nonatomic, readwrite) BOOL has$capitalized_name$;\n");
+        "/** Test to see if @c $name$ has been set. */\n"
+        "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
   }
-  printer->Print(
-      variables_,
-      "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$;\n");
   if (IsInitName(variables_.find("name")->second)) {
     // If property name starts with init we need to annotate it to get past ARC.
     // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
     printer->Print(variables_,
-                   "- ($property_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n");
+                   "- ($property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
   }
   printer->Print("\n");
 }
 
 RepeatedFieldGenerator::RepeatedFieldGenerator(
-    const FieldDescriptor* descriptor)
-    : ObjCObjFieldGenerator(descriptor) {
-  // Repeated fields don't use the has index.
-  variables_["has_index"] = "GPBNoHasBit";
+    const FieldDescriptor* descriptor, const Options& options)
+    : ObjCObjFieldGenerator(descriptor, options) {
+  // Default to no comment and let the cases needing it fill it in.
+  variables_["array_comment"] = "";
 }
 
 RepeatedFieldGenerator::~RepeatedFieldGenerator() {}
 
 void RepeatedFieldGenerator::FinishInitialization(void) {
   FieldGenerator::FinishInitialization();
-  variables_["array_comment"] =
-      "// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n";
+  if (variables_.find("array_property_type") == variables_.end()) {
+    variables_["array_property_type"] = variable("array_storage_type");
+  }
 }
 
 void RepeatedFieldGenerator::GenerateFieldStorageDeclaration(
@@ -379,13 +386,14 @@
       variables_,
       "$comments$"
       "$array_comment$"
-      "@property(nonatomic, readwrite, strong, null_resettable) $array_storage_type$ *$name$$storage_attribute$;\n"
-      "@property(nonatomic, readonly) NSUInteger $name$_Count;\n");
+      "@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n"
+      "/** The number of items in @c $name$ without causing the array to be created. */\n"
+      "@property(nonatomic, readonly) NSUInteger $name$_Count$deprecated_attribute$;\n");
   if (IsInitName(variables_.find("name")->second)) {
     // If property name starts with init we need to annotate it to get past ARC.
     // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
     printer->Print(variables_,
-                   "- ($array_storage_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n");
+                   "- ($array_property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
   }
   printer->Print("\n");
 }
@@ -395,18 +403,23 @@
   return false;
 }
 
-FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
+bool RepeatedFieldGenerator::RuntimeUsesHasBit(void) const {
+  return false;  // The array having anything is what is used.
+}
+
+FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
+                                     const Options& options)
     : descriptor_(descriptor),
-      field_generators_(
-          new scoped_ptr<FieldGenerator>[descriptor->field_count()]),
-      extension_generators_(
-          new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
+      field_generators_(descriptor->field_count()),
+      extension_generators_(descriptor->extension_count()) {
   // Construct all the FieldGenerators.
   for (int i = 0; i < descriptor->field_count(); i++) {
-    field_generators_[i].reset(FieldGenerator::Make(descriptor->field(i)));
+    field_generators_[i].reset(
+        FieldGenerator::Make(descriptor->field(i), options));
   }
   for (int i = 0; i < descriptor->extension_count(); i++) {
-    extension_generators_[i].reset(FieldGenerator::Make(descriptor->extension(i)));
+    extension_generators_[i].reset(
+        FieldGenerator::Make(descriptor->extension(i), options));
   }
 }
 
@@ -422,12 +435,40 @@
   return *extension_generators_[index];
 }
 
+int FieldGeneratorMap::CalculateHasBits(void) {
+  int total_bits = 0;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (field_generators_[i]->RuntimeUsesHasBit()) {
+      field_generators_[i]->SetRuntimeHasBit(total_bits);
+      ++total_bits;
+    } else {
+      field_generators_[i]->SetNoHasBit();
+    }
+    int extra_bits = field_generators_[i]->ExtraRuntimeHasBitsNeeded();
+    if (extra_bits) {
+      field_generators_[i]->SetExtraRuntimeHasBitsBase(total_bits);
+      total_bits += extra_bits;
+    }
+  }
+  return total_bits;
+}
+
 void FieldGeneratorMap::SetOneofIndexBase(int index_base) {
   for (int i = 0; i < descriptor_->field_count(); i++) {
     field_generators_[i]->SetOneofIndexBase(index_base);
   }
 }
 
+bool FieldGeneratorMap::DoesAnyFieldHaveNonZeroDefault(void) const {
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (HasNonZeroDefaultValue(descriptor_->field(i))) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 }  // namespace objectivec
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.h b/src/google/protobuf/compiler/objectivec/objectivec_field.h
index 130a52d..216034d 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.h
@@ -49,24 +49,37 @@
 
 class FieldGenerator {
  public:
-  static FieldGenerator* Make(const FieldDescriptor* field);
+  static FieldGenerator* Make(const FieldDescriptor* field,
+                              const Options& options);
 
   virtual ~FieldGenerator();
 
+  // Exposed for subclasses to fill in.
   virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const = 0;
   virtual void GeneratePropertyDeclaration(io::Printer* printer) const = 0;
-
   virtual void GeneratePropertyImplementation(io::Printer* printer) const = 0;
 
-  virtual void GenerateFieldDescription(io::Printer* printer) const;
-  virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
-  virtual void GenerateFieldNumberConstant(io::Printer* printer) const;
+  // Called by GenerateFieldDescription, exposed for classes that need custom
+  // generation.
 
+  // Exposed for subclasses to extend, base does nothing.
   virtual void GenerateCFunctionDeclarations(io::Printer* printer) const;
   virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
 
-  virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+  // Exposed for subclasses, should always call it on the parent class also.
+  virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
 
+  // Used during generation, not intended to be extended by subclasses.
+  void GenerateFieldDescription(
+      io::Printer* printer, bool include_default) const;
+  void GenerateFieldNumberConstant(io::Printer* printer) const;
+
+  // Exposed to get and set the has bits information.
+  virtual bool RuntimeUsesHasBit(void) const = 0;
+  void SetRuntimeHasBit(int has_index);
+  void SetNoHasBit(void);
+  virtual int ExtraRuntimeHasBitsNeeded(void) const;
+  virtual void SetExtraRuntimeHasBitsBase(int index_base);
   void SetOneofIndexBase(int index_base);
 
   string variable(const char* key) const {
@@ -81,13 +94,13 @@
   string raw_field_name() const { return variable("raw_field_name"); }
 
  protected:
-  explicit FieldGenerator(const FieldDescriptor* descriptor);
+  FieldGenerator(const FieldDescriptor* descriptor, const Options& options);
 
   virtual void FinishInitialization(void);
   virtual bool WantsHasProperty(void) const = 0;
 
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
@@ -102,8 +115,11 @@
 
   virtual void GeneratePropertyImplementation(io::Printer* printer) const;
 
+  virtual bool RuntimeUsesHasBit(void) const;
+
  protected:
-  explicit SingleFieldGenerator(const FieldDescriptor* descriptor);
+  SingleFieldGenerator(const FieldDescriptor* descriptor,
+                       const Options& options);
   virtual bool WantsHasProperty(void) const;
 
  private:
@@ -119,7 +135,8 @@
   virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
 
  protected:
-  explicit ObjCObjFieldGenerator(const FieldDescriptor* descriptor);
+  ObjCObjFieldGenerator(const FieldDescriptor* descriptor,
+                        const Options& options);
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjCObjFieldGenerator);
@@ -134,8 +151,11 @@
 
   virtual void GeneratePropertyImplementation(io::Printer* printer) const;
 
+  virtual bool RuntimeUsesHasBit(void) const;
+
  protected:
-  explicit RepeatedFieldGenerator(const FieldDescriptor* descriptor);
+  RepeatedFieldGenerator(const FieldDescriptor* descriptor,
+                         const Options& options);
   virtual void FinishInitialization(void);
   virtual bool WantsHasProperty(void) const;
 
@@ -146,18 +166,24 @@
 // Convenience class which constructs FieldGenerators for a Descriptor.
 class FieldGeneratorMap {
  public:
-  explicit FieldGeneratorMap(const Descriptor* descriptor);
+  FieldGeneratorMap(const Descriptor* descriptor, const Options& options);
   ~FieldGeneratorMap();
 
   const FieldGenerator& get(const FieldDescriptor* field) const;
   const FieldGenerator& get_extension(int index) const;
 
+  // Assigns the has bits and returns the number of bits needed.
+  int CalculateHasBits(void);
+
   void SetOneofIndexBase(int index_base);
 
+  // Check if any field of this message has a non zero default.
+  bool DoesAnyFieldHaveNonZeroDefault(void) const;
+
  private:
   const Descriptor* descriptor_;
-  scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
-  scoped_array<scoped_ptr<FieldGenerator> > extension_generators_;
+  std::vector<std::unique_ptr<FieldGenerator>> field_generators_;
+  std::vector<std::unique_ptr<FieldGenerator>> extension_generators_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
 };
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
index 228c66f..f0d9b4d 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
@@ -37,30 +37,166 @@
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/stubs/stl_util.h>
 #include <google/protobuf/stubs/strutil.h>
+#include <algorithm> // std::find()
+#include <iostream>
 #include <sstream>
 
+// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
+// error cases, so it seems to be ok to use as a back door for errors.
+
 namespace google {
 namespace protobuf {
-
-// This is also found in GPBBootstrap.h, and needs to be kept in sync.  It
-// is the version check done to ensure generated code works with the current
-// runtime being used.
-const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30000;
-
 namespace compiler {
 namespace objectivec {
 
-FileGenerator::FileGenerator(const FileDescriptor *file)
+namespace {
+
+// This is also found in GPBBootstrap.h, and needs to be kept in sync.
+const int32 GOOGLE_PROTOBUF_OBJC_VERSION = 30002;
+
+const char* kHeaderExtension = ".pbobjc.h";
+
+// Checks if a message contains any enums definitions (on the message or
+// a nested message under it).
+bool MessageContainsEnums(const Descriptor* message) {
+  if (message->enum_type_count() > 0) {
+    return true;
+  }
+  for (int i = 0; i < message->nested_type_count(); i++) {
+    if (MessageContainsEnums(message->nested_type(i))) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Checks if a message contains any extension definitions (on the message or
+// a nested message under it).
+bool MessageContainsExtensions(const Descriptor* message) {
+  if (message->extension_count() > 0) {
+    return true;
+  }
+  for (int i = 0; i < message->nested_type_count(); i++) {
+    if (MessageContainsExtensions(message->nested_type(i))) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Checks if the file contains any enum definitions (at the root or
+// nested under a message).
+bool FileContainsEnums(const FileDescriptor* file) {
+  if (file->enum_type_count() > 0) {
+    return true;
+  }
+  for (int i = 0; i < file->message_type_count(); i++) {
+    if (MessageContainsEnums(file->message_type(i))) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Checks if the file contains any extensions definitions (at the root or
+// nested under a message).
+bool FileContainsExtensions(const FileDescriptor* file) {
+  if (file->extension_count() > 0) {
+    return true;
+  }
+  for (int i = 0; i < file->message_type_count(); i++) {
+    if (MessageContainsExtensions(file->message_type(i))) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Helper for CollectMinimalFileDepsContainingExtensionsWorker that marks all
+// deps as visited and prunes them from the needed files list.
+void PruneFileAndDepsMarkingAsVisited(
+    const FileDescriptor* file,
+    std::vector<const FileDescriptor*>* files,
+    std::set<const FileDescriptor*>* files_visited) {
+  std::vector<const FileDescriptor*>::iterator iter =
+      std::find(files->begin(), files->end(), file);
+  if (iter != files->end()) {
+    files->erase(iter);
+  }
+  files_visited->insert(file);
+  for (int i = 0; i < file->dependency_count(); i++) {
+    PruneFileAndDepsMarkingAsVisited(file->dependency(i), files, files_visited);
+  }
+}
+
+// Helper for CollectMinimalFileDepsContainingExtensions.
+void CollectMinimalFileDepsContainingExtensionsWorker(
+    const FileDescriptor* file,
+    std::vector<const FileDescriptor*>* files,
+    std::set<const FileDescriptor*>* files_visited) {
+  if (files_visited->find(file) != files_visited->end()) {
+    return;
+  }
+  files_visited->insert(file);
+
+  if (FileContainsExtensions(file)) {
+    files->push_back(file);
+    for (int i = 0; i < file->dependency_count(); i++) {
+      const FileDescriptor* dep = file->dependency(i);
+      PruneFileAndDepsMarkingAsVisited(dep, files, files_visited);
+    }
+  } else {
+    for (int i = 0; i < file->dependency_count(); i++) {
+      const FileDescriptor* dep = file->dependency(i);
+      CollectMinimalFileDepsContainingExtensionsWorker(dep, files,
+                                                       files_visited);
+    }
+  }
+}
+
+// Collect the deps of the given file that contain extensions. This can be used to
+// create the chain of roots that need to be wired together.
+//
+// NOTE: If any changes are made to this and the supporting functions, you will
+// need to manually validate what the generated code is for the test files:
+//   objectivec/Tests/unittest_extension_chain_*.proto
+// There are comments about what the expected code should be line and limited
+// testing objectivec/Tests/GPBUnittestProtos2.m around compilation (#imports
+// specifically).
+void CollectMinimalFileDepsContainingExtensions(
+    const FileDescriptor* file,
+    std::vector<const FileDescriptor*>* files) {
+  std::set<const FileDescriptor*> files_visited;
+  for (int i = 0; i < file->dependency_count(); i++) {
+    const FileDescriptor* dep = file->dependency(i);
+    CollectMinimalFileDepsContainingExtensionsWorker(dep, files,
+                                                     &files_visited);
+  }
+}
+
+bool IsDirectDependency(const FileDescriptor* dep, const FileDescriptor* file) {
+  for (int i = 0; i < file->dependency_count(); i++) {
+    if (dep == file->dependency(i)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+}  // namespace
+
+FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options)
     : file_(file),
       root_class_name_(FileClassName(file)),
-      is_public_dep_(false) {
+      is_bundled_proto_(IsProtobufLibraryBundledProtoFile(file)),
+      options_(options) {
   for (int i = 0; i < file_->enum_type_count(); i++) {
     EnumGenerator *generator = new EnumGenerator(file_->enum_type(i));
     enum_generators_.push_back(generator);
   }
   for (int i = 0; i < file_->message_type_count(); i++) {
     MessageGenerator *generator =
-        new MessageGenerator(root_class_name_, file_->message_type(i));
+        new MessageGenerator(root_class_name_, file_->message_type(i), options_);
     message_generators_.push_back(generator);
   }
   for (int i = 0; i < file_->extension_count(); i++) {
@@ -71,8 +207,6 @@
 }
 
 FileGenerator::~FileGenerator() {
-  STLDeleteContainerPointers(dependency_generators_.begin(),
-                             dependency_generators_.end());
   STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end());
   STLDeleteContainerPointers(message_generators_.begin(),
                              message_generators_.end());
@@ -81,48 +215,66 @@
 }
 
 void FileGenerator::GenerateHeader(io::Printer *printer) {
-  printer->Print(
-      "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
-      "// source: $filename$\n"
-      "\n",
-      "filename", file_->name());
-
-  printer->Print(
-      "#import \"GPBProtocolBuffers.h\"\n"
-      "\n");
+  std::set<string> headers;
+  // Generated files bundled with the library get minimal imports, everything
+  // else gets the wrapper so everything is usable.
+  if (is_bundled_proto_) {
+    headers.insert("GPBRootObject.h");
+    headers.insert("GPBMessage.h");
+    headers.insert("GPBDescriptor.h");
+  } else {
+    headers.insert("GPBProtocolBuffers.h");
+  }
+  PrintFileRuntimePreamble(printer, headers);
 
   // Add some verification that the generated code matches the source the
   // code is being compiled with.
+  // NOTE: This captures the raw numeric values at the time the generator was
+  // compiled, since that will be the versions for the ObjC runtime at that
+  // time.  The constants in the generated code will then get their values at
+  // at compile time (so checking against the headers being used to compile).
   printer->Print(
-      "#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != $protoc_gen_objc_version$\n"
-      "#error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources.\n"
+      "#if GOOGLE_PROTOBUF_OBJC_VERSION < $google_protobuf_objc_version$\n"
+      "#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.\n"
+      "#endif\n"
+      "#if $google_protobuf_objc_version$ < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION\n"
+      "#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.\n"
       "#endif\n"
       "\n",
-      "protoc_gen_objc_version",
-      SimpleItoa(GOOGLE_PROTOBUF_OBJC_GEN_VERSION));
+      "google_protobuf_objc_version", SimpleItoa(GOOGLE_PROTOBUF_OBJC_VERSION));
 
-  const vector<FileGenerator *> &dependency_generators = DependencyGenerators();
-  for (vector<FileGenerator *>::const_iterator iter =
-           dependency_generators.begin();
-       iter != dependency_generators.end(); ++iter) {
-    if ((*iter)->IsPublicDependency()) {
-      printer->Print("#import \"$header$.pbobjc.h\"\n",
-                     "header", (*iter)->Path());
+  // #import any headers for "public imports" in the proto file.
+  {
+    ImportWriter import_writer(
+        options_.generate_for_named_framework,
+        options_.named_framework_to_proto_path_mappings_path,
+        is_bundled_proto_);
+    const string header_extension(kHeaderExtension);
+    for (int i = 0; i < file_->public_dependency_count(); i++) {
+      import_writer.AddFile(file_->public_dependency(i), header_extension);
     }
+    import_writer.Print(printer);
   }
 
+  // Note:
+  //  deprecated-declarations suppression is only needed if some place in this
+  //    proto file is something deprecated or if it references something from
+  //    another file that is deprecated.
   printer->Print(
       "// @@protoc_insertion_point(imports)\n"
       "\n"
+      "#pragma clang diagnostic push\n"
+      "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n"
+      "\n"
       "CF_EXTERN_C_BEGIN\n"
       "\n");
 
-  set<string> fwd_decls;
-  for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
+  std::set<string> fwd_decls;
+  for (std::vector<MessageGenerator *>::iterator iter = message_generators_.begin();
        iter != message_generators_.end(); ++iter) {
     (*iter)->DetermineForwardDeclarations(&fwd_decls);
   }
-  for (set<string>::const_iterator i(fwd_decls.begin());
+  for (std::set<string>::const_iterator i(fwd_decls.begin());
        i != fwd_decls.end(); ++i) {
     printer->Print("$value$;\n", "value", *i);
   }
@@ -135,12 +287,12 @@
       "\n");
 
   // need to write out all enums first
-  for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin();
+  for (std::vector<EnumGenerator *>::iterator iter = enum_generators_.begin();
        iter != enum_generators_.end(); ++iter) {
     (*iter)->GenerateHeader(printer);
   }
 
-  for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
+  for (std::vector<MessageGenerator *>::iterator iter = message_generators_.begin();
        iter != message_generators_.end(); ++iter) {
     (*iter)->GenerateEnumHeader(printer);
   }
@@ -150,13 +302,17 @@
   printer->Print(
       "#pragma mark - $root_class_name$\n"
       "\n"
+      "/**\n"
+      " * Exposes the extension registry for this file.\n"
+      " *\n"
+      " * The base class provides:\n"
+      " * @code\n"
+      " *   + (GPBExtensionRegistry *)extensionRegistry;\n"
+      " * @endcode\n"
+      " * which is a @c GPBExtensionRegistry that includes all the extensions defined by\n"
+      " * this file and all files that it depends on.\n"
+      " **/\n"
       "@interface $root_class_name$ : GPBRootObject\n"
-      "\n"
-      "// The base class provides:\n"
-      "//   + (GPBExtensionRegistry *)extensionRegistry;\n"
-      "// which is an GPBExtensionRegistry that includes all the extensions defined by\n"
-      "// this file and all files that it depends on.\n"
-      "\n"
       "@end\n"
       "\n",
       "root_class_name", root_class_name_);
@@ -167,7 +323,7 @@
         "@interface $root_class_name$ (DynamicMethods)\n",
         "root_class_name", root_class_name_);
 
-    for (vector<ExtensionGenerator *>::iterator iter =
+    for (std::vector<ExtensionGenerator *>::iterator iter =
              extension_generators_.begin();
          iter != extension_generators_.end(); ++iter) {
       (*iter)->GenerateMembersHeader(printer);
@@ -176,7 +332,7 @@
     printer->Print("@end\n\n");
   }  // extension_generators_.size() > 0
 
-  for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
+  for (std::vector<MessageGenerator *>::iterator iter = message_generators_.begin();
        iter != message_generators_.end(); ++iter) {
     (*iter)->GenerateMessageHeader(printer);
   }
@@ -186,81 +342,130 @@
       "\n"
       "CF_EXTERN_C_END\n"
       "\n"
+      "#pragma clang diagnostic pop\n"
+      "\n"
       "// @@protoc_insertion_point(global_scope)\n");
 }
 
 void FileGenerator::GenerateSource(io::Printer *printer) {
-  printer->Print(
-      "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
-      "// source: $filename$\n"
-      "\n",
-      "filename", file_->name());
+  // #import the runtime support.
+  std::set<string> headers;
+  headers.insert("GPBProtocolBuffers_RuntimeSupport.h");
+  PrintFileRuntimePreamble(printer, headers);
 
-  string header_file = Path() + ".pbobjc.h";
-  printer->Print(
-      "#import \"GPBProtocolBuffers_RuntimeSupport.h\"\n"
-      "#import \"$header_file$\"\n",
-      "header_file", header_file);
-  const vector<FileGenerator *> &dependency_generators =
-      DependencyGenerators();
-  for (vector<FileGenerator *>::const_iterator iter =
-           dependency_generators.begin();
-       iter != dependency_generators.end(); ++iter) {
-    if (!(*iter)->IsPublicDependency()) {
-      printer->Print("#import \"$header$.pbobjc.h\"\n",
-                     "header", (*iter)->Path());
+  // Enums use atomic in the generated code, so add the system import as needed.
+  if (FileContainsEnums(file_)) {
+    printer->Print(
+        "#import <stdatomic.h>\n"
+        "\n");
+  }
+
+  std::vector<const FileDescriptor*> deps_with_extensions;
+  CollectMinimalFileDepsContainingExtensions(file_, &deps_with_extensions);
+
+  {
+    ImportWriter import_writer(
+        options_.generate_for_named_framework,
+        options_.named_framework_to_proto_path_mappings_path,
+        is_bundled_proto_);
+    const string header_extension(kHeaderExtension);
+
+    // #import the header for this proto file.
+    import_writer.AddFile(file_, header_extension);
+
+    // #import the headers for anything that a plain dependency of this proto
+    // file (that means they were just an include, not a "public" include).
+    std::set<string> public_import_names;
+    for (int i = 0; i < file_->public_dependency_count(); i++) {
+      public_import_names.insert(file_->public_dependency(i)->name());
+    }
+    for (int i = 0; i < file_->dependency_count(); i++) {
+      const FileDescriptor *dep = file_->dependency(i);
+      bool public_import = (public_import_names.count(dep->name()) != 0);
+      if (!public_import) {
+        import_writer.AddFile(dep, header_extension);
+      }
+    }
+
+    // If any indirect dependency provided extensions, it needs to be directly
+    // imported so it can get merged into the root's extensions registry.
+    // See the Note by CollectMinimalFileDepsContainingExtensions before
+    // changing this.
+    for (std::vector<const FileDescriptor *>::iterator iter =
+             deps_with_extensions.begin();
+         iter != deps_with_extensions.end(); ++iter) {
+      if (!IsDirectDependency(*iter, file_)) {
+        import_writer.AddFile(*iter, header_extension);
+      }
+    }
+
+    import_writer.Print(printer);
+  }
+
+  bool includes_oneof = false;
+  for (std::vector<MessageGenerator *>::iterator iter = message_generators_.begin();
+       iter != message_generators_.end(); ++iter) {
+    if ((*iter)->IncludesOneOfDefinition()) {
+      includes_oneof = true;
+      break;
     }
   }
+
+  // Note:
+  //  deprecated-declarations suppression is only needed if some place in this
+  //    proto file is something deprecated or if it references something from
+  //    another file that is deprecated.
   printer->Print(
       "// @@protoc_insertion_point(imports)\n"
-      "\n");
+      "\n"
+      "#pragma clang diagnostic push\n"
+      "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n");
+  if (includes_oneof) {
+    // The generated code for oneof's uses direct ivar access, suppress the
+    // warning incase developer turn that on in the context they compile the
+    // generated code.
+    printer->Print(
+        "#pragma clang diagnostic ignored \"-Wdirect-ivar-access\"\n");
+  }
 
   printer->Print(
+      "\n"
       "#pragma mark - $root_class_name$\n"
       "\n"
       "@implementation $root_class_name$\n\n",
       "root_class_name", root_class_name_);
 
-  // Generate the extension initialization structures for the top level and
-  // any nested messages.
-  ostringstream extensions_stringstream;
-  if (file_->extension_count() + file_->message_type_count() > 0) {
-    io::OstreamOutputStream extensions_outputstream(&extensions_stringstream);
-    io::Printer extensions_printer(&extensions_outputstream, '$');
-    for (vector<ExtensionGenerator *>::iterator iter =
-             extension_generators_.begin();
-         iter != extension_generators_.end(); ++iter) {
-      (*iter)->GenerateStaticVariablesInitialization(&extensions_printer);
-    }
-    for (vector<MessageGenerator *>::iterator iter =
-             message_generators_.begin();
-         iter != message_generators_.end(); ++iter) {
-      (*iter)->GenerateStaticVariablesInitialization(&extensions_printer);
-    }
-    extensions_stringstream.flush();
-  }
+  const bool file_contains_extensions = FileContainsExtensions(file_);
 
   // If there were any extensions or this file has any dependencies, output
   // a registry to override to create the file specific registry.
-  const string& extensions_str = extensions_stringstream.str();
-  if (extensions_str.length() > 0 || file_->dependency_count() > 0) {
+  if (file_contains_extensions || !deps_with_extensions.empty()) {
     printer->Print(
         "+ (GPBExtensionRegistry*)extensionRegistry {\n"
         "  // This is called by +initialize so there is no need to worry\n"
         "  // about thread safety and initialization of registry.\n"
         "  static GPBExtensionRegistry* registry = nil;\n"
         "  if (!registry) {\n"
-        "    GPBDebugCheckRuntimeVersion();\n"
+        "    GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n"
         "    registry = [[GPBExtensionRegistry alloc] init];\n");
 
     printer->Indent();
     printer->Indent();
 
-    if (extensions_str.length() > 0) {
+    if (file_contains_extensions) {
       printer->Print(
           "static GPBExtensionDescription descriptions[] = {\n");
       printer->Indent();
-      printer->Print(extensions_str.c_str());
+      for (std::vector<ExtensionGenerator *>::iterator iter =
+               extension_generators_.begin();
+           iter != extension_generators_.end(); ++iter) {
+        (*iter)->GenerateStaticVariablesInitialization(printer);
+      }
+      for (std::vector<MessageGenerator *>::iterator iter =
+               message_generators_.begin();
+           iter != message_generators_.end(); ++iter) {
+        (*iter)->GenerateStaticVariablesInitialization(printer);
+      }
       printer->Outdent();
       printer->Print(
           "};\n"
@@ -273,14 +478,21 @@
           "}\n");
     }
 
-    const vector<FileGenerator *> &dependency_generators =
-        DependencyGenerators();
-    for (vector<FileGenerator *>::const_iterator iter =
-             dependency_generators.begin();
-         iter != dependency_generators.end(); ++iter) {
+    if (deps_with_extensions.empty()) {
       printer->Print(
-          "[registry addExtensions:[$dependency$ extensionRegistry]];\n",
-          "dependency", (*iter)->RootClassName());
+          "// None of the imports (direct or indirect) defined extensions, so no need to add\n"
+          "// them to this registry.\n");
+    } else {
+      printer->Print(
+          "// Merge in the imports (direct or indirect) that defined extensions.\n");
+      for (std::vector<const FileDescriptor *>::iterator iter =
+               deps_with_extensions.begin();
+           iter != deps_with_extensions.end(); ++iter) {
+        const string root_class_name(FileClassName((*iter)));
+        printer->Print(
+            "[registry addExtensions:[$dependency$ extensionRegistry]];\n",
+            "dependency", root_class_name);
+      }
     }
 
     printer->Outdent();
@@ -289,27 +501,39 @@
     printer->Print(
         "  }\n"
         "  return registry;\n"
-        "}\n"
-        "\n");
+        "}\n");
+  } else {
+    if (file_->dependency_count() > 0) {
+      printer->Print(
+          "// No extensions in the file and none of the imports (direct or indirect)\n"
+          "// defined extensions, so no need to generate +extensionRegistry.\n");
+    } else {
+      printer->Print(
+          "// No extensions in the file and no imports, so no need to generate\n"
+          "// +extensionRegistry.\n");
+    }
   }
 
-  printer->Print("@end\n\n");
+  printer->Print("\n@end\n\n");
 
   // File descriptor only needed if there are messages to use it.
   if (message_generators_.size() > 0) {
-    string syntax;
+    std::map<string, string> vars;
+    vars["root_class_name"] = root_class_name_;
+    vars["package"] = file_->package();
+    vars["objc_prefix"] = FileClassPrefix(file_);
     switch (file_->syntax()) {
       case FileDescriptor::SYNTAX_UNKNOWN:
-        syntax = "GPBFileSyntaxUnknown";
+        vars["syntax"] = "GPBFileSyntaxUnknown";
         break;
       case FileDescriptor::SYNTAX_PROTO2:
-        syntax = "GPBFileSyntaxProto2";
+        vars["syntax"] = "GPBFileSyntaxProto2";
         break;
       case FileDescriptor::SYNTAX_PROTO3:
-        syntax = "GPBFileSyntaxProto3";
+        vars["syntax"] = "GPBFileSyntaxProto3";
         break;
     }
-    printer->Print(
+    printer->Print(vars,
         "#pragma mark - $root_class_name$_FileDescriptor\n"
         "\n"
         "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n"
@@ -317,49 +541,88 @@
         "  // about thread safety of the singleton.\n"
         "  static GPBFileDescriptor *descriptor = NULL;\n"
         "  if (!descriptor) {\n"
-        "    GPBDebugCheckRuntimeVersion();\n"
-        "    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
-        "                                                     syntax:$syntax$];\n"
+        "    GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n");
+    if (vars["objc_prefix"].size() > 0) {
+      printer->Print(
+          vars,
+          "    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
+          "                                                 objcPrefix:@\"$objc_prefix$\"\n"
+          "                                                     syntax:$syntax$];\n");
+    } else {
+      printer->Print(
+          vars,
+          "    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
+          "                                                     syntax:$syntax$];\n");
+    }
+    printer->Print(
         "  }\n"
         "  return descriptor;\n"
         "}\n"
-        "\n",
-        "root_class_name", root_class_name_,
-        "package", file_->package(),
-        "syntax", syntax);
+        "\n");
   }
 
-  for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin();
+  for (std::vector<EnumGenerator *>::iterator iter = enum_generators_.begin();
        iter != enum_generators_.end(); ++iter) {
     (*iter)->GenerateSource(printer);
   }
-  for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
+  for (std::vector<MessageGenerator *>::iterator iter = message_generators_.begin();
        iter != message_generators_.end(); ++iter) {
     (*iter)->GenerateSource(printer);
   }
 
   printer->Print(
     "\n"
+    "#pragma clang diagnostic pop\n"
+    "\n"
     "// @@protoc_insertion_point(global_scope)\n");
 }
 
-const string FileGenerator::Path() const { return FilePath(file_); }
+// Helper to print the import of the runtime support at the top of generated
+// files. This currently only supports the runtime coming from a framework
+// as defined by the official CocoaPod.
+void FileGenerator::PrintFileRuntimePreamble(
+    io::Printer* printer, const std::set<string>& headers_to_import) const {
+  printer->Print(
+      "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+      "// source: $filename$\n"
+      "\n",
+      "filename", file_->name());
 
-const vector<FileGenerator *> &FileGenerator::DependencyGenerators() {
-  if (file_->dependency_count() != dependency_generators_.size()) {
-    set<string> public_import_names;
-    for (int i = 0; i < file_->public_dependency_count(); i++) {
-      public_import_names.insert(file_->public_dependency(i)->name());
-    }
-    for (int i = 0; i < file_->dependency_count(); i++) {
-      FileGenerator *generator = new FileGenerator(file_->dependency(i));
-      const string& name = file_->dependency(i)->name();
-      bool public_import = (public_import_names.count(name) != 0);
-      generator->SetIsPublicDependency(public_import);
-      dependency_generators_.push_back(generator);
-    }
+  const string framework_name(ProtobufLibraryFrameworkName);
+  const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name));
+
+  printer->Print(
+      "// This CPP symbol can be defined to use imports that match up to the framework\n"
+      "// imports needed when using CocoaPods.\n"
+      "#if !defined($cpp_symbol$)\n"
+      " #define $cpp_symbol$ 0\n"
+      "#endif\n"
+      "\n"
+      "#if $cpp_symbol$\n",
+      "cpp_symbol", cpp_symbol);
+
+
+  for (std::set<string>::const_iterator iter = headers_to_import.begin();
+       iter != headers_to_import.end(); ++iter) {
+    printer->Print(
+        " #import <$framework_name$/$header$>\n",
+        "header", *iter,
+        "framework_name", framework_name);
   }
-  return dependency_generators_;
+
+  printer->Print(
+      "#else\n");
+
+  for (std::set<string>::const_iterator iter = headers_to_import.begin();
+       iter != headers_to_import.end(); ++iter) {
+    printer->Print(
+        " #import \"$header$\"\n",
+        "header", *iter);
+  }
+
+  printer->Print(
+      "#endif\n"
+      "\n");
 }
 
 }  // namespace objectivec
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h
index 1bb4f0e..1754fc0 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h
@@ -55,36 +55,27 @@
 
 class FileGenerator {
  public:
-  explicit FileGenerator(const FileDescriptor* file);
+  FileGenerator(const FileDescriptor* file, const Options& options);
   ~FileGenerator();
 
   void GenerateSource(io::Printer* printer);
   void GenerateHeader(io::Printer* printer);
 
   const string& RootClassName() const { return root_class_name_; }
-  const string Path() const;
-
-  bool IsPublicDependency() const { return is_public_dep_; }
-
- protected:
-  void SetIsPublicDependency(bool is_public_dep) {
-    is_public_dep_ = is_public_dep;
-  }
 
  private:
   const FileDescriptor* file_;
   string root_class_name_;
+  bool is_bundled_proto_;
 
-  // Access this field through the DependencyGenerators accessor call below.
-  // Do not reference it directly.
-  vector<FileGenerator*> dependency_generators_;
+  std::vector<EnumGenerator*> enum_generators_;
+  std::vector<MessageGenerator*> message_generators_;
+  std::vector<ExtensionGenerator*> extension_generators_;
 
-  vector<EnumGenerator*> enum_generators_;
-  vector<MessageGenerator*> message_generators_;
-  vector<ExtensionGenerator*> extension_generators_;
-  bool is_public_dep_;
+  const Options options_;
 
-  const vector<FileGenerator*>& DependencyGenerators();
+  void PrintFileRuntimePreamble(
+      io::Printer* printer, const std::set<string>& headers_to_import) const;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
 };
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
index 375b4e0..e0597cc 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
@@ -45,41 +45,116 @@
 
 ObjectiveCGenerator::~ObjectiveCGenerator() {}
 
+bool ObjectiveCGenerator::HasGenerateAll() const {
+  return true;
+}
+
 bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
                                    const string& parameter,
-                                   OutputDirectory* output_directory,
+                                   GeneratorContext* context,
                                    string* error) const {
-  // ObjC doesn't have any options at the moment, error if passed one.
-  vector<pair<string, string> > options;
+  *error = "Unimplemented Generate() method. Call GenerateAll() instead.";
+  return false;
+}
+
+bool ObjectiveCGenerator::GenerateAll(const std::vector<const FileDescriptor*>& files,
+                                      const string& parameter,
+                                      GeneratorContext* context,
+                                      string* error) const {
+  // -----------------------------------------------------------------
+  // Parse generator options. These options are passed to the compiler using the
+  // --objc_opt flag. The options are passed as a comma separated list of
+  // options along with their values. If the option appears multiple times, only
+  // the last value will be considered.
+  //
+  // e.g. protoc ... --objc_opt=expected_prefixes=file.txt,generate_for_named_framework=MyFramework
+
+  Options generation_options;
+
+  std::vector<std::pair<string, string> > options;
   ParseGeneratorParameter(parameter, &options);
   for (int i = 0; i < options.size(); i++) {
-    *error = "error:: Unknown generator option: " + options[i].first;
-    return false;
+    if (options[i].first == "expected_prefixes_path") {
+      // Path to find a file containing the expected prefixes
+      // (objc_class_prefix "PREFIX") for proto packages (package NAME). The
+      // generator will then issue warnings/errors if in the proto files being
+      // generated the option is not listed/wrong/etc in the file.
+      //
+      // The format of the file is:
+      //   - An entry is a line of "package=prefix".
+      //   - Comments start with "#".
+      //   - A comment can go on a line after a expected package/prefix pair.
+      //     (i.e. - "package=prefix # comment")
+      //
+      // There is no validation that the prefixes are good prefixes, it is
+      // assumed that they are when you create the file.
+      generation_options.expected_prefixes_path = options[i].second;
+    } else if (options[i].first == "generate_for_named_framework") {
+      // The name of the framework that protos are being generated for. This
+      // will cause the #import statements to be framework based using this
+      // name (i.e. - "#import <NAME/proto.pbobjc.h>).
+      //
+      // NOTE: If this option is used with
+      // named_framework_to_proto_path_mappings_path, then this is effectively
+      // the "default" framework name used for everything that wasn't mapped by
+      // the mapping file.
+      generation_options.generate_for_named_framework = options[i].second;
+    } else if (options[i].first == "named_framework_to_proto_path_mappings_path") {
+      // Path to find a file containing the list of framework names and proto
+      // files. The generator uses this to decide if a proto file
+      // referenced should use a framework style import vs. a user level import
+      // (#import <FRAMEWORK/file.pbobjc.h> vs #import "dir/file.pbobjc.h").
+      //
+      // The format of the file is:
+      //   - An entry is a line of "frameworkName: file.proto, dir/file2.proto".
+      //   - Comments start with "#".
+      //   - A comment can go on a line after a expected package/prefix pair.
+      //     (i.e. - "frameworkName: file.proto # comment")
+      //
+      // Any number of files can be listed for a framework, just separate them
+      // with commas.
+      //
+      // There can be multiple lines listing the same frameworkName incase it
+      // has a lot of proto files included in it; having multiple lines makes
+      // things easier to read. If a proto file is not configured in the
+      // mappings file, it will use the default framework name if one was passed
+      // with generate_for_named_framework, or the relative path to it's include
+      // path otherwise.
+      generation_options.named_framework_to_proto_path_mappings_path = options[i].second;
+    } else {
+      *error = "error: Unknown generator option: " + options[i].first;
+      return false;
+    }
   }
 
-  // Validate the objc prefix/package pairing.
-  if (!ValidateObjCClassPrefix(file, error)) {
+  // -----------------------------------------------------------------
+
+  // Validate the objc prefix/package pairings.
+  if (!ValidateObjCClassPrefixes(files, generation_options, error)) {
     // *error will have been filled in.
     return false;
   }
 
-  FileGenerator file_generator(file);
-  string filepath = FilePath(file);
+  for (int i = 0; i < files.size(); i++) {
+    const FileDescriptor* file = files[i];
+    FileGenerator file_generator(file, generation_options);
+    string filepath = FilePath(file);
 
-  // Generate header.
-  {
-    scoped_ptr<io::ZeroCopyOutputStream> output(
-        output_directory->Open(filepath + ".pbobjc.h"));
-    io::Printer printer(output.get(), '$');
-    file_generator.GenerateHeader(&printer);
-  }
+    // Generate header.
+    {
+      std::unique_ptr<io::ZeroCopyOutputStream> output(
+          context->Open(filepath + ".pbobjc.h"));
+      io::Printer printer(output.get(), '$');
+      file_generator.GenerateHeader(&printer);
+    }
 
-  // Generate m file.
-  {
-    scoped_ptr<io::ZeroCopyOutputStream> output(
-        output_directory->Open(filepath + ".pbobjc.m"));
-    io::Printer printer(output.get(), '$');
-    file_generator.GenerateSource(&printer);
+    // Generate m file.
+    {
+      std::unique_ptr<io::ZeroCopyOutputStream> output(
+          context->Open(filepath + ".pbobjc.m"));
+      io::Printer printer(output.get(), '$');
+      file_generator.GenerateSource(&printer);
+    }
   }
 
   return true;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.h b/src/google/protobuf/compiler/objectivec/objectivec_generator.h
index 09266b0..3e43f73 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_generator.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.h
@@ -41,14 +41,25 @@
 namespace compiler {
 namespace objectivec {
 
+// CodeGenerator implementation which generates a ObjectiveC source file and
+// header.  If you create your own protocol compiler binary and you want it to
+// support ObjectiveC output, you can do so by registering an instance of this
+// CodeGenerator with the CommandLineInterface in your main() function.
 class LIBPROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator {
  public:
   ObjectiveCGenerator();
   ~ObjectiveCGenerator();
 
   // implements CodeGenerator ----------------------------------------
-  bool Generate(const FileDescriptor* file, const string& parameter,
-                OutputDirectory* output_directory, string* error) const;
+  bool HasGenerateAll() const;
+  bool Generate(const FileDescriptor* file,
+                const string& parameter,
+                GeneratorContext* context,
+                string* error) const;
+  bool GenerateAll(const std::vector<const FileDescriptor*>& files,
+                   const string& parameter,
+                   GeneratorContext* context,
+                   string* error) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectiveCGenerator);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
index 8527b74..df71c8b 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
@@ -28,9 +28,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#ifdef _MSC_VER
-#include <io.h>
-#else
+#ifndef _MSC_VER
 #include <unistd.h>
 #endif
 #include <climits>
@@ -44,12 +42,15 @@
 
 #include <google/protobuf/stubs/hash.h>
 #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/io_win32.h>
 #include <google/protobuf/stubs/strutil.h>
 
+
 // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
 // error cases, so it seems to be ok to use as a back door for errors.
 
@@ -58,6 +59,24 @@
 namespace compiler {
 namespace objectivec {
 
+// <io.h> is transitively included in this file. Import the functions explicitly
+// in this port namespace to avoid ambiguous definition.
+namespace posix {
+#ifdef _WIN32
+using ::google::protobuf::internal::win32::open;
+#else
+using ::open;
+#endif
+}  // namespace port
+
+Options::Options() {
+  // Default is the value of the env for the package prefixes.
+  const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES");
+  if (file_path) {
+    expected_prefixes_path = file_path;
+  }
+}
+
 namespace {
 
 hash_set<string> MakeWordsMap(const char* const words[], size_t num_words) {
@@ -73,11 +92,15 @@
 hash_set<string> kUpperSegments =
     MakeWordsMap(kUpperSegmentsList, GOOGLE_ARRAYSIZE(kUpperSegmentsList));
 
+bool ascii_isnewline(char c) {
+  return c == '\n' || c == '\r';
+}
+
 // Internal helper for name handing.
 // Do not expose this outside of helpers, stick to having functions for specific
 // cases (ClassName(), FieldName()), so there is always consistent suffix rules.
 string UnderscoresToCamelCase(const string& input, bool first_capitalized) {
-  vector<string> values;
+  std::vector<string> values;
   string current;
 
   bool last_char_was_number = false;
@@ -116,9 +139,14 @@
   }
   values.push_back(current);
 
-  for (vector<string>::iterator i = values.begin(); i != values.end(); ++i) {
+  string result;
+  bool first_segment_forces_upper = false;
+  for (std::vector<string>::iterator i = values.begin(); i != values.end(); ++i) {
     string value = *i;
     bool all_upper = (kUpperSegments.count(value) > 0);
+    if (all_upper && (result.length() == 0)) {
+      first_segment_forces_upper = true;
+    }
     for (int j = 0; j < value.length(); j++) {
       if (j == 0 || all_upper) {
         value[j] = ascii_toupper(value[j]);
@@ -126,13 +154,11 @@
         // Nothing, already in lower.
       }
     }
-    *i = value;
+    result += value;
   }
-  string result;
-  for (vector<string>::iterator i = values.begin(); i != values.end(); ++i) {
-    result += *i;
-  }
-  if ((result.length() != 0) && !first_capitalized) {
+  if ((result.length() != 0) &&
+      !first_capitalized &&
+      !first_segment_forces_upper) {
     result[0] = ascii_tolower(result[0]);
   }
   return result;
@@ -180,7 +206,7 @@
     // method declared in protos. The main cases are methods
     // that take no arguments, or setFoo:/hasFoo: type methods.
     "clear", "data", "delimitedData", "descriptor", "extensionRegistry",
-    "extensionsCurrentlySet", "isInitialized", "serializedSize",
+    "extensionsCurrentlySet", "initialized", "isInitialized", "serializedSize",
     "sortedExtensionsInUse", "unknownFields",
 
     // MacTypes.h names
@@ -194,10 +220,14 @@
 hash_set<string> kReservedWords =
     MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList));
 
-string SanitizeNameForObjC(const string& input, const string& extension) {
+string SanitizeNameForObjC(const string& input,
+                           const string& extension,
+                           string* out_suffix_added) {
   if (kReservedWords.count(input) > 0) {
+    if (out_suffix_added) *out_suffix_added = extension;
     return input + extension;
   }
+  if (out_suffix_added) out_suffix_added->clear();
   return input;
 }
 
@@ -209,11 +239,6 @@
   }
 }
 
-// Escape C++ trigraphs by escaping question marks to \?
-string EscapeTrigraphs(const string& to_escape) {
-  return StringReplace(to_escape, "?", "\\?", true);
-}
-
 void PathSplit(const string& path, string* directory, string* basename) {
   string::size_type last_slash = path.rfind('/');
   if (last_slash == string::npos) {
@@ -251,8 +276,41 @@
   return false;
 }
 
+string GetZeroEnumNameForFlagType(const FlagType flag_type) {
+  switch(flag_type) {
+    case FLAGTYPE_DESCRIPTOR_INITIALIZATION:
+      return "GPBDescriptorInitializationFlag_None";
+    case FLAGTYPE_EXTENSION:
+      return "GPBExtensionNone";
+    case FLAGTYPE_FIELD:
+      return "GPBFieldNone";
+    default:
+      GOOGLE_LOG(FATAL) << "Can't get here.";
+      return "0";
+  }
+}
+
+string GetEnumNameForFlagType(const FlagType flag_type) {
+  switch(flag_type) {
+    case FLAGTYPE_DESCRIPTOR_INITIALIZATION:
+      return "GPBDescriptorInitializationFlags";
+    case FLAGTYPE_EXTENSION:
+      return "GPBExtensionOptions";
+    case FLAGTYPE_FIELD:
+      return "GPBFieldFlags";
+    default:
+      GOOGLE_LOG(FATAL) << "Can't get here.";
+      return string();
+  }
+}
+
 }  // namespace
 
+// Escape C++ trigraphs by escaping question marks to \?
+string EscapeTrigraphs(const string& to_escape) {
+  return StringReplace(to_escape, "?", "\\?", true);
+}
+
 string StripProto(const string& filename) {
   if (HasSuffixString(filename, ".protodevel")) {
     return StripSuffixString(filename, ".protodevel");
@@ -261,6 +319,16 @@
   }
 }
 
+void StringPieceTrimWhitespace(StringPiece* input) {
+  while (!input->empty() && ascii_isspace(*input->data())) {
+    input->remove_prefix(1);
+  }
+  while (!input->empty() && ascii_isspace((*input)[input->length() - 1])) {
+    input->remove_suffix(1);
+  }
+}
+
+
 bool IsRetainedName(const string& name) {
   // List of prefixes from
   // http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
@@ -282,11 +350,10 @@
   return basename;
 }
 
-string FileName(const FileDescriptor* file) {
-  string path = FilePath(file);
-  string basename;
-  PathSplit(path, NULL, &basename);
-  return basename;
+string FileClassPrefix(const FileDescriptor* file) {
+  // Default is empty string, no need to check has_objc_class_prefix.
+  string result = file->options().objc_class_prefix();
+  return result;
 }
 
 string FilePath(const FileDescriptor* file) {
@@ -306,10 +373,17 @@
   return output;
 }
 
-string FileClassPrefix(const FileDescriptor* file) {
-  // Default is empty string, no need to check has_objc_class_prefix.
-  string result = file->options().objc_class_prefix();
-  return result;
+string FilePathBasename(const FileDescriptor* file) {
+  string output;
+  string basename;
+  string directory;
+  PathSplit(file->name(), &directory, &basename);
+  basename = StripProto(basename);
+
+  // CamelCase to be more ObjC friendly.
+  output = UnderscoresToCamelCase(basename, true);
+
+  return output;
 }
 
 string FileClassName(const FileDescriptor* file) {
@@ -318,7 +392,7 @@
   name += "Root";
   // There aren't really any reserved words that end in "Root", but playing
   // it safe and checking.
-  return SanitizeNameForObjC(name, "_RootClass");
+  return SanitizeNameForObjC(name, "_RootClass", NULL);
 }
 
 string ClassNameWorker(const Descriptor* descriptor) {
@@ -340,11 +414,15 @@
 }
 
 string ClassName(const Descriptor* descriptor) {
+  return ClassName(descriptor, NULL);
+}
+
+string ClassName(const Descriptor* descriptor, string* out_suffix_added) {
   // 1. Message names are used as is (style calls for CamelCase, trust it).
   // 2. Check for reserved word at the very end and then suffix things.
   string prefix = FileClassPrefix(descriptor->file());
   string name = ClassNameWorker(descriptor);
-  return SanitizeNameForObjC(prefix + name, "_Class");
+  return SanitizeNameForObjC(prefix + name, "_Class", out_suffix_added);
 }
 
 string EnumName(const EnumDescriptor* descriptor) {
@@ -358,7 +436,7 @@
   //    yields Fixed_Class, Fixed_Size.
   string name = FileClassPrefix(descriptor->file());
   name += ClassNameWorker(descriptor);
-  return SanitizeNameForObjC(name, "_Enum");
+  return SanitizeNameForObjC(name, "_Enum", NULL);
 }
 
 string EnumValueName(const EnumValueDescriptor* descriptor) {
@@ -373,7 +451,7 @@
   const string& name = class_name + "_" + value_str;
   // There aren't really any reserved words with an underscore and a leading
   // capital letter, but playing it safe and checking.
-  return SanitizeNameForObjC(name, "_Value");
+  return SanitizeNameForObjC(name, "_Value", NULL);
 }
 
 string EnumValueShortName(const EnumValueDescriptor* descriptor) {
@@ -410,7 +488,7 @@
 string ExtensionMethodName(const FieldDescriptor* descriptor) {
   const string& name = NameFromFieldDescriptor(descriptor);
   const string& result = UnderscoresToCamelCase(name, false);
-  return SanitizeNameForObjC(result, "_Extension");
+  return SanitizeNameForObjC(result, "_Extension", NULL);
 }
 
 string FieldName(const FieldDescriptor* field) {
@@ -425,7 +503,7 @@
       result += "_p";
     }
   }
-  return SanitizeNameForObjC(result, "_p");
+  return SanitizeNameForObjC(result, "_p", NULL);
 }
 
 string FieldNameCapitalized(const FieldDescriptor* field) {
@@ -723,7 +801,7 @@
         uint32 length = ghtonl(default_string.length());
         string bytes((const char*)&length, sizeof(length));
         bytes.append(default_string);
-        return "(NSData*)\"" + CEscape(bytes) + "\"";
+        return "(NSData*)\"" + EscapeTrigraphs(CEscape(bytes)) + "\"";
       } else {
         return "@\"" + EscapeTrigraphs(CEscape(default_string)) + "\"";
       }
@@ -740,102 +818,155 @@
   return NULL;
 }
 
-string BuildFlagsString(const vector<string>& strings) {
-  if (strings.size() == 0) {
-    return "0";
+bool HasNonZeroDefaultValue(const FieldDescriptor* field) {
+  // Repeated fields don't have defaults.
+  if (field->is_repeated()) {
+    return false;
   }
-  string string;
+
+  // As much as checking field->has_default_value() seems useful, it isn't
+  // because of enums. proto2 syntax allows the first item in an enum (the
+  // default) to be non zero. So checking field->has_default_value() would
+  // result in missing this non zero default.  See MessageWithOneBasedEnum in
+  // objectivec/Tests/unittest_objc.proto for a test Message to confirm this.
+
+  // Some proto file set the default to the zero value, so make sure the value
+  // isn't the zero case.
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+      return field->default_value_int32() != 0;
+    case FieldDescriptor::CPPTYPE_UINT32:
+      return field->default_value_uint32() != 0U;
+    case FieldDescriptor::CPPTYPE_INT64:
+      return field->default_value_int64() != 0LL;
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return field->default_value_uint64() != 0ULL;
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return field->default_value_double() != 0.0;
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return field->default_value_float() != 0.0f;
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return field->default_value_bool();
+    case FieldDescriptor::CPPTYPE_STRING: {
+      const string& default_string = field->default_value_string();
+      return default_string.length() != 0;
+    }
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return field->default_value_enum()->number() != 0;
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return false;
+  }
+
+  // Some compilers report reaching end of function even though all cases of
+  // the enum are handed in the switch.
+  GOOGLE_LOG(FATAL) << "Can't get here.";
+  return false;
+}
+
+string BuildFlagsString(const FlagType flag_type,
+                        const std::vector<string>& strings) {
+  if (strings.size() == 0) {
+    return GetZeroEnumNameForFlagType(flag_type);
+  } else if (strings.size() == 1) {
+    return strings[0];
+  }
+  string string("(" + GetEnumNameForFlagType(flag_type) + ")(");
   for (size_t i = 0; i != strings.size(); ++i) {
     if (i > 0) {
       string.append(" | ");
     }
     string.append(strings[i]);
   }
+  string.append(")");
   return string;
 }
 
-string BuildCommentsString(const SourceLocation& location) {
+string BuildCommentsString(const SourceLocation& location,
+                           bool prefer_single_line) {
   const string& comments = location.leading_comments.empty()
                                ? location.trailing_comments
                                : location.leading_comments;
-  vector<string> lines;
+  std::vector<string> lines;
   SplitStringAllowEmpty(comments, "\n", &lines);
   while (!lines.empty() && lines.back().empty()) {
     lines.pop_back();
   }
-  string prefix("//");
-  string suffix("\n");
-  string final_comments;
-  for (int i = 0; i < lines.size(); i++) {
-    // We use $ for delimiters, so replace comments with dollars with
-    // html escaped version.
-    // None of the other compilers handle this (as of this writing) but we
-    // ran into it once, so just to be safe.
-    final_comments +=
-        prefix + StringReplace(lines[i], "$", "&#36;", true) + suffix;
+  // If there are no comments, just return an empty string.
+  if (lines.size() == 0) {
+    return "";
   }
+
+  string prefix;
+  string suffix;
+  string final_comments;
+  string epilogue;
+
+  bool add_leading_space = false;
+
+  if (prefer_single_line && lines.size() == 1) {
+    prefix = "/** ";
+    suffix = " */\n";
+  } else {
+    prefix = "* ";
+    suffix = "\n";
+    final_comments += "/**\n";
+    epilogue = " **/\n";
+    add_leading_space = true;
+  }
+
+  for (int i = 0; i < lines.size(); i++) {
+    string line = StripPrefixString(lines[i], " ");
+    // HeaderDoc and appledoc use '\' and '@' for markers; escape them.
+    line = StringReplace(line, "\\", "\\\\", true);
+    line = StringReplace(line, "@", "\\@", true);
+    // Decouple / from * to not have inline comments inside comments.
+    line = StringReplace(line, "/*", "/\\*", true);
+    line = StringReplace(line, "*/", "*\\/", true);
+    line = prefix + line;
+    StripWhitespace(&line);
+    // If not a one line, need to add the first space before *, as
+    // StripWhitespace would have removed it.
+    line = (add_leading_space ? " " : "") + line;
+    final_comments += line + suffix;
+  }
+  final_comments += epilogue;
   return final_comments;
 }
 
-namespace {
+// Making these a generator option for folks that don't use CocoaPods, but do
+// want to put the library in a framework is an interesting question. The
+// problem is it means changing sources shipped with the library to actually
+// use a different value; so it isn't as simple as a option.
+const char* const ProtobufLibraryFrameworkName = "Protobuf";
 
-// Internal helper class that parses the expected package to prefix mappings
-// file.
-class Parser {
- public:
-  Parser(map<string, string>* inout_package_to_prefix_map)
-      : prefix_map_(inout_package_to_prefix_map), line_(0) {}
-
-  // Parses a check of input, returning success/failure.
-  bool ParseChunk(StringPiece chunk);
-
-  // Should be called to finish parsing (after all input has been provided via
-  // ParseChunk()).  Returns success/failure.
-  bool Finish();
-
-  int last_line() const { return line_; }
-  string error_str() const { return error_str_; }
-
- private:
-  bool ParseLoop();
-
-  map<string, string>* prefix_map_;
-  int line_;
-  string error_str_;
-  StringPiece p_;
-  string leftover_;
-};
-
-bool Parser::ParseChunk(StringPiece chunk) {
-  if (!leftover_.empty()) {
-    chunk.AppendToString(&leftover_);
-    p_ = StringPiece(leftover_);
-  } else {
-    p_ = chunk;
-  }
-  bool result = ParseLoop();
-  if (p_.empty()) {
-    leftover_.clear();
-  } else {
-    leftover_ = p_.ToString();
-  }
+string ProtobufFrameworkImportSymbol(const string& framework_name) {
+  // GPB_USE_[framework_name]_FRAMEWORK_IMPORTS
+  string result = string("GPB_USE_");
+  result += ToUpper(framework_name);
+  result += "_FRAMEWORK_IMPORTS";
   return result;
 }
 
-bool Parser::Finish() {
-  if (leftover_.empty()) {
+bool IsProtobufLibraryBundledProtoFile(const FileDescriptor* file) {
+  // We don't check the name prefix or proto package because some files
+  // (descriptor.proto), aren't shipped generated by the library, so this
+  // seems to be the safest way to only catch the ones shipped.
+  const string name = file->name();
+  if (name == "google/protobuf/any.proto" ||
+      name == "google/protobuf/api.proto" ||
+      name == "google/protobuf/duration.proto" ||
+      name == "google/protobuf/empty.proto" ||
+      name == "google/protobuf/field_mask.proto" ||
+      name == "google/protobuf/source_context.proto" ||
+      name == "google/protobuf/struct.proto" ||
+      name == "google/protobuf/timestamp.proto" ||
+      name == "google/protobuf/type.proto" ||
+      name == "google/protobuf/wrappers.proto") {
     return true;
   }
-  // Force a newline onto the end to finish parsing.
-  p_ = StringPiece(leftover_ + "\n");
-  if (!ParseLoop()) {
-    return false;
-  }
-  return p_.empty();  // Everything used?
+  return false;
 }
 
-static bool ascii_isnewline(char c) { return c == '\n' || c == '\r'; }
-
 bool ReadLine(StringPiece* input, StringPiece* line) {
   for (int len = 0; len < input->size(); ++len) {
     if (ascii_isnewline((*input)[len])) {
@@ -848,15 +979,6 @@
   return false;  // Ran out of input with no newline.
 }
 
-void TrimWhitespace(StringPiece* input) {
-  while (!input->empty() && ascii_isspace(*input->data())) {
-    input->remove_prefix(1);
-  }
-  while (!input->empty() && ascii_isspace((*input)[input->length() - 1])) {
-    input->remove_suffix(1);
-  }
-}
-
 void RemoveComment(StringPiece* input) {
   int offset = input->find('#');
   if (offset != StringPiece::npos) {
@@ -864,91 +986,64 @@
   }
 }
 
-bool Parser::ParseLoop() {
-  StringPiece line;
-  while (ReadLine(&p_, &line)) {
-    ++line_;
-    RemoveComment(&line);
-    TrimWhitespace(&line);
-    if (line.size() == 0) {
-      continue;  // Blank line.
-    }
-    int offset = line.find('=');
-    if (offset == StringPiece::npos) {
-      error_str_ =
-          string("Line without equal sign: '") + line.ToString() + "'.";
-      return false;
-    }
-    StringPiece package(line, 0, offset);
-    StringPiece prefix(line, offset + 1, line.length() - offset - 1);
-    TrimWhitespace(&package);
-    TrimWhitespace(&prefix);
-    // Don't really worry about error checking the package/prefix for
-    // being valid.  Assume the file is validated when it is created/edited.
-    (*prefix_map_)[package.ToString()] = prefix.ToString();
+namespace {
+
+class ExpectedPrefixesCollector : public LineConsumer {
+ public:
+  ExpectedPrefixesCollector(std::map<string, string>* inout_package_to_prefix_map)
+      : prefix_map_(inout_package_to_prefix_map) {}
+
+  virtual bool ConsumeLine(const StringPiece& line, string* out_error);
+
+ private:
+  std::map<string, string>* prefix_map_;
+};
+
+bool ExpectedPrefixesCollector::ConsumeLine(
+    const StringPiece& line, string* out_error) {
+  int offset = line.find('=');
+  if (offset == StringPiece::npos) {
+    *out_error =
+        string("Expected prefixes file line without equal sign: '") +
+        line.ToString() + "'.";
+    return false;
   }
+  StringPiece package(line, 0, offset);
+  StringPiece prefix(line, offset + 1, line.length() - offset - 1);
+  StringPieceTrimWhitespace(&package);
+  StringPieceTrimWhitespace(&prefix);
+  // Don't really worry about error checking the package/prefix for
+  // being valid.  Assume the file is validated when it is created/edited.
+  (*prefix_map_)[package.ToString()] = prefix.ToString();
   return true;
 }
 
-bool LoadExpectedPackagePrefixes(map<string, string>* prefix_map,
-                                 string* out_expect_file_path,
+bool LoadExpectedPackagePrefixes(const Options &generation_options,
+                                 std::map<string, string>* prefix_map,
                                  string* out_error) {
-  const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES");
-  if (file_path == NULL) {
+  if (generation_options.expected_prefixes_path.empty()) {
     return true;
   }
 
-  int fd;
-  do {
-    fd = open(file_path, O_RDONLY);
-  } while (fd < 0 && errno == EINTR);
-  if (fd < 0) {
-    *out_error =
-        string(file_path) + ":0:0: error: Unable to open." + strerror(errno);
-    return false;
-  }
-  io::FileInputStream file_stream(fd);
-  file_stream.SetCloseOnDelete(true);
-  *out_expect_file_path = file_path;
-
-  Parser parser(prefix_map);
-  const void* buf;
-  int buf_len;
-  while (file_stream.Next(&buf, &buf_len)) {
-    if (buf_len == 0) {
-      continue;
-    }
-
-    if (!parser.ParseChunk(StringPiece(static_cast<const char*>(buf), buf_len))) {
-      *out_error = string(file_path) + ":" + SimpleItoa(parser.last_line()) +
-                   ":0: error: " + parser.error_str();
-      return false;
-    }
-  }
-  return parser.Finish();
+  ExpectedPrefixesCollector collector(prefix_map);
+  return ParseSimpleFile(
+      generation_options.expected_prefixes_path, &collector, out_error);
 }
 
-}  // namespace
-
-bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) {
+bool ValidateObjCClassPrefix(
+    const FileDescriptor* file,
+    const string& expected_prefixes_path,
+    const std::map<string, string>& expected_package_prefixes,
+    string* out_error) {
   const string prefix = file->options().objc_class_prefix();
   const string package = file->package();
 
   // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
   // error cases, so it seems to be ok to use as a back door for warnings.
 
-  // Load any expected package prefixes to validate against those.
-  map<string, string> expected_package_prefixes;
-  string expect_file_path;
-  if (!LoadExpectedPackagePrefixes(&expected_package_prefixes,
-                                   &expect_file_path, out_error)) {
-    // Any error, clear the entries that were read.
-    expected_package_prefixes.clear();
-  }
-
   // Check: Error - See if there was an expected prefix for the package and
   // report if it doesn't match (wrong or missing).
-  map<string, string>::iterator package_match =
+  std::map<string, string>::const_iterator package_match =
       expected_package_prefixes.find(package);
   if (package_match != expected_package_prefixes.end()) {
     // There was an entry, and...
@@ -957,8 +1052,9 @@
       return true;
     } else {
       // ...it didn't match!
-      *out_error = "protoc:0: error: Expected 'option objc_class_prefix = \"" +
-                   package_match->second + "\";' in '" + file->name() + "'";
+      *out_error = "error: Expected 'option objc_class_prefix = \"" +
+                   package_match->second + "\";' for package '" + package +
+                   "' in '" + file->name() + "'";
       if (prefix.length()) {
         *out_error += "; but found '" + prefix + "' instead";
       }
@@ -968,72 +1064,136 @@
   }
 
   // If there was no prefix option, we're done at this point.
-  if (prefix.length() == 0) {
+  if (prefix.empty()) {
     // No prefix, nothing left to check.
     return true;
   }
 
-  // Check: Error - Make sure the prefix wasn't expected for a different
-  // package (overlap is allowed, but it has to be listed as an expected
-  // overlap).
-  for (map<string, string>::iterator i = expected_package_prefixes.begin();
-       i != expected_package_prefixes.end(); ++i) {
-    if (i->second == prefix) {
-      *out_error =
-          "protoc:0: error: Found 'option objc_class_prefix = \"" + prefix +
-          "\";' in '" + file->name() +
-          "'; that prefix is already used for 'package " + i->first +
-          ";'. It can only be reused by listing it in the expected file (" +
-          expect_file_path + ").";
-      return false;  // Only report first usage of the prefix.
-    }
-  }
-
   // Check: Warning - Make sure the prefix is is a reasonable value according
   // to Apple's rules (the checks above implicitly whitelist anything that
   // doesn't meet these rules).
   if (!ascii_isupper(prefix[0])) {
-    cerr << endl
+    std::cerr << std::endl
          << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
          << prefix << "\";' in '" << file->name() << "';"
-         << " it should start with a capital letter." << endl;
-    cerr.flush();
+         << " it should start with a capital letter." << std::endl;
+    std::cerr.flush();
   }
   if (prefix.length() < 3) {
     // Apple reserves 2 character prefixes for themselves. They do use some
     // 3 character prefixes, but they haven't updated the rules/docs.
-    cerr << endl
+    std::cerr << std::endl
          << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
          << prefix << "\";' in '" << file->name() << "';"
          << " Apple recommends they should be at least 3 characters long."
-         << endl;
-    cerr.flush();
+         << std::endl;
+    std::cerr.flush();
+  }
+
+  // Look for any other package that uses the same prefix.
+  string other_package_for_prefix;
+  for (std::map<string, string>::const_iterator i = expected_package_prefixes.begin();
+       i != expected_package_prefixes.end(); ++i) {
+    if (i->second == prefix) {
+      other_package_for_prefix = i->first;
+      break;
+    }
+  }
+
+  // Check: Warning - If the file does not have a package, check whether
+  // the prefix declared is being used by another package or not.
+  if (package.empty()) {
+    // The file does not have a package and ...
+    if (other_package_for_prefix.empty()) {
+      // ... no other package has declared that prefix.
+      std::cerr << std::endl
+           << "protoc:0: warning: File '" << file->name() << "' has no "
+           << "package. Consider adding a new package to the proto and adding '"
+           << "new.package = " << prefix << "' to the expected prefixes file ("
+           << expected_prefixes_path << ")." << std::endl;
+      std::cerr.flush();
+    } else {
+      // ... another package has declared the same prefix.
+      std::cerr << std::endl
+           << "protoc:0: warning: File '" << file->name() << "' has no package "
+           << "and package '" << other_package_for_prefix << "' already uses '"
+           << prefix << "' as its prefix. Consider either adding a new package "
+           << "to the proto, or reusing one of the packages already using this "
+           << "prefix in the expected prefixes file ("
+           << expected_prefixes_path << ")." << std::endl;
+      std::cerr.flush();
+    }
+    return true;
+  }
+
+  // Check: Error - Make sure the prefix wasn't expected for a different
+  // package (overlap is allowed, but it has to be listed as an expected
+  // overlap).
+  if (!other_package_for_prefix.empty()) {
+    *out_error =
+        "error: Found 'option objc_class_prefix = \"" + prefix +
+        "\";' in '" + file->name() +
+        "'; that prefix is already used for 'package " +
+        other_package_for_prefix + ";'. It can only be reused by listing " +
+        "it in the expected file (" +
+        expected_prefixes_path + ").";
+    return false;  // Only report first usage of the prefix.
   }
 
   // Check: Warning - If the given package/prefix pair wasn't expected, issue a
   // warning issue a warning suggesting it gets added to the file.
   if (!expected_package_prefixes.empty()) {
-    cerr << endl
+    std::cerr << std::endl
          << "protoc:0: warning: Found unexpected 'option objc_class_prefix = \""
          << prefix << "\";' in '" << file->name() << "';"
          << " consider adding it to the expected prefixes file ("
-         << expect_file_path << ")." << endl;
-    cerr.flush();
+         << expected_prefixes_path << ")." << std::endl;
+    std::cerr.flush();
   }
 
   return true;
 }
 
+}  // namespace
+
+bool ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files,
+                               const Options& generation_options,
+                               string* out_error) {
+  // Load the expected package prefixes, if available, to validate against.
+  std::map<string, string> expected_package_prefixes;
+  if (!LoadExpectedPackagePrefixes(generation_options,
+                                   &expected_package_prefixes,
+                                   out_error)) {
+    return false;
+  }
+
+  for (int i = 0; i < files.size(); i++) {
+    bool is_valid =
+        ValidateObjCClassPrefix(files[i],
+                                generation_options.expected_prefixes_path,
+                                expected_package_prefixes,
+                                out_error);
+    if (!is_valid) {
+      return false;
+    }
+  }
+  return true;
+}
+
+TextFormatDecodeData::TextFormatDecodeData() { }
+
+TextFormatDecodeData::~TextFormatDecodeData() { }
+
 void TextFormatDecodeData::AddString(int32 key,
                                      const string& input_for_decode,
                                      const string& desired_output) {
-  for (vector<DataEntry>::const_iterator i = entries_.begin();
+  for (std::vector<DataEntry>::const_iterator i = entries_.begin();
        i != entries_.end(); ++i) {
     if (i->first == key) {
-      cerr << "error: duplicate key (" << key
+      std::cerr << "error: duplicate key (" << key
            << ") making TextFormat data, input: \"" << input_for_decode
-           << "\", desired: \"" << desired_output << "\"." << endl;
-      cerr.flush();
+           << "\", desired: \"" << desired_output << "\"." << std::endl;
+      std::cerr.flush();
       abort();
     }
   }
@@ -1044,14 +1204,14 @@
 }
 
 string TextFormatDecodeData::Data() const {
-  ostringstream data_stringstream;
+  std::ostringstream data_stringstream;
 
   if (num_entries() > 0) {
     io::OstreamOutputStream data_outputstream(&data_stringstream);
     io::CodedOutputStream output_stream(&data_outputstream);
 
     output_stream.WriteVarint32(num_entries());
-    for (vector<DataEntry>::const_iterator i = entries_.begin();
+    for (std::vector<DataEntry>::const_iterator i = entries_.begin();
          i != entries_.end(); ++i) {
       output_stream.WriteVarint32(i->first);
       output_stream.WriteString(i->second);
@@ -1185,18 +1345,18 @@
 string TextFormatDecodeData::DecodeDataForString(const string& input_for_decode,
                                                  const string& desired_output) {
   if ((input_for_decode.size() == 0) || (desired_output.size() == 0)) {
-    cerr << "error: got empty string for making TextFormat data, input: \""
+    std::cerr << "error: got empty string for making TextFormat data, input: \""
          << input_for_decode << "\", desired: \"" << desired_output << "\"."
-         << endl;
-    cerr.flush();
+         << std::endl;
+    std::cerr.flush();
     abort();
   }
   if ((input_for_decode.find('\0') != string::npos) ||
       (desired_output.find('\0') != string::npos)) {
-    cerr << "error: got a null char in a string for making TextFormat data,"
+    std::cerr << "error: got a null char in a string for making TextFormat data,"
          << " input: \"" << CEscape(input_for_decode) << "\", desired: \""
-         << CEscape(desired_output) << "\"." << endl;
-    cerr.flush();
+         << CEscape(desired_output) << "\"." << std::endl;
+    std::cerr.flush();
     abort();
   }
 
@@ -1232,6 +1392,296 @@
   return builder.Finish() + (char)'\0';
 }
 
+namespace {
+
+class Parser {
+ public:
+  Parser(LineConsumer* line_consumer)
+      : line_consumer_(line_consumer), line_(0) {}
+
+  // Parses a check of input, returning success/failure.
+  bool ParseChunk(StringPiece chunk);
+
+  // Should be called to finish parsing (after all input has been provided via
+  // ParseChunk()).  Returns success/failure.
+  bool Finish();
+
+  int last_line() const { return line_; }
+  string error_str() const { return error_str_; }
+
+ private:
+  bool ParseLoop();
+
+  LineConsumer* line_consumer_;
+  int line_;
+  string error_str_;
+  StringPiece p_;
+  string leftover_;
+};
+
+bool Parser::ParseChunk(StringPiece chunk) {
+  if (!leftover_.empty()) {
+    chunk.AppendToString(&leftover_);
+    p_ = StringPiece(leftover_);
+  } else {
+    p_ = chunk;
+  }
+  bool result = ParseLoop();
+  if (p_.empty()) {
+    leftover_.clear();
+  } else {
+    leftover_ = p_.ToString();
+  }
+  return result;
+}
+
+bool Parser::Finish() {
+  if (leftover_.empty()) {
+    return true;
+  }
+  // Force a newline onto the end to finish parsing.
+  leftover_ += "\n";
+  p_ = StringPiece(leftover_);
+  if (!ParseLoop()) {
+    return false;
+  }
+  return p_.empty();  // Everything used?
+}
+
+bool Parser::ParseLoop() {
+  StringPiece line;
+  while (ReadLine(&p_, &line)) {
+    ++line_;
+    RemoveComment(&line);
+    StringPieceTrimWhitespace(&line);
+    if (line.size() == 0) {
+      continue;  // Blank line.
+    }
+    if (!line_consumer_->ConsumeLine(line, &error_str_)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+}  // namespace
+
+LineConsumer::LineConsumer() {}
+
+LineConsumer::~LineConsumer() {}
+
+bool ParseSimpleFile(
+    const string& path, LineConsumer* line_consumer, string* out_error) {
+  int fd;
+  do {
+    fd = posix::open(path.c_str(), O_RDONLY);
+  } while (fd < 0 && errno == EINTR);
+  if (fd < 0) {
+    *out_error =
+        string("error: Unable to open \"") + path + "\", " + strerror(errno);
+    return false;
+  }
+  io::FileInputStream file_stream(fd);
+  file_stream.SetCloseOnDelete(true);
+
+  Parser parser(line_consumer);
+  const void* buf;
+  int buf_len;
+  while (file_stream.Next(&buf, &buf_len)) {
+    if (buf_len == 0) {
+      continue;
+    }
+
+    if (!parser.ParseChunk(StringPiece(static_cast<const char*>(buf), buf_len))) {
+      *out_error =
+          string("error: ") + path +
+          " Line " + SimpleItoa(parser.last_line()) + ", " + parser.error_str();
+      return false;
+    }
+  }
+  return parser.Finish();
+}
+
+ImportWriter::ImportWriter(
+  const string& generate_for_named_framework,
+  const string& named_framework_to_proto_path_mappings_path,
+  bool include_wkt_imports)
+    : generate_for_named_framework_(generate_for_named_framework),
+      named_framework_to_proto_path_mappings_path_(
+          named_framework_to_proto_path_mappings_path),
+      include_wkt_imports_(include_wkt_imports),
+      need_to_parse_mapping_file_(true) {
+}
+
+ImportWriter::~ImportWriter() {}
+
+void ImportWriter::AddFile(const FileDescriptor* file,
+                           const string& header_extension) {
+  const string file_path(FilePath(file));
+
+  if (IsProtobufLibraryBundledProtoFile(file)) {
+    // The imports of the WKTs are only needed within the library itself,
+    // in other cases, they get skipped because the generated code already
+    // import GPBProtocolBuffers.h and hence proves them.
+    if (include_wkt_imports_) {
+      protobuf_framework_imports_.push_back(
+          FilePathBasename(file) + header_extension);
+      protobuf_non_framework_imports_.push_back(file_path + header_extension);
+    }
+    return;
+  }
+
+  // Lazy parse any mappings.
+  if (need_to_parse_mapping_file_) {
+    ParseFrameworkMappings();
+  }
+
+  std::map<string, string>::iterator proto_lookup =
+      proto_file_to_framework_name_.find(file->name());
+  if (proto_lookup != proto_file_to_framework_name_.end()) {
+    other_framework_imports_.push_back(
+        proto_lookup->second + "/" +
+        FilePathBasename(file) + header_extension);
+    return;
+  }
+
+  if (!generate_for_named_framework_.empty()) {
+    other_framework_imports_.push_back(
+        generate_for_named_framework_ + "/" +
+        FilePathBasename(file) + header_extension);
+    return;
+  }
+
+  other_imports_.push_back(file_path + header_extension);
+}
+
+void ImportWriter::Print(io::Printer* printer) const {
+  assert(protobuf_non_framework_imports_.size() ==
+         protobuf_framework_imports_.size());
+
+  bool add_blank_line = false;
+
+  if (protobuf_framework_imports_.size() > 0) {
+    const string framework_name(ProtobufLibraryFrameworkName);
+    const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name));
+
+    printer->Print(
+        "#if $cpp_symbol$\n",
+        "cpp_symbol", cpp_symbol);
+    for (std::vector<string>::const_iterator iter = protobuf_framework_imports_.begin();
+         iter != protobuf_framework_imports_.end(); ++iter) {
+      printer->Print(
+          " #import <$framework_name$/$header$>\n",
+          "framework_name", framework_name,
+          "header", *iter);
+    }
+    printer->Print(
+        "#else\n");
+    for (std::vector<string>::const_iterator iter = protobuf_non_framework_imports_.begin();
+         iter != protobuf_non_framework_imports_.end(); ++iter) {
+      printer->Print(
+          " #import \"$header$\"\n",
+          "header", *iter);
+    }
+    printer->Print(
+        "#endif\n");
+
+    add_blank_line = true;
+  }
+
+  if (other_framework_imports_.size() > 0) {
+    if (add_blank_line) {
+      printer->Print("\n");
+    }
+
+    for (std::vector<string>::const_iterator iter = other_framework_imports_.begin();
+         iter != other_framework_imports_.end(); ++iter) {
+      printer->Print(
+          "#import <$header$>\n",
+          "header", *iter);
+    }
+
+    add_blank_line = true;
+  }
+
+  if (other_imports_.size() > 0) {
+    if (add_blank_line) {
+      printer->Print("\n");
+    }
+
+    for (std::vector<string>::const_iterator iter = other_imports_.begin();
+         iter != other_imports_.end(); ++iter) {
+      printer->Print(
+          "#import \"$header$\"\n",
+          "header", *iter);
+    }
+  }
+}
+
+void ImportWriter::ParseFrameworkMappings() {
+  need_to_parse_mapping_file_ = false;
+  if (named_framework_to_proto_path_mappings_path_.empty()) {
+    return;  // Nothing to do.
+  }
+
+  ProtoFrameworkCollector collector(&proto_file_to_framework_name_);
+  string parse_error;
+  if (!ParseSimpleFile(named_framework_to_proto_path_mappings_path_,
+                       &collector, &parse_error)) {
+    std::cerr << "error parsing " << named_framework_to_proto_path_mappings_path_
+         << " : " << parse_error << std::endl;
+    std::cerr.flush();
+  }
+}
+
+bool ImportWriter::ProtoFrameworkCollector::ConsumeLine(
+    const StringPiece& line, string* out_error) {
+  int offset = line.find(':');
+  if (offset == StringPiece::npos) {
+    *out_error =
+        string("Framework/proto file mapping line without colon sign: '") +
+        line.ToString() + "'.";
+    return false;
+  }
+  StringPiece framework_name(line, 0, offset);
+  StringPiece proto_file_list(line, offset + 1, line.length() - offset - 1);
+  StringPieceTrimWhitespace(&framework_name);
+
+  int start = 0;
+  while (start < proto_file_list.length()) {
+    offset = proto_file_list.find(',', start);
+    if (offset == StringPiece::npos) {
+      offset = proto_file_list.length();
+    }
+
+    StringPiece proto_file(proto_file_list, start, offset - start);
+    StringPieceTrimWhitespace(&proto_file);
+    if (proto_file.size() != 0) {
+      std::map<string, string>::iterator existing_entry =
+          map_->find(proto_file.ToString());
+      if (existing_entry != map_->end()) {
+        std::cerr << "warning: duplicate proto file reference, replacing framework entry for '"
+             << proto_file.ToString() << "' with '" << framework_name.ToString()
+             << "' (was '" << existing_entry->second << "')." << std::endl;
+        std::cerr.flush();
+      }
+
+      if (proto_file.find(' ') != StringPiece::npos) {
+        std::cerr << "note: framework mapping file had a proto file with a space in, hopefully that isn't a missing comma: '"
+             << proto_file.ToString() << "'" << std::endl;
+        std::cerr.flush();
+      }
+
+      (*map_)[proto_file.ToString()] = framework_name.ToString();
+    }
+
+    start = offset + 1;
+  }
+
+  return true;
+}
+
+
 }  // namespace objectivec
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
index 8574486..8999aa5 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
@@ -28,6 +28,8 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+// Helper functions for generating ObjectiveC code.
+
 #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
 #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
 
@@ -42,58 +44,75 @@
 namespace compiler {
 namespace objectivec {
 
+// Generator options (see objectivec_generator.cc for a description of each):
+struct Options {
+  Options();
+  string expected_prefixes_path;
+  string generate_for_named_framework;
+  string named_framework_to_proto_path_mappings_path;
+};
+
+// Escape C++ trigraphs by escaping question marks to "\?".
+string LIBPROTOC_EXPORT EscapeTrigraphs(const string& to_escape);
+
 // Strips ".proto" or ".protodevel" from the end of a filename.
-string StripProto(const string& filename);
+string LIBPROTOC_EXPORT StripProto(const string& filename);
+
+// Remove white space from either end of a StringPiece.
+void LIBPROTOC_EXPORT StringPieceTrimWhitespace(StringPiece* input);
 
 // Returns true if the name requires a ns_returns_not_retained attribute applied
 // to it.
-bool IsRetainedName(const string& name);
+bool LIBPROTOC_EXPORT IsRetainedName(const string& name);
 
 // Returns true if the name starts with "init" and will need to have special
 // handling under ARC.
-bool IsInitName(const string& name);
+bool LIBPROTOC_EXPORT IsInitName(const string& name);
 
-// Gets the name of the file we're going to generate (sans the .pb.h
-// extension).  This does not include the path to that file.
-string FileName(const FileDescriptor* file);
+// Gets the objc_class_prefix.
+string LIBPROTOC_EXPORT FileClassPrefix(const FileDescriptor* file);
 
 // Gets the path of the file we're going to generate (sans the .pb.h
 // extension).  The path will be dependent on the objectivec package
 // declared in the proto package.
-string FilePath(const FileDescriptor* file);
+string LIBPROTOC_EXPORT FilePath(const FileDescriptor* file);
+
+// Just like FilePath(), but without the directory part.
+string LIBPROTOC_EXPORT FilePathBasename(const FileDescriptor* file);
 
 // Gets the name of the root class we'll generate in the file.  This class
 // is not meant for external consumption, but instead contains helpers that
 // the rest of the classes need
-string FileClassName(const FileDescriptor* file);
+string LIBPROTOC_EXPORT FileClassName(const FileDescriptor* file);
 
 // These return the fully-qualified class name corresponding to the given
 // descriptor.
-string ClassName(const Descriptor* descriptor);
-string EnumName(const EnumDescriptor* descriptor);
+string LIBPROTOC_EXPORT ClassName(const Descriptor* descriptor);
+string LIBPROTOC_EXPORT ClassName(const Descriptor* descriptor, string* out_suffix_added);
+string LIBPROTOC_EXPORT EnumName(const EnumDescriptor* descriptor);
 
 // Returns the fully-qualified name of the enum value corresponding to the
 // the descriptor.
-string EnumValueName(const EnumValueDescriptor* descriptor);
+string LIBPROTOC_EXPORT EnumValueName(const EnumValueDescriptor* descriptor);
 
 // Returns the name of the enum value corresponding to the descriptor.
-string EnumValueShortName(const EnumValueDescriptor* descriptor);
+string LIBPROTOC_EXPORT EnumValueShortName(const EnumValueDescriptor* descriptor);
 
 // Reverse what an enum does.
-string UnCamelCaseEnumShortName(const string& name);
+string LIBPROTOC_EXPORT UnCamelCaseEnumShortName(const string& name);
 
 // Returns the name to use for the extension (used as the method off the file's
 // Root class).
-string ExtensionMethodName(const FieldDescriptor* descriptor);
+string LIBPROTOC_EXPORT ExtensionMethodName(const FieldDescriptor* descriptor);
 
 // Returns the transformed field name.
-string FieldName(const FieldDescriptor* field);
-string FieldNameCapitalized(const FieldDescriptor* field);
+string LIBPROTOC_EXPORT FieldName(const FieldDescriptor* field);
+string LIBPROTOC_EXPORT FieldNameCapitalized(const FieldDescriptor* field);
 
 // Returns the transformed oneof name.
-string OneofEnumName(const OneofDescriptor* descriptor);
-string OneofName(const OneofDescriptor* descriptor);
-string OneofNameCapitalized(const OneofDescriptor* descriptor);
+string LIBPROTOC_EXPORT OneofEnumName(const OneofDescriptor* descriptor);
+string LIBPROTOC_EXPORT OneofName(const OneofDescriptor* descriptor);
+string LIBPROTOC_EXPORT OneofNameCapitalized(const OneofDescriptor* descriptor);
 
 inline bool HasFieldPresence(const FileDescriptor* file) {
   return file->syntax() != FileDescriptor::SYNTAX_PROTO3;
@@ -108,7 +127,7 @@
 }
 
 // Reverse of the above.
-string UnCamelCaseFieldName(const string& name, const FieldDescriptor* field);
+string LIBPROTOC_EXPORT UnCamelCaseFieldName(const string& name, const FieldDescriptor* field);
 
 enum ObjectiveCType {
   OBJECTIVECTYPE_INT32,
@@ -124,34 +143,83 @@
   OBJECTIVECTYPE_MESSAGE
 };
 
-string GetCapitalizedType(const FieldDescriptor* field);
+enum FlagType {
+  FLAGTYPE_DESCRIPTOR_INITIALIZATION,
+  FLAGTYPE_EXTENSION,
+  FLAGTYPE_FIELD
+};
 
-ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type);
+template<class TDescriptor>
+string GetOptionalDeprecatedAttribute(
+    const TDescriptor* descriptor,
+    const FileDescriptor* file = NULL,
+    bool preSpace = true, bool postNewline = false) {
+  bool isDeprecated = descriptor->options().deprecated();
+  // The file is only passed when checking Messages & Enums, so those types
+  // get tagged. At the moment, it doesn't seem to make sense to tag every
+  // field or enum value with when the file is deprecated.
+  if (!isDeprecated && file) {
+    isDeprecated = file->options().deprecated();
+  }
+  if (isDeprecated) {
+    string result = "DEPRECATED_ATTRIBUTE";
+    if (preSpace) {
+      result.insert(0, " ");
+    }
+    if (postNewline) {
+      result.append("\n");
+    }
+    return result;
+  } else {
+    return "";
+  }
+}
+
+string LIBPROTOC_EXPORT GetCapitalizedType(const FieldDescriptor* field);
+
+ObjectiveCType LIBPROTOC_EXPORT GetObjectiveCType(FieldDescriptor::Type field_type);
 
 inline ObjectiveCType GetObjectiveCType(const FieldDescriptor* field) {
   return GetObjectiveCType(field->type());
 }
 
-bool IsPrimitiveType(const FieldDescriptor* field);
-bool IsReferenceType(const FieldDescriptor* field);
+bool LIBPROTOC_EXPORT IsPrimitiveType(const FieldDescriptor* field);
+bool LIBPROTOC_EXPORT IsReferenceType(const FieldDescriptor* field);
 
-string GPBGenericValueFieldName(const FieldDescriptor* field);
-string DefaultValue(const FieldDescriptor* field);
+string LIBPROTOC_EXPORT GPBGenericValueFieldName(const FieldDescriptor* field);
+string LIBPROTOC_EXPORT DefaultValue(const FieldDescriptor* field);
+bool LIBPROTOC_EXPORT HasNonZeroDefaultValue(const FieldDescriptor* field);
 
-string BuildFlagsString(const vector<string>& strings);
+string LIBPROTOC_EXPORT BuildFlagsString(const FlagType type, const std::vector<string>& strings);
 
-string BuildCommentsString(const SourceLocation& location);
+// Builds HeaderDoc/appledoc style comments out of the comments in the .proto
+// file.
+string LIBPROTOC_EXPORT BuildCommentsString(const SourceLocation& location,
+                           bool prefer_single_line);
 
-// Checks the prefix for a given file and outputs any warnings needed, if
-// there are flat out errors, then out_error is filled in and the result is
-// false.
-bool ValidateObjCClassPrefix(const FileDescriptor* file, string *out_error);
+// The name the commonly used by the library when built as a framework.
+// This lines up to the name used in the CocoaPod.
+extern LIBPROTOC_EXPORT const char* const ProtobufLibraryFrameworkName;
+// Returns the CPP symbol name to use as the gate for framework style imports
+// for the given framework name to use.
+string LIBPROTOC_EXPORT ProtobufFrameworkImportSymbol(const string& framework_name);
+
+// Checks if the file is one of the proto's bundled with the library.
+bool LIBPROTOC_EXPORT IsProtobufLibraryBundledProtoFile(const FileDescriptor* file);
+
+// Checks the prefix for the given files and outputs any warnings as needed. If
+// there are flat out errors, then out_error is filled in with the first error
+// and the result is false.
+bool LIBPROTOC_EXPORT ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files,
+                               const Options& generation_options,
+                               string* out_error);
 
 // Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform
 // the input into the expected output.
 class LIBPROTOC_EXPORT TextFormatDecodeData {
  public:
-  TextFormatDecodeData() {}
+  TextFormatDecodeData();
+  ~TextFormatDecodeData();
 
   void AddString(int32 key, const string& input_for_decode,
                  const string& desired_output);
@@ -165,7 +233,57 @@
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextFormatDecodeData);
 
   typedef std::pair<int32, string> DataEntry;
-  vector<DataEntry> entries_;
+  std::vector<DataEntry> entries_;
+};
+
+// Helper for parsing simple files.
+class LIBPROTOC_EXPORT LineConsumer {
+ public:
+  LineConsumer();
+  virtual ~LineConsumer();
+  virtual bool ConsumeLine(const StringPiece& line, string* out_error) = 0;
+};
+
+bool LIBPROTOC_EXPORT ParseSimpleFile(
+    const string& path, LineConsumer* line_consumer, string* out_error);
+
+
+// Helper class for parsing framework import mappings and generating
+// import statements.
+class LIBPROTOC_EXPORT ImportWriter {
+ public:
+  ImportWriter(const string& generate_for_named_framework,
+               const string& named_framework_to_proto_path_mappings_path,
+               bool include_wkt_imports);
+  ~ImportWriter();
+
+  void AddFile(const FileDescriptor* file, const string& header_extension);
+  void Print(io::Printer *printer) const;
+
+ private:
+  class ProtoFrameworkCollector : public LineConsumer {
+   public:
+    ProtoFrameworkCollector(std::map<string, string>* inout_proto_file_to_framework_name)
+        : map_(inout_proto_file_to_framework_name) {}
+
+    virtual bool ConsumeLine(const StringPiece& line, string* out_error);
+
+   private:
+    std::map<string, string>* map_;
+  };
+
+  void ParseFrameworkMappings();
+
+  const string generate_for_named_framework_;
+  const string named_framework_to_proto_path_mappings_path_;
+  const bool include_wkt_imports_;
+  std::map<string, string> proto_file_to_framework_name_;
+  bool need_to_parse_mapping_file_;
+
+  std::vector<string> protobuf_framework_imports_;
+  std::vector<string> protobuf_non_framework_imports_;
+  std::vector<string> other_framework_imports_;
+  std::vector<string> other_imports_;
 };
 
 }  // namespace objectivec
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
index 2987f3d..bcaf570 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
@@ -84,13 +84,14 @@
 
 }  // namespace
 
-MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor)
-    : RepeatedFieldGenerator(descriptor) {
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
+                                     const Options& options)
+    : RepeatedFieldGenerator(descriptor, options) {
   const FieldDescriptor* key_descriptor =
       descriptor->message_type()->FindFieldByName("key");
   const FieldDescriptor* value_descriptor =
       descriptor->message_type()->FindFieldByName("value");
-  value_field_generator_.reset(FieldGenerator::Make(value_descriptor));
+  value_field_generator_.reset(FieldGenerator::Make(value_descriptor, options));
 
   // Pull over some variables_ from the value.
   variables_["field_type"] = value_field_generator_->variable("field_type");
@@ -114,49 +115,65 @@
   if (value_field_flags.find("GPBFieldHasEnumDescriptor") != string::npos) {
     field_flags.push_back("GPBFieldHasEnumDescriptor");
   }
-  variables_["fieldflags"] = BuildFlagsString(field_flags);
+  variables_["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags);
 
   ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
-  if ((GetObjectiveCType(key_descriptor) == OBJECTIVECTYPE_STRING) &&
+  const bool value_is_object_type =
       ((value_objc_type == OBJECTIVECTYPE_STRING) ||
        (value_objc_type == OBJECTIVECTYPE_DATA) ||
-       (value_objc_type == OBJECTIVECTYPE_MESSAGE))) {
+       (value_objc_type == OBJECTIVECTYPE_MESSAGE));
+  if ((GetObjectiveCType(key_descriptor) == OBJECTIVECTYPE_STRING) &&
+      value_is_object_type) {
     variables_["array_storage_type"] = "NSMutableDictionary";
+    variables_["array_property_type"] =
+        "NSMutableDictionary<NSString*, " +
+        value_field_generator_->variable("storage_type") + "*>";
   } else {
-    string base_name = MapEntryTypeName(key_descriptor, true);
-    base_name += MapEntryTypeName(value_descriptor, false);
-    base_name += "Dictionary";
-    variables_["array_storage_type"] = "GPB" + base_name;
+    string class_name("GPB");
+    class_name += MapEntryTypeName(key_descriptor, true);
+    class_name += MapEntryTypeName(value_descriptor, false);
+    class_name += "Dictionary";
+    variables_["array_storage_type"] = class_name;
+    if (value_is_object_type) {
+      variables_["array_property_type"] =
+          class_name + "<" +
+          value_field_generator_->variable("storage_type") + "*>";
+    }
   }
+
+  variables_["dataTypeSpecific_name"] =
+      value_field_generator_->variable("dataTypeSpecific_name");
+  variables_["dataTypeSpecific_value"] =
+      value_field_generator_->variable("dataTypeSpecific_value");
 }
 
 MapFieldGenerator::~MapFieldGenerator() {}
 
 void MapFieldGenerator::FinishInitialization(void) {
   RepeatedFieldGenerator::FinishInitialization();
-  // Use the array_comment suport in RepeatedFieldGenerator to output what the
+  // Use the array_comment support in RepeatedFieldGenerator to output what the
   // values in the map are.
   const FieldDescriptor* value_descriptor =
       descriptor_->message_type()->FindFieldByName("value");
-  ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
-  if ((value_objc_type == OBJECTIVECTYPE_MESSAGE) ||
-      (value_objc_type == OBJECTIVECTYPE_DATA) ||
-      (value_objc_type == OBJECTIVECTYPE_STRING) ||
-      (value_objc_type == OBJECTIVECTYPE_ENUM)) {
+  if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_ENUM) {
     variables_["array_comment"] =
         "// |" + variables_["name"] + "| values are |" + value_field_generator_->variable("storage_type") + "|\n";
-  } else {
-    variables_["array_comment"] = "";
   }
 }
 
-void MapFieldGenerator::GenerateFieldDescriptionTypeSpecific(
-    io::Printer* printer) const {
-  // Relay it to the value generator to provide enum validator, message
-  // class, etc.
-  value_field_generator_->GenerateFieldDescriptionTypeSpecific(printer);
+void MapFieldGenerator::DetermineForwardDeclarations(
+    std::set<string>* fwd_decls) const {
+  RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls);
+  const FieldDescriptor* value_descriptor =
+      descriptor_->message_type()->FindFieldByName("value");
+  if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE) {
+    const string& value_storage_type =
+        value_field_generator_->variable("storage_type");
+    fwd_decls->insert("@class " + value_storage_type);
+  }
 }
 
+
 }  // namespace objectivec
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
index 173541f..dc7beac 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
@@ -41,18 +41,21 @@
 namespace objectivec {
 
 class MapFieldGenerator : public RepeatedFieldGenerator {
-  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
 
  public:
   virtual void FinishInitialization(void);
-  virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
 
  protected:
-  explicit MapFieldGenerator(const FieldDescriptor* descriptor);
+  MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
   virtual ~MapFieldGenerator();
 
+  virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
+
  private:
-  scoped_ptr<FieldGenerator> value_field_generator_;
+  std::unique_ptr<FieldGenerator> value_field_generator_;
+
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
 };
 
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
index 32671d4..8388885 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
@@ -66,11 +66,12 @@
   // The first item in the object structure is our uint32[] for has bits.
   // We then want to order things to make the instances as small as
   // possible. So we follow the has bits with:
-  //   1. Bools (1 byte)
-  //   2. Anything always 4 bytes - float, *32, enums
-  //   3. Anything that is always a pointer (they will be 8 bytes on 64 bit
+  //   1. Anything always 4 bytes - float, *32, enums
+  //   2. Anything that is always a pointer (they will be 8 bytes on 64 bit
   //      builds and 4 bytes on 32bit builds.
-  //   4. Anything always 8 bytes - double, *64
+  //   3. Anything always 8 bytes - double, *64
+  //
+  // NOTE: Bools aren't listed, they were stored in the has bits.
   //
   // Why? Using 64bit builds as an example, this means worse case, we have
   // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes
@@ -115,9 +116,9 @@
     case FieldDescriptor::TYPE_ENUM:
       return 2;
 
-    // 1 byte.
+    // 0 bytes. Stored in the has bits.
     case FieldDescriptor::TYPE_BOOL:
-      return 1;
+      return 99;  // End of the list (doesn't really matter).
   }
 
   // Some compilers report reaching end of function even though all cases of
@@ -155,7 +156,7 @@
   for (int i = 0; i < descriptor->field_count(); i++) {
     fields[i] = descriptor->field(i);
   }
-  sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber());
+  std::sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber());
   return fields;
 }
 
@@ -167,18 +168,22 @@
   for (int i = 0; i < descriptor->field_count(); i++) {
     fields[i] = descriptor->field(i);
   }
-  sort(fields, fields + descriptor->field_count(),
+  std::sort(fields, fields + descriptor->field_count(),
        FieldOrderingByStorageSize());
   return fields;
 }
 }  // namespace
 
 MessageGenerator::MessageGenerator(const string& root_classname,
-                                   const Descriptor* descriptor)
+                                   const Descriptor* descriptor,
+                                   const Options& options)
     : root_classname_(root_classname),
       descriptor_(descriptor),
-      field_generators_(descriptor),
-      class_name_(ClassName(descriptor_)) {
+      field_generators_(descriptor, options),
+      class_name_(ClassName(descriptor_)),
+      deprecated_attribute_(
+          GetOptionalDeprecatedAttribute(descriptor, descriptor->file(), false, true)) {
+
   for (int i = 0; i < descriptor_->extension_count(); i++) {
     extension_generators_.push_back(
         new ExtensionGenerator(class_name_, descriptor_->extension(i)));
@@ -196,7 +201,9 @@
 
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     MessageGenerator* generator =
-        new MessageGenerator(root_classname_, descriptor_->nested_type(i));
+        new MessageGenerator(root_classname_,
+                             descriptor_->nested_type(i),
+                             options);
     nested_message_generators_.push_back(generator);
   }
 }
@@ -213,47 +220,58 @@
 
 void MessageGenerator::GenerateStaticVariablesInitialization(
     io::Printer* printer) {
-  for (vector<ExtensionGenerator*>::iterator iter =
+  for (std::vector<ExtensionGenerator*>::iterator iter =
            extension_generators_.begin();
        iter != extension_generators_.end(); ++iter) {
     (*iter)->GenerateStaticVariablesInitialization(printer);
   }
 
-  for (vector<MessageGenerator*>::iterator iter =
+  for (std::vector<MessageGenerator*>::iterator iter =
            nested_message_generators_.begin();
        iter != nested_message_generators_.end(); ++iter) {
     (*iter)->GenerateStaticVariablesInitialization(printer);
   }
 }
 
-void MessageGenerator::DetermineForwardDeclarations(set<string>* fwd_decls) {
+void MessageGenerator::DetermineForwardDeclarations(std::set<string>* fwd_decls) {
   if (!IsMapEntryMessage(descriptor_)) {
     for (int i = 0; i < descriptor_->field_count(); i++) {
       const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
-      // If it is a the field is repeated, the type will be and *Array, and we
-      // don't need any forward decl.
-      if (fieldDescriptor->is_repeated()) {
-        continue;
-      }
       field_generators_.get(fieldDescriptor)
           .DetermineForwardDeclarations(fwd_decls);
     }
   }
 
-  for (vector<MessageGenerator*>::iterator iter =
+  for (std::vector<MessageGenerator*>::iterator iter =
            nested_message_generators_.begin();
        iter != nested_message_generators_.end(); ++iter) {
     (*iter)->DetermineForwardDeclarations(fwd_decls);
   }
 }
 
+bool MessageGenerator::IncludesOneOfDefinition() const {
+  if (!oneof_generators_.empty()) {
+    return true;
+  }
+
+  for (std::vector<MessageGenerator*>::const_iterator iter =
+           nested_message_generators_.begin();
+       iter != nested_message_generators_.end(); ++iter) {
+    if ((*iter)->IncludesOneOfDefinition()) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 void MessageGenerator::GenerateEnumHeader(io::Printer* printer) {
-  for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
+  for (std::vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
        iter != enum_generators_.end(); ++iter) {
     (*iter)->GenerateHeader(printer);
   }
 
-  for (vector<MessageGenerator*>::iterator iter =
+  for (std::vector<MessageGenerator*>::iterator iter =
            nested_message_generators_.begin();
        iter != nested_message_generators_.end(); ++iter) {
     (*iter)->GenerateEnumHeader(printer);
@@ -262,13 +280,13 @@
 
 void MessageGenerator::GenerateExtensionRegistrationSource(
     io::Printer* printer) {
-  for (vector<ExtensionGenerator*>::iterator iter =
+  for (std::vector<ExtensionGenerator*>::iterator iter =
            extension_generators_.begin();
        iter != extension_generators_.end(); ++iter) {
     (*iter)->GenerateRegistrationSource(printer);
   }
 
-  for (vector<MessageGenerator*>::iterator iter =
+  for (std::vector<MessageGenerator*>::iterator iter =
            nested_message_generators_.begin();
        iter != nested_message_generators_.end(); ++iter) {
     (*iter)->GenerateExtensionRegistrationSource(printer);
@@ -278,7 +296,7 @@
 void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
   // This a a map entry message, just recurse and do nothing directly.
   if (IsMapEntryMessage(descriptor_)) {
-    for (vector<MessageGenerator*>::iterator iter =
+    for (std::vector<MessageGenerator*>::iterator iter =
              nested_message_generators_.begin();
          iter != nested_message_generators_.end(); ++iter) {
       (*iter)->GenerateMessageHeader(printer);
@@ -292,7 +310,7 @@
       "classname", class_name_);
 
   if (descriptor_->field_count()) {
-    scoped_array<const FieldDescriptor*> sorted_fields(
+    std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
         SortFieldsByNumber(descriptor_));
 
     printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n",
@@ -308,7 +326,7 @@
     printer->Print("};\n\n");
   }
 
-  for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+  for (std::vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
        iter != oneof_generators_.end(); ++iter) {
     (*iter)->GenerateCaseEnum(printer);
   }
@@ -316,17 +334,18 @@
   string message_comments;
   SourceLocation location;
   if (descriptor_->GetSourceLocation(&location)) {
-    message_comments = BuildCommentsString(location);
+    message_comments = BuildCommentsString(location, false);
   } else {
     message_comments = "";
   }
 
   printer->Print(
-      "$comments$@interface $classname$ : GPBMessage\n\n",
+      "$comments$$deprecated_attribute$@interface $classname$ : GPBMessage\n\n",
       "classname", class_name_,
+      "deprecated_attribute", deprecated_attribute_,
       "comments", message_comments);
 
-  vector<char> seen_oneofs(descriptor_->oneof_decl_count(), 0);
+  std::vector<char> seen_oneofs(descriptor_->oneof_decl_count(), 0);
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
     if (field->containing_oneof() != NULL) {
@@ -348,7 +367,7 @@
   }
 
   if (!oneof_generators_.empty()) {
-    for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+    for (std::vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
          iter != oneof_generators_.end(); ++iter) {
       (*iter)->GenerateClearFunctionDeclaration(printer);
     }
@@ -358,7 +377,7 @@
   if (descriptor_->extension_count() > 0) {
     printer->Print("@interface $classname$ (DynamicMethods)\n\n",
                    "classname", class_name_);
-    for (vector<ExtensionGenerator*>::iterator iter =
+    for (std::vector<ExtensionGenerator*>::iterator iter =
              extension_generators_.begin();
          iter != extension_generators_.end(); ++iter) {
       (*iter)->GenerateMembersHeader(printer);
@@ -366,7 +385,7 @@
     printer->Print("@end\n\n");
   }
 
-  for (vector<MessageGenerator*>::iterator iter =
+  for (std::vector<MessageGenerator*>::iterator iter =
            nested_message_generators_.begin();
        iter != nested_message_generators_.end(); ++iter) {
     (*iter)->GenerateMessageHeader(printer);
@@ -380,10 +399,18 @@
         "\n",
         "classname", class_name_);
 
+    if (!deprecated_attribute_.empty()) {
+      // No warnings when compiling the impl of this deprecated class.
+      printer->Print(
+          "#pragma clang diagnostic push\n"
+          "#pragma clang diagnostic ignored \"-Wdeprecated-implementations\"\n"
+          "\n");
+    }
+
     printer->Print("@implementation $classname$\n\n",
                    "classname", class_name_);
 
-    for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+    for (std::vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
          iter != oneof_generators_.end(); ++iter) {
       (*iter)->GeneratePropertyImplementation(printer);
     }
@@ -393,45 +420,41 @@
           .GeneratePropertyImplementation(printer);
     }
 
-    scoped_array<const FieldDescriptor*> sorted_fields(
+    std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
         SortFieldsByNumber(descriptor_));
-    scoped_array<const FieldDescriptor*> size_order_fields(
+    std::unique_ptr<const FieldDescriptor*[]> size_order_fields(
         SortFieldsByStorageSize(descriptor_));
 
-    vector<const Descriptor::ExtensionRange*> sorted_extensions;
+    std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
     for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
       sorted_extensions.push_back(descriptor_->extension_range(i));
     }
 
-    sort(sorted_extensions.begin(), sorted_extensions.end(),
+    std::sort(sorted_extensions.begin(), sorted_extensions.end(),
          ExtensionRangeOrdering());
 
-    // TODO(thomasvl): Finish optimizing has bit. The current behavior is as
-    // follows:
-    // 1. objectivec_field.cc's SetCommonFieldVariables() defaults the has_index
-    //    to the field's index in the list of fields.
-    // 2. RepeatedFieldGenerator::RepeatedFieldGenerator() sets has_index to
-    //    GPBNoHasBit because repeated fields & map<> fields don't use the has
-    //    bit.
-    // 3. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
-    //    index that groups all the elements on of the oneof.
-    // So in has_storage, we need enough bits for the single fields that aren't
-    // in any oneof, and then one int32 for each oneof (to store the field
-    // number).  So we could save a little space by not using the field's index
-    // and instead make a second pass only assigning indexes for the fields
-    // that would need it.  The only savings would come when messages have over
-    // a multiple of 32 fields with some number being repeated or in oneofs to
-    // drop the count below that 32 multiple; so it hasn't seemed worth doing
-    // at the moment.
-    size_t num_has_bits = descriptor_->field_count();
+    // Assign has bits:
+    // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing
+    //    who needs has bits and assigning them.
+    // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
+    //    index that groups all the elements in the oneof.
+    size_t num_has_bits = field_generators_.CalculateHasBits();
     size_t sizeof_has_storage = (num_has_bits + 31) / 32;
+    if (sizeof_has_storage == 0) {
+      // In the case where no field needs has bits, don't let the _has_storage_
+      // end up as zero length (zero length arrays are sort of a grey area
+      // since it has to be at the start of the struct). This also ensures a
+      // field with only oneofs keeps the required negative indices they need.
+      sizeof_has_storage = 1;
+    }
     // Tell all the fields the oneof base.
-    for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+    for (std::vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
          iter != oneof_generators_.end(); ++iter) {
       (*iter)->SetOneofIndexBase(sizeof_has_storage);
     }
     field_generators_.SetOneofIndexBase(sizeof_has_storage);
-    // Add an int32 for each oneof to store which is set.
+    // sizeof_has_storage needs enough bits for the single fields that aren't in
+    // any oneof, and then one int32 for each oneof (to store the field number).
     sizeof_has_storage += descriptor_->oneof_decl_count();
 
     printer->Print(
@@ -458,47 +481,26 @@
         "  static GPBDescriptor *descriptor = nil;\n"
         "  if (!descriptor) {\n");
 
-    bool has_oneofs = oneof_generators_.size();
-    if (has_oneofs) {
-      printer->Print(
-          "    static GPBMessageOneofDescription oneofs[] = {\n");
-      printer->Indent();
-      printer->Indent();
-      printer->Indent();
-      for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
-           iter != oneof_generators_.end(); ++iter) {
-        (*iter)->GenerateDescription(printer);
-      }
-      printer->Outdent();
-      printer->Outdent();
-      printer->Outdent();
-      printer->Print(
-          "    };\n");
-    }
-
     TextFormatDecodeData text_format_decode_data;
     bool has_fields = descriptor_->field_count() > 0;
+    bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault();
+    string field_description_type;
+    if (need_defaults) {
+      field_description_type = "GPBMessageFieldDescriptionWithDefault";
+    } else {
+      field_description_type = "GPBMessageFieldDescription";
+    }
     if (has_fields) {
-      // TODO(thomasvl): The plugin's FieldGenerator::GenerateFieldDescription()
-      // wraps the fieldOptions's value of this structure in an CPP gate so
-      // they can be compiled away; but that still results in a const char* in
-      // the structure for a NULL pointer for every message field.  If the
-      // fieldOptions are moved to a separate payload like the TextFormat extra
-      // data is, then it would shrink that static data shrinking the binaries
-      // a little more.
-      // TODO(thomasvl): proto3 syntax doens't need a defaultValue in the
-      // structure because primitive types are always zero.  If we add a second
-      // structure and a different initializer, we can avoid the wasted static
-      // storage for every field in a proto3 message.
       printer->Print(
-          "    static GPBMessageFieldDescription fields[] = {\n");
+          "    static $field_description_type$ fields[] = {\n",
+          "field_description_type", field_description_type);
       printer->Indent();
       printer->Indent();
       printer->Indent();
       for (int i = 0; i < descriptor_->field_count(); ++i) {
         const FieldGenerator& field_generator =
             field_generators_.get(sorted_fields[i]);
-        field_generator.GenerateFieldDescription(printer);
+        field_generator.GenerateFieldDescription(printer, need_defaults);
         if (field_generator.needs_textformat_name_support()) {
           text_format_decode_data.AddString(sorted_fields[i]->number(),
                                             field_generator.generated_objc_name(),
@@ -512,129 +514,127 @@
           "    };\n");
     }
 
-    bool has_enums = enum_generators_.size();
-    if (has_enums) {
-      printer->Print(
-          "    static GPBMessageEnumDescription enums[] = {\n");
-      printer->Indent();
-      printer->Indent();
-      printer->Indent();
-      for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
-           iter != enum_generators_.end(); ++iter) {
-        printer->Print("{ .enumDescriptorFunc = $name$_EnumDescriptor },\n",
-                       "name", (*iter)->name());
-      }
-      printer->Outdent();
-      printer->Outdent();
-      printer->Outdent();
-      printer->Print(
-          "    };\n");
-    }
-
-    bool has_extensions = sorted_extensions.size();
-    if (has_extensions) {
-      printer->Print(
-          "    static GPBExtensionRange ranges[] = {\n");
-      printer->Indent();
-      printer->Indent();
-      printer->Indent();
-      for (int i = 0; i < sorted_extensions.size(); i++) {
-        printer->Print("{ .start = $start$, .end = $end$ },\n",
-                       "start", SimpleItoa(sorted_extensions[i]->start),
-                       "end", SimpleItoa(sorted_extensions[i]->end));
-      }
-      printer->Outdent();
-      printer->Outdent();
-      printer->Outdent();
-      printer->Print(
-          "    };\n");
-    }
-
-    map<string, string> vars;
+    std::map<string, string> vars;
     vars["classname"] = class_name_;
     vars["rootclassname"] = root_classname_;
     vars["fields"] = has_fields ? "fields" : "NULL";
-    vars["fields_count"] =
-        has_fields ? "sizeof(fields) / sizeof(GPBMessageFieldDescription)" : "0";
-    vars["oneofs"] = has_oneofs ? "oneofs" : "NULL";
-    vars["oneof_count"] =
-        has_oneofs ? "sizeof(oneofs) / sizeof(GPBMessageOneofDescription)" : "0";
-    vars["enums"] = has_enums ? "enums" : "NULL";
-    vars["enum_count"] =
-        has_enums ? "sizeof(enums) / sizeof(GPBMessageEnumDescription)" : "0";
-    vars["ranges"] = has_extensions ? "ranges" : "NULL";
-    vars["range_count"] =
-        has_extensions ? "sizeof(ranges) / sizeof(GPBExtensionRange)" : "0";
-    vars["wireformat"] =
-        descriptor_->options().message_set_wire_format() ? "YES" : "NO";
-
-    if (text_format_decode_data.num_entries() == 0) {
-      printer->Print(
-          vars,
-          "    GPBDescriptor *localDescriptor =\n"
-          "        [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
-          "                                     rootClass:[$rootclassname$ class]\n"
-          "                                          file:$rootclassname$_FileDescriptor()\n"
-          "                                        fields:$fields$\n"
-          "                                    fieldCount:$fields_count$\n"
-          "                                        oneofs:$oneofs$\n"
-          "                                    oneofCount:$oneof_count$\n"
-          "                                         enums:$enums$\n"
-          "                                     enumCount:$enum_count$\n"
-          "                                        ranges:$ranges$\n"
-          "                                    rangeCount:$range_count$\n"
-          "                                   storageSize:sizeof($classname$__storage_)\n"
-          "                                    wireFormat:$wireformat$];\n");
+    if (has_fields) {
+      vars["fields_count"] =
+          "(uint32_t)(sizeof(fields) / sizeof(" + field_description_type + "))";
     } else {
-      vars["extraTextFormatInfo"] = CEscape(text_format_decode_data.Data());
+      vars["fields_count"] = "0";
+    }
+
+    std::vector<string> init_flags;
+    if (need_defaults) {
+      init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault");
+    }
+    if (descriptor_->options().message_set_wire_format()) {
+      init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat");
+    }
+    vars["init_flags"] = BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION,
+                                          init_flags);
+
+    printer->Print(
+        vars,
+        "    GPBDescriptor *localDescriptor =\n"
+        "        [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
+        "                                     rootClass:[$rootclassname$ class]\n"
+        "                                          file:$rootclassname$_FileDescriptor()\n"
+        "                                        fields:$fields$\n"
+        "                                    fieldCount:$fields_count$\n"
+        "                                   storageSize:sizeof($classname$__storage_)\n"
+        "                                         flags:$init_flags$];\n");
+    if (oneof_generators_.size() != 0) {
       printer->Print(
-          vars,
-          "#if GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
-          "    const char *extraTextFormatInfo = NULL;\n"
-          "#else\n"
-          "    static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n"
-          "#endif  // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
-          "    GPBDescriptor *localDescriptor =\n"
-          "        [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
-          "                                     rootClass:[$rootclassname$ class]\n"
-          "                                          file:$rootclassname$_FileDescriptor()\n"
-          "                                        fields:$fields$\n"
-          "                                    fieldCount:$fields_count$\n"
-          "                                        oneofs:$oneofs$\n"
-          "                                    oneofCount:$oneof_count$\n"
-          "                                         enums:$enums$\n"
-          "                                     enumCount:$enum_count$\n"
-          "                                        ranges:$ranges$\n"
-          "                                    rangeCount:$range_count$\n"
-          "                                   storageSize:sizeof($classname$__storage_)\n"
-          "                                    wireFormat:$wireformat$\n"
-          "                           extraTextFormatInfo:extraTextFormatInfo];\n");
+          "    static const char *oneofs[] = {\n");
+      for (std::vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+           iter != oneof_generators_.end(); ++iter) {
+        printer->Print(
+            "      \"$name$\",\n",
+            "name", (*iter)->DescriptorName());
       }
       printer->Print(
-          "    NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
-          "    descriptor = localDescriptor;\n"
-          "  }\n"
-          "  return descriptor;\n"
-          "}\n\n"
-          "@end\n\n");
+          "    };\n"
+          "    [localDescriptor setupOneofs:oneofs\n"
+          "                           count:(uint32_t)(sizeof(oneofs) / sizeof(char*))\n"
+          "                   firstHasIndex:$first_has_index$];\n",
+          "first_has_index", oneof_generators_[0]->HasIndexAsString());
+    }
+    if (text_format_decode_data.num_entries() != 0) {
+      const string text_format_data_str(text_format_decode_data.Data());
+      printer->Print(
+          "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
+          "    static const char *extraTextFormatInfo =");
+      static const int kBytesPerLine = 40;  // allow for escaping
+      for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) {
+        printer->Print(
+            "\n        \"$data$\"",
+            "data", EscapeTrigraphs(
+                CEscape(text_format_data_str.substr(i, kBytesPerLine))));
+      }
+      printer->Print(
+          ";\n"
+          "    [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n"
+          "#endif  // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n");
+    }
+    if (sorted_extensions.size() != 0) {
+      printer->Print(
+          "    static const GPBExtensionRange ranges[] = {\n");
+      for (int i = 0; i < sorted_extensions.size(); i++) {
+        printer->Print("      { .start = $start$, .end = $end$ },\n",
+                       "start", SimpleItoa(sorted_extensions[i]->start),
+                       "end", SimpleItoa(sorted_extensions[i]->end));
+      }
+      printer->Print(
+          "    };\n"
+          "    [localDescriptor setupExtensionRanges:ranges\n"
+          "                                    count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
+    }
+    if (descriptor_->containing_type() != NULL) {
+      string parent_class_name = ClassName(descriptor_->containing_type());
+      printer->Print(
+          "    [localDescriptor setupContainingMessageClassName:GPBStringifySymbol($parent_name$)];\n",
+          "parent_name", parent_class_name);
+    }
+    string suffix_added;
+    ClassName(descriptor_, &suffix_added);
+    if (suffix_added.size() > 0) {
+      printer->Print(
+          "    [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n",
+          "suffix", suffix_added);
+    }
+    printer->Print(
+        "    NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
+        "    descriptor = localDescriptor;\n"
+        "  }\n"
+        "  return descriptor;\n"
+        "}\n\n"
+        "@end\n\n");
+
+    if (!deprecated_attribute_.empty()) {
+      printer->Print(
+          "#pragma clang diagnostic pop\n"
+          "\n");
+    }
 
     for (int i = 0; i < descriptor_->field_count(); i++) {
       field_generators_.get(descriptor_->field(i))
           .GenerateCFunctionImplementations(printer);
     }
 
-    for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+    for (std::vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
          iter != oneof_generators_.end(); ++iter) {
       (*iter)->GenerateClearFunctionImplementation(printer);
     }
   }
 
-  for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
+  for (std::vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
        iter != enum_generators_.end(); ++iter) {
     (*iter)->GenerateSource(printer);
   }
 
-  for (vector<MessageGenerator*>::iterator iter =
+  for (std::vector<MessageGenerator*>::iterator iter =
            nested_message_generators_.begin();
        iter != nested_message_generators_.end(); ++iter) {
     (*iter)->GenerateSource(printer);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.h b/src/google/protobuf/compiler/objectivec/objectivec_message.h
index 06b536f..2de03f1 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.h
@@ -54,7 +54,9 @@
 
 class MessageGenerator {
  public:
-  MessageGenerator(const string& root_classname, const Descriptor* descriptor);
+  MessageGenerator(const string& root_classname,
+                   const Descriptor* descriptor,
+                   const Options& options);
   ~MessageGenerator();
 
   void GenerateStaticVariablesInitialization(io::Printer* printer);
@@ -62,7 +64,10 @@
   void GenerateMessageHeader(io::Printer* printer);
   void GenerateSource(io::Printer* printer);
   void GenerateExtensionRegistrationSource(io::Printer* printer);
-  void DetermineForwardDeclarations(set<string>* fwd_decls);
+  void DetermineForwardDeclarations(std::set<string>* fwd_decls);
+
+  // Checks if the message or a nested message includes a oneof definition.
+  bool IncludesOneOfDefinition() const;
 
  private:
   void GenerateParseFromMethodsHeader(io::Printer* printer);
@@ -80,10 +85,11 @@
   const Descriptor* descriptor_;
   FieldGeneratorMap field_generators_;
   const string class_name_;
-  vector<ExtensionGenerator*> extension_generators_;
-  vector<EnumGenerator*> enum_generators_;
-  vector<MessageGenerator*> nested_message_generators_;
-  vector<OneofGenerator*> oneof_generators_;
+  const string deprecated_attribute_;
+  std::vector<ExtensionGenerator*> extension_generators_;
+  std::vector<EnumGenerator*> enum_generators_;
+  std::vector<MessageGenerator*> nested_message_generators_;
+  std::vector<OneofGenerator*> oneof_generators_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
 };
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
index f2ce4e5..699d25b 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
@@ -45,7 +45,7 @@
 namespace {
 
 void SetMessageVariables(const FieldDescriptor* descriptor,
-                         map<string, string>* variables) {
+                         std::map<string, string>* variables) {
   const string& message_type = ClassName(descriptor->message_type());
   (*variables)["type"] = message_type;
   (*variables)["containing_class"] = ClassName(descriptor->containing_type());
@@ -58,15 +58,17 @@
 
 }  // namespace
 
-MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor)
-    : ObjCObjFieldGenerator(descriptor) {
+MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
+                                             const Options& options)
+    : ObjCObjFieldGenerator(descriptor, options) {
   SetMessageVariables(descriptor, &variables_);
 }
 
 MessageFieldGenerator::~MessageFieldGenerator() {}
 
 void MessageFieldGenerator::DetermineForwardDeclarations(
-    set<string>* fwd_decls) const {
+    std::set<string>* fwd_decls) const {
+  ObjCObjFieldGenerator::DetermineForwardDeclarations(fwd_decls);
   // Class name is already in "storage_type".
   fwd_decls->insert("@class " + variable("storage_type"));
 }
@@ -82,14 +84,24 @@
 }
 
 RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
-    const FieldDescriptor* descriptor)
-    : RepeatedFieldGenerator(descriptor) {
+    const FieldDescriptor* descriptor, const Options& options)
+    : RepeatedFieldGenerator(descriptor, options) {
   SetMessageVariables(descriptor, &variables_);
   variables_["array_storage_type"] = "NSMutableArray";
+  variables_["array_property_type"] =
+      "NSMutableArray<" + variables_["storage_type"] + "*>";
 }
 
 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
 
+void RepeatedMessageFieldGenerator::DetermineForwardDeclarations(
+    std::set<string>* fwd_decls) const {
+  RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls);
+  // Class name is already in "storage_type".
+  fwd_decls->insert("@class " + variable("storage_type"));
+}
+
+
 }  // namespace objectivec
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
index 708ea56..50f4b6d 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
@@ -41,27 +41,34 @@
 namespace objectivec {
 
 class MessageFieldGenerator : public ObjCObjFieldGenerator {
-  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
 
  protected:
-  explicit MessageFieldGenerator(const FieldDescriptor* descriptor);
+  MessageFieldGenerator(const FieldDescriptor* descriptor,
+                        const Options& options);
   virtual ~MessageFieldGenerator();
   virtual bool WantsHasProperty(void) const;
 
  public:
-  virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+  virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
 };
 
 class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator {
-  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
 
  protected:
-  explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor);
+  RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+                                const Options& options);
   virtual ~RepeatedMessageFieldGenerator();
 
+ public:
+  virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
+
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
 };
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
index 3cb8748..5531ae2 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
@@ -53,7 +53,7 @@
   string comments;
   SourceLocation location;
   if (descriptor_->GetSourceLocation(&location)) {
-    comments = BuildCommentsString(location);
+    comments = BuildCommentsString(location, true);
   } else {
     comments = "";
   }
@@ -104,6 +104,9 @@
 void OneofGenerator::GenerateClearFunctionDeclaration(io::Printer* printer) {
   printer->Print(
       variables_,
+      "/**\n"
+      " * Clears whatever value was set for the oneof '$name$'.\n"
+      " **/\n"
       "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message);\n");
 }
 
@@ -118,18 +121,17 @@
       variables_,
       "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message) {\n"
       "  GPBDescriptor *descriptor = [message descriptor];\n"
-      "  GPBOneofDescriptor *oneof = descriptor->oneofs_[$raw_index$];\n"
-      "  GPBMaybeClearOneof(message, oneof, 0);\n"
+      "  GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:$raw_index$];\n"
+      "  GPBMaybeClearOneof(message, oneof, $index$, 0);\n"
       "}\n");
 }
 
-void OneofGenerator::GenerateDescription(io::Printer* printer) {
-  printer->Print(
-      variables_,
-      "{\n"
-      "  .name = \"$name$\",\n"
-      "  .index = $index$,\n"
-      "},\n");
+string OneofGenerator::DescriptorName(void) const {
+  return variables_.find("name")->second;
+}
+
+string OneofGenerator::HasIndexAsString(void) const {
+  return variables_.find("index")->second;
 }
 
 }  // namespace objectivec
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
index bcba82d..ff353a6 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
@@ -61,11 +61,13 @@
 
   void GeneratePropertyImplementation(io::Printer* printer);
   void GenerateClearFunctionImplementation(io::Printer* printer);
-  void GenerateDescription(io::Printer* printer);
+
+  string DescriptorName(void) const;
+  string HasIndexAsString(void) const;
 
  private:
   const OneofDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OneofGenerator);
 };
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
index c185b66..aa8ac32 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
@@ -74,7 +74,7 @@
     case OBJECTIVECTYPE_ENUM:
       return "int32_t";
     case OBJECTIVECTYPE_MESSAGE:
-      return NULL;
+      return NULL;  // Messages go through objectivec_message_field.cc|h.
   }
 
   // Some compilers report reaching end of function even though all cases of
@@ -107,7 +107,8 @@
     case OBJECTIVECTYPE_ENUM:
       return "Enum";
     case OBJECTIVECTYPE_MESSAGE:
-      return "";  // Want NSArray
+      // Want NSArray (but goes through objectivec_message_field.cc|h).
+      return "";
   }
 
   // Some compilers report reaching end of function even though all cases of
@@ -117,7 +118,7 @@
 }
 
 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
-                           map<string, string>* variables) {
+                           std::map<string, string>* variables) {
   std::string primitive_name = PrimitiveTypeName(descriptor);
   (*variables)["type"] = primitive_name;
   (*variables)["storage_type"] = primitive_name;
@@ -126,16 +127,42 @@
 }  // namespace
 
 PrimitiveFieldGenerator::PrimitiveFieldGenerator(
-    const FieldDescriptor* descriptor)
-    : SingleFieldGenerator(descriptor) {
+    const FieldDescriptor* descriptor, const Options& options)
+    : SingleFieldGenerator(descriptor, options) {
   SetPrimitiveVariables(descriptor, &variables_);
 }
 
 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
 
+void PrimitiveFieldGenerator::GenerateFieldStorageDeclaration(
+    io::Printer* printer) const {
+  if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) {
+    // Nothing, BOOLs are stored in the has bits.
+  } else {
+    SingleFieldGenerator::GenerateFieldStorageDeclaration(printer);
+  }
+}
+
+int PrimitiveFieldGenerator::ExtraRuntimeHasBitsNeeded(void) const {
+  if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) {
+    // Reserve a bit for the storage of the boolean.
+    return 1;
+  }
+  return 0;
+}
+
+void PrimitiveFieldGenerator::SetExtraRuntimeHasBitsBase(int has_base) {
+  if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) {
+    // Set into the offset the has bit to use for the actual value.
+    variables_["storage_offset_value"] = SimpleItoa(has_base);
+    variables_["storage_offset_comment"] =
+        "  // Stored in _has_storage_ to save space.";
+  }
+}
+
 PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator(
-    const FieldDescriptor* descriptor)
-    : ObjCObjFieldGenerator(descriptor) {
+    const FieldDescriptor* descriptor, const Options& options)
+    : ObjCObjFieldGenerator(descriptor, options) {
   SetPrimitiveVariables(descriptor, &variables_);
   variables_["property_storage_attribute"] = "copy";
 }
@@ -143,8 +170,8 @@
 PrimitiveObjFieldGenerator::~PrimitiveObjFieldGenerator() {}
 
 RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
-    const FieldDescriptor* descriptor)
-    : RepeatedFieldGenerator(descriptor) {
+    const FieldDescriptor* descriptor, const Options& options)
+    : RepeatedFieldGenerator(descriptor, options) {
   SetPrimitiveVariables(descriptor, &variables_);
 
   string base_name = PrimitiveArrayTypeName(descriptor);
@@ -152,19 +179,13 @@
     variables_["array_storage_type"] = "GPB" + base_name + "Array";
   } else {
     variables_["array_storage_type"] = "NSMutableArray";
+    variables_["array_property_type"] =
+        "NSMutableArray<" + variables_["storage_type"] + "*>";
   }
 }
 
 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
 
-void RepeatedPrimitiveFieldGenerator::FinishInitialization(void) {
-  RepeatedFieldGenerator::FinishInitialization();
-  if (IsPrimitiveType(descriptor_)) {
-    // No comment needed for primitive types.
-    variables_["array_comment"] = "";
-  }
-}
-
 }  // namespace objectivec
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
index 9bb7934..69bb1fd 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
@@ -41,21 +41,30 @@
 namespace objectivec {
 
 class PrimitiveFieldGenerator : public SingleFieldGenerator {
-  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
 
  protected:
-  explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+  PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                          const Options& options);
   virtual ~PrimitiveFieldGenerator();
 
+  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const;
+
+  virtual int ExtraRuntimeHasBitsNeeded(void) const;
+  virtual void SetExtraRuntimeHasBitsBase(int index_base);
+
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
 };
 
 class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator {
-  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
 
  protected:
-  explicit PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor);
+  PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor,
+                             const Options& options);
   virtual ~PrimitiveObjFieldGenerator();
 
  private:
@@ -63,12 +72,13 @@
 };
 
 class RepeatedPrimitiveFieldGenerator : public RepeatedFieldGenerator {
-  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
 
  protected:
-  explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+  RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                                  const Options& options);
   virtual ~RepeatedPrimitiveFieldGenerator();
-  virtual void FinishInitialization(void);
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index 90ded4d..5c7047a 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -39,13 +39,14 @@
 #include <limits>
 
 
-#include <google/protobuf/compiler/parser.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/stubs/casts.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/parser.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/map_util.h>
 
@@ -249,11 +250,11 @@
     input_->Next();
     return true;
   } else if (LookingAt("inf")) {
-    *output = numeric_limits<double>::infinity();
+    *output = std::numeric_limits<double>::infinity();
     input_->Next();
     return true;
   } else if (LookingAt("nan")) {
-    *output = numeric_limits<double>::quiet_NaN();
+    *output = std::numeric_limits<double>::quiet_NaN();
     input_->Next();
     return true;
   } else {
@@ -282,7 +283,7 @@
     const char* text, const LocationRecorder* location) {
   if (LookingAt(text)) {
     string leading, trailing;
-    vector<string> detached;
+    std::vector<string> detached;
     input_->NextWithComments(&trailing, &detached, &leading);
 
     // Save the leading comments for next time, and recall the leading comments
@@ -336,31 +337,42 @@
 
 Parser::LocationRecorder::LocationRecorder(Parser* parser)
   : parser_(parser),
+    source_code_info_(parser->source_code_info_),
     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);
+  Init(parent, parent.source_code_info_);
+}
+
+Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent,
+                                           int path1,
+                                           SourceCodeInfo* source_code_info) {
+  Init(parent, source_code_info);
+  AddPath(path1);
 }
 
 Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent,
                                            int path1) {
-  Init(parent);
+  Init(parent, parent.source_code_info_);
   AddPath(path1);
 }
 
 Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent,
                                            int path1, int path2) {
-  Init(parent);
+  Init(parent, parent.source_code_info_);
   AddPath(path1);
   AddPath(path2);
 }
 
-void Parser::LocationRecorder::Init(const LocationRecorder& parent) {
+void Parser::LocationRecorder::Init(const LocationRecorder& parent,
+                                    SourceCodeInfo* source_code_info) {
   parser_ = parent.parser_;
-  location_ = parser_->source_code_info_->add_location();
+  source_code_info_ = source_code_info;
+
+  location_ = source_code_info_->add_location();
   location_->mutable_path()->CopyFrom(parent.location_->path());
 
   location_->add_span(parser_->input_->current().line);
@@ -402,9 +414,13 @@
   }
 }
 
+int Parser::LocationRecorder::CurrentPathSize() const {
+  return location_->path_size();
+}
+
 void Parser::LocationRecorder::AttachComments(
     string* leading, string* trailing,
-    vector<string>* detached_comments) const {
+    std::vector<string>* detached_comments) const {
   GOOGLE_CHECK(!location_->has_leading_comments());
   GOOGLE_CHECK(!location_->has_trailing_comments());
 
@@ -487,7 +503,7 @@
     return false;
   }
 
-  set<int> used_values;
+  std::set<int> used_values;
   bool has_duplicates = false;
   for (int i = 0; i < proto->value_size(); ++i) {
     const EnumValueDescriptorProto enum_value = proto->value(i);
@@ -525,7 +541,6 @@
   SourceCodeInfo source_code_info;
   source_code_info_ = &source_code_info;
 
-  vector<string> top_doc_comments;
   if (LookingAtType(io::Tokenizer::TYPE_START)) {
     // Advance to first token.
     input_->NextWithComments(NULL, &upcoming_detached_comments_,
@@ -571,6 +586,7 @@
 
   input_ = NULL;
   source_code_info_ = NULL;
+  assert(file != NULL);
   source_code_info.Swap(file->mutable_source_code_info());
   return !had_errors_;
 }
@@ -664,7 +680,7 @@
 
 namespace {
 
-const int kMaxExtensionRangeSentinel = -1;
+const int kMaxRangeSentinel = -1;
 
 bool IsMessageSetWireFormatMessage(const DescriptorProto& message) {
   const MessageOptions& options = message.options();
@@ -688,12 +704,27 @@
       kint32max :
       FieldDescriptor::kMaxNumber + 1;
   for (int i = 0; i < message->extension_range_size(); ++i) {
-    if (message->extension_range(i).end() == kMaxExtensionRangeSentinel) {
+    if (message->extension_range(i).end() == kMaxRangeSentinel) {
       message->mutable_extension_range(i)->set_end(max_extension_number);
     }
   }
 }
 
+// Modifies any reserved ranges that specified 'max' as the end of the
+// reserved range, and sets them to the type-specific maximum. The actual max
+// tag number can only be determined after all options have been parsed.
+void AdjustReservedRangesWithMaxEndNumber(DescriptorProto* message) {
+  const bool is_message_set = IsMessageSetWireFormatMessage(*message);
+  const int max_field_number = is_message_set ?
+      kint32max :
+      FieldDescriptor::kMaxNumber + 1;
+  for (int i = 0; i < message->reserved_range_size(); ++i) {
+    if (message->reserved_range(i).end() == kMaxRangeSentinel) {
+      message->mutable_reserved_range(i)->set_end(max_field_number);
+    }
+  }
+}
+
 }  // namespace
 
 bool Parser::ParseMessageBlock(DescriptorProto* message,
@@ -717,6 +748,9 @@
   if (message->extension_range_size() > 0) {
     AdjustExtensionRangesWithMaxEndNumber(message);
   }
+  if (message->reserved_range_size() > 0) {
+    AdjustReservedRangesWithMaxEndNumber(message);
+  }
   return true;
 }
 
@@ -1373,7 +1407,7 @@
           value_location.AddPath(
               UninterpretedOption::kNegativeIntValueFieldNumber);
           uninterpreted_option->set_negative_int_value(
-              -static_cast<int64>(value));
+              static_cast<int64>(-value));
         } else {
           value_location.AddPath(
               UninterpretedOption::kPositiveIntValueFieldNumber);
@@ -1429,6 +1463,8 @@
   // Parse the declaration.
   DO(Consume("extensions"));
 
+  int old_range_size = message->extension_range_size();
+
   do {
     // Note that kExtensionRangeFieldNumber was already pushed by the parent.
     LocationRecorder location(extensions_location,
@@ -1455,7 +1491,7 @@
         // Set to the sentinel value - 1 since we increment the value below.
         // The actual value of the end of the range should be set with
         // AdjustExtensionRangesWithMaxEndNumber.
-        end = kMaxExtensionRangeSentinel - 1;
+        end = kMaxRangeSentinel - 1;
       } else {
         DO(ConsumeInteger(&end, "Expected integer."));
       }
@@ -1475,12 +1511,58 @@
     range->set_end(end);
   } while (TryConsume(","));
 
+
+  if (LookingAt("[")) {
+    int range_number_index = extensions_location.CurrentPathSize();
+    SourceCodeInfo info;
+
+    // Parse extension range options in the first range.
+    ExtensionRangeOptions* options =
+        message->mutable_extension_range(old_range_size)->mutable_options();
+
+    {
+      LocationRecorder index_location(
+          extensions_location, 0 /* we fill this in w/ actual index below */,
+          &info);
+      LocationRecorder location(
+          index_location,
+          DescriptorProto::ExtensionRange::kOptionsFieldNumber);
+      DO(Consume("["));
+
+      do {
+        DO(ParseOption(options, location, containing_file, OPTION_ASSIGNMENT));
+      } while (TryConsume(","));
+
+      DO(Consume("]"));
+    }
+
+    // Then copy the extension range options to all of the other ranges we've
+    // parsed.
+    for (int i = old_range_size + 1; i < message->extension_range_size(); i++) {
+      message->mutable_extension_range(i)->mutable_options()
+          ->CopyFrom(*options);
+    }
+    // and copy source locations to the other ranges, too
+    for (int i = old_range_size; i < message->extension_range_size(); i++) {
+      for (int j = 0; j < info.location_size(); j++) {
+        if (info.location(j).path_size() == range_number_index + 1) {
+          // this location's path is up to the extension range index, but doesn't
+          // include options; so it's redundant with location above
+          continue;
+        }
+        SourceCodeInfo_Location* dest = source_code_info_->add_location();
+        dest->CopyFrom(info.location(j));
+        dest->set_path(range_number_index, i);
+      }
+    }
+  }
+
   DO(ConsumeEndOfDeclaration(";", &extensions_location));
   return true;
 }
 
-// This is similar to extension range parsing, except that "max" is not
-// supported, and accepts field name literals.
+// This is similar to extension range parsing, except that it accepts field
+// name literals.
 bool Parser::ParseReserved(DescriptorProto* message,
                            const LocationRecorder& message_location) {
   // Parse the declaration.
@@ -1496,7 +1578,6 @@
   }
 }
 
-
 bool Parser::ParseReservedNames(DescriptorProto* message,
                                 const LocationRecorder& parent_location) {
   do {
@@ -1528,7 +1609,14 @@
     if (TryConsume("to")) {
       LocationRecorder end_location(
           location, DescriptorProto::ReservedRange::kEndFieldNumber);
-      DO(ConsumeInteger(&end, "Expected integer."));
+      if (TryConsume("max")) {
+        // Set to the sentinel value - 1 since we increment the value below.
+        // The actual value of the end of the range should be set with
+        // AdjustExtensionRangesWithMaxEndNumber.
+        end = kMaxRangeSentinel - 1;
+      } else {
+        DO(ConsumeInteger(&end, "Expected integer."));
+      }
     } else {
       LocationRecorder end_location(
           location, DescriptorProto::ReservedRange::kEndFieldNumber);
@@ -1550,6 +1638,77 @@
   return true;
 }
 
+bool Parser::ParseReserved(EnumDescriptorProto* message,
+                          const LocationRecorder& message_location) {
+  // Parse the declaration.
+  DO(Consume("reserved"));
+  if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+    LocationRecorder location(message_location,
+                              DescriptorProto::kReservedNameFieldNumber);
+    return ParseReservedNames(message, location);
+  } else {
+    LocationRecorder location(message_location,
+                              DescriptorProto::kReservedRangeFieldNumber);
+    return ParseReservedNumbers(message, location);
+  }
+}
+
+bool Parser::ParseReservedNames(EnumDescriptorProto* message,
+                                const LocationRecorder& parent_location) {
+  do {
+    LocationRecorder location(parent_location, message->reserved_name_size());
+    DO(ConsumeString(message->add_reserved_name(), "Expected enum value."));
+  } while (TryConsume(","));
+  DO(ConsumeEndOfDeclaration(";", &parent_location));
+  return true;
+}
+
+bool Parser::ParseReservedNumbers(EnumDescriptorProto* message,
+                                  const LocationRecorder& parent_location) {
+  bool first = true;
+  do {
+    LocationRecorder location(parent_location, message->reserved_range_size());
+
+    EnumDescriptorProto::EnumReservedRange* range =
+        message->add_reserved_range();
+    int start, end;
+    io::Tokenizer::Token start_token;
+    {
+      LocationRecorder start_location(
+          location, EnumDescriptorProto::EnumReservedRange::kStartFieldNumber);
+      start_token = input_->current();
+      DO(ConsumeSignedInteger(&start, (first ?
+                                 "Expected enum value or number range." :
+                                 "Expected enum number range.")));
+    }
+
+    if (TryConsume("to")) {
+      LocationRecorder end_location(
+          location, EnumDescriptorProto::EnumReservedRange::kEndFieldNumber);
+      if (TryConsume("max")) {
+        // This is in the enum descriptor path, which doesn't have the message
+        // set duality to fix up, so it doesn't integrate with the sentinel.
+        end = INT_MAX;
+      } else {
+        DO(ConsumeSignedInteger(&end, "Expected integer."));
+      }
+    } else {
+      LocationRecorder end_location(
+          location, EnumDescriptorProto::EnumReservedRange::kEndFieldNumber);
+      end_location.StartAt(start_token);
+      end_location.EndAt(start_token);
+      end = start;
+    }
+
+    range->set_start(start);
+    range->set_end(end);
+    first = false;
+  } while (TryConsume(","));
+
+  DO(ConsumeEndOfDeclaration(";", &parent_location));
+  return true;
+}
+
 bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
                          RepeatedPtrField<DescriptorProto>* messages,
                          const LocationRecorder& parent_location,
@@ -1630,6 +1789,16 @@
       return false;
     }
 
+    if (LookingAt("option")) {
+      LocationRecorder option_location(
+          oneof_location, OneofDescriptorProto::kOptionsFieldNumber);
+      if (!ParseOption(oneof_decl->mutable_options(), option_location,
+                       containing_file, OPTION_STATEMENT)) {
+        return false;
+      }
+      continue;
+    }
+
     // Print a nice error if the user accidentally tries to place a label
     // on an individual member of a oneof.
     if (LookingAt("required") ||
@@ -1720,6 +1889,8 @@
                               EnumDescriptorProto::kOptionsFieldNumber);
     return ParseOption(enum_type->mutable_options(), location,
                        containing_file, OPTION_STATEMENT);
+  } else if (LookingAt("reserved")) {
+    return ParseReserved(enum_type, enum_location);
   } else {
     LocationRecorder location(enum_location,
         EnumDescriptorProto::kValueFieldNumber, enum_type->value_size());
@@ -2079,7 +2250,7 @@
     const Message* descriptor,
     DescriptorPool::ErrorCollector::ErrorLocation location,
     int* line, int* column) const {
-  const pair<int, int>* result =
+  const std::pair<int, int>* result =
       FindOrNull(location_map_, std::make_pair(descriptor, location));
   if (result == NULL) {
     *line   = -1;
@@ -2106,4 +2277,5 @@
 
 }  // namespace compiler
 }  // namespace protobuf
+
 }  // namespace google
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index 2c561c2..5d98e5e 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -40,10 +40,10 @@
 #include <map>
 #include <string>
 #include <utility>
-#include <google/protobuf/descriptor.h>
 #include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/repeated_field.h>
 #include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/repeated_field.h>
 
 namespace google {
 namespace protobuf { class Message; }
@@ -71,7 +71,7 @@
   // it.  Returns true if no errors occurred, false otherwise.
   bool Parse(io::Tokenizer* input, FileDescriptorProto* file);
 
-  // Optional fetaures:
+  // Optional features:
 
   // DEPRECATED:  New code should use the SourceCodeInfo embedded in the
   //   FileDescriptorProto.
@@ -224,6 +224,10 @@
     LocationRecorder(const LocationRecorder& parent, int path1);
     LocationRecorder(const LocationRecorder& parent, int path1, int path2);
 
+    // Creates a recorder that generates locations into given source code info.
+    LocationRecorder(const LocationRecorder& parent, int path1,
+                    SourceCodeInfo* source_code_info);
+
     ~LocationRecorder();
 
     // Add a path component.  See SourceCodeInfo.Location.path in
@@ -250,6 +254,9 @@
     void RecordLegacyLocation(const Message* descriptor,
         DescriptorPool::ErrorCollector::ErrorLocation location);
 
+    // Returns the number of path components in the recorder's current location.
+    int CurrentPathSize() const;
+
     // Attaches leading and trailing comments to the location.  The two strings
     // will be swapped into place, so after this is called *leading and
     // *trailing will be empty.
@@ -257,16 +264,17 @@
     // TODO(kenton):  See comment on TryConsumeEndOfDeclaration(), above, for
     //   why this is const.
     void AttachComments(string* leading, string* trailing,
-                        vector<string>* detached_comments) const;
+                        std::vector<string>* detached_comments) const;
 
    private:
     // Indexes of parent and current location in the parent
     // SourceCodeInfo.location repeated field. For top-level elements,
     // parent_index_ is -1.
     Parser* parser_;
+    SourceCodeInfo* source_code_info_;
     SourceCodeInfo::Location* location_;
 
-    void Init(const LocationRecorder& parent);
+    void Init(const LocationRecorder& parent, SourceCodeInfo* source_code_info);
   };
 
   // =================================================================
@@ -371,6 +379,12 @@
                           const LocationRecorder& parent_location);
   bool ParseReservedNumbers(DescriptorProto* message,
                             const LocationRecorder& parent_location);
+  bool ParseReserved(EnumDescriptorProto* message,
+                     const LocationRecorder& message_location);
+  bool ParseReservedNames(EnumDescriptorProto* message,
+                          const LocationRecorder& parent_location);
+  bool ParseReservedNumbers(EnumDescriptorProto* message,
+                            const LocationRecorder& parent_location);
 
   // Parse an "extend" declaration.  (See also comments for
   // ParseMessageField().)
@@ -520,7 +534,7 @@
   // detached comments will be put into the leading_detached_comments field for
   // the next element (See SourceCodeInfo.Location in descriptor.proto), when
   // ConsumeEndOfDeclaration() is called.
-  vector<string> upcoming_detached_comments_;
+  std::vector<string> upcoming_detached_comments_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser);
 };
@@ -556,9 +570,9 @@
   void Clear();
 
  private:
-  typedef map<
-    pair<const Message*, DescriptorPool::ErrorCollector::ErrorLocation>,
-    pair<int, int> > LocationMap;
+  typedef std::map<
+    std::pair<const Message*, DescriptorPool::ErrorCollector::ErrorLocation>,
+    std::pair<int, int> > LocationMap;
   LocationMap location_map_;
 };
 
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index 1d623dd..0725a68 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -33,24 +33,21 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 #include <vector>
 #include <algorithm>
 #include <map>
 
 #include <google/protobuf/compiler/parser.h>
 
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_custom_options.pb.h>
 #include <google/protobuf/io/tokenizer.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/wire_format.h>
 #include <google/protobuf/text_format.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/unittest_custom_options.pb.h>
-#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/substitute.h>
+
 #include <google/protobuf/stubs/map_util.h>
 
 #include <google/protobuf/testing/googletest.h>
@@ -178,9 +175,9 @@
   MockErrorCollector error_collector_;
   DescriptorPool pool_;
 
-  google::protobuf::scoped_ptr<io::ZeroCopyInputStream> raw_input_;
-  google::protobuf::scoped_ptr<io::Tokenizer> input_;
-  google::protobuf::scoped_ptr<Parser> parser_;
+  std::unique_ptr<io::ZeroCopyInputStream> raw_input_;
+  std::unique_ptr<io::Tokenizer> input_;
+  std::unique_ptr<Parser> parser_;
   bool require_syntax_identifier_;
 };
 
@@ -664,7 +661,7 @@
   ExpectParsesTo(
     "message TestMessage {\n"
     "  required int32 foo = 1;\n"
-    "  reserved 2, 15, 9 to 11, 3;\n"
+    "  reserved 2, 15, 9 to 11, 3, 20 to max;\n"
     "}\n",
 
     "message_type {"
@@ -674,6 +671,29 @@
     "  reserved_range { start:15  end:16        }"
     "  reserved_range { start:9   end:12        }"
     "  reserved_range { start:3   end:4         }"
+    "  reserved_range { start:20  end:536870912 }"
+    "}");
+}
+
+TEST_F(ParseMessageTest, ReservedRangeOnMessageSet) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  option message_set_wire_format = true;\n"
+    "  reserved 20 to max;\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  options {"
+    "    uninterpreted_option {"
+    "      name {"
+    "        name_part: \"message_set_wire_format\""
+    "        is_extension: false"
+    "      }"
+    "      identifier_value: \"true\""
+    "    }"
+    "  }"
+    "  reserved_range { start:20  end:2147483647 }"
     "}");
 }
 
@@ -704,6 +724,30 @@
     "}");
 }
 
+TEST_F(ParseMessageTest, ExtensionRangeWithOptions) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  extensions 10 to 19 [(i) = 5];\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  extension_range {"
+    "    start:10"
+    "    end:20"
+    "    options {"
+    "      uninterpreted_option {"
+    "        name {"
+    "          name_part: \"i\""
+    "          is_extension: true"
+    "        }"
+    "        positive_int_value: 5"
+    "      }"
+    "    }"
+    "  }"
+    "}");
+}
+
 TEST_F(ParseMessageTest, CompoundExtensionRange) {
   ExpectParsesTo(
     "message TestMessage {\n"
@@ -720,6 +764,82 @@
     "}");
 }
 
+TEST_F(ParseMessageTest, CompoundExtensionRangeWithOptions) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  extensions 2, 15, 9 to 11, 100 to max, 3 [(i) = 5];\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  extension_range {"
+    "    start:2"
+    "    end:3"
+    "    options {"
+    "      uninterpreted_option {"
+    "        name {"
+    "          name_part: \"i\""
+    "          is_extension: true"
+    "        }"
+    "        positive_int_value: 5"
+    "      }"
+    "    }"
+    "  }"
+    "  extension_range {"
+    "    start:15"
+    "    end:16"
+    "    options {"
+    "      uninterpreted_option {"
+    "        name {"
+    "          name_part: \"i\""
+    "          is_extension: true"
+    "        }"
+    "        positive_int_value: 5"
+    "      }"
+    "    }"
+    "  }"
+    "  extension_range {"
+    "    start:9"
+    "    end:12"
+    "    options {"
+    "      uninterpreted_option {"
+    "        name {"
+    "          name_part: \"i\""
+    "          is_extension: true"
+    "        }"
+    "        positive_int_value: 5"
+    "      }"
+    "    }"
+    "  }"
+    "  extension_range {"
+    "    start:100"
+    "    end:536870912"
+    "    options {"
+    "      uninterpreted_option {"
+    "        name {"
+    "          name_part: \"i\""
+    "          is_extension: true"
+    "        }"
+    "        positive_int_value: 5"
+    "      }"
+    "    }"
+    "  }"
+    "  extension_range {"
+    "    start:3"
+    "    end:4"
+    "    options {"
+    "      uninterpreted_option {"
+    "        name {"
+    "          name_part: \"i\""
+    "          is_extension: true"
+    "        }"
+    "        positive_int_value: 5"
+    "      }"
+    "    }"
+    "  }"
+    "}");
+}
+
 TEST_F(ParseMessageTest, LargerMaxForMessageSetWireFormatMessages) {
   // Messages using the message_set_wire_format option can accept larger
   // extension numbers, as the numbers are not encoded as int32 field values
@@ -872,6 +992,42 @@
     "}");
 }
 
+TEST_F(ParseEnumTest, ReservedRange) {
+  ExpectParsesTo(
+    "enum TestEnum {\n"
+    "  FOO = 0;\n"
+    "  reserved -2147483648, -6 to -4, -1 to 1, 2, 15, 9 to 11, 3, 20 to max;\n"
+    "}\n",
+
+    "enum_type {"
+    "  name: \"TestEnum\""
+    "  value { name:\"FOO\" number:0 }"
+    "  reserved_range { start:-2147483648  end:-2147483648 }"
+    "  reserved_range { start:-6           end:-4          }"
+    "  reserved_range { start:-1           end:1           }"
+    "  reserved_range { start:2            end:2           }"
+    "  reserved_range { start:15           end:15          }"
+    "  reserved_range { start:9            end:11          }"
+    "  reserved_range { start:3            end:3           }"
+    "  reserved_range { start:20           end:2147483647  }"
+    "}");
+}
+
+TEST_F(ParseEnumTest, ReservedNames) {
+  ExpectParsesTo(
+    "enum TestEnum {\n"
+    "  FOO = 0;\n"
+    "  reserved \"foo\", \"bar\";\n"
+    "}\n",
+
+    "enum_type {"
+    "  name: \"TestEnum\""
+    "  value { name:\"FOO\" number:0 }"
+    "  reserved_name: \"foo\""
+    "  reserved_name: \"bar\""
+    "}");
+}
+
 // ===================================================================
 
 typedef ParserTest ParseServiceTest;
@@ -1366,15 +1522,60 @@
     "1:5: Missing numeric value for enum constant.\n");
 }
 
+TEST_F(ParseErrorTest, EnumReservedStandaloneMaxNotAllowed) {
+  ExpectHasErrors(
+    "enum TestEnum {\n"
+    "  FOO = 1;\n"
+    "  reserved max;\n"
+    "}\n",
+    "2:11: Expected enum value or number range.\n");
+}
+
+TEST_F(ParseErrorTest, EnumReservedMixNameAndNumber) {
+  ExpectHasErrors(
+    "enum TestEnum {\n"
+    "  FOO = 1;\n"
+    "  reserved 10, \"foo\";\n"
+    "}\n",
+    "2:15: Expected enum number range.\n");
+}
+
+TEST_F(ParseErrorTest, EnumReservedPositiveNumberOutOfRange) {
+  ExpectHasErrors(
+    "enum TestEnum {\n"
+       "FOO = 1;\n"
+    "  reserved 2147483648;\n"
+    "}\n",
+    "2:11: Integer out of range.\n");
+}
+
+TEST_F(ParseErrorTest, EnumReservedNegativeNumberOutOfRange) {
+  ExpectHasErrors(
+    "enum TestEnum {\n"
+       "FOO = 1;\n"
+    "  reserved -2147483649;\n"
+    "}\n",
+    "2:12: Integer out of range.\n");
+}
+
+TEST_F(ParseErrorTest, EnumReservedMissingQuotes) {
+  ExpectHasErrors(
+    "enum TestEnum {\n"
+    "  FOO = 1;\n"
+    "  reserved foo;\n"
+    "}\n",
+    "2:11: Expected enum value or number range.\n");
+}
+
 // -------------------------------------------------------------------
 // Reserved field number errors
 
-TEST_F(ParseErrorTest, ReservedMaxNotAllowed) {
+TEST_F(ParseErrorTest, ReservedStandaloneMaxNotAllowed) {
   ExpectHasErrors(
     "message Foo {\n"
-    "  reserved 10 to max;\n"
+    "  reserved max;\n"
     "}\n",
-    "1:17: Expected integer.\n");
+    "1:11: Expected field name or number range.\n");
 }
 
 TEST_F(ParseErrorTest, ReservedMixNameAndNumber) {
@@ -1393,6 +1594,23 @@
     "1:11: Expected field name or number range.\n");
 }
 
+TEST_F(ParseErrorTest, ReservedNegativeNumber) {
+  ExpectHasErrors(
+    "message Foo {\n"
+    "  reserved -10;\n"
+    "}\n",
+    "1:11: Expected field name or number range.\n");
+}
+
+TEST_F(ParseErrorTest, ReservedNumberOutOfRange) {
+  ExpectHasErrors(
+    "message Foo {\n"
+    "  reserved 2147483648;\n"
+    "}\n",
+    "1:11: Integer out of range.\n");
+}
+
+
 // -------------------------------------------------------------------
 // Service errors
 
@@ -2218,7 +2436,7 @@
       const char* expected_leading_comments,
       const char* expected_trailing_comments,
       const char* expected_leading_detached_comments) {
-    pair<SpanMap::iterator, SpanMap::iterator> range =
+    std::pair<SpanMap::iterator, SpanMap::iterator> range =
         spans_.equal_range(SpanKey(descriptor_proto, field, index));
 
     if (start_marker == '\0') {
@@ -2229,8 +2447,8 @@
         return true;
       }
     } else {
-      pair<int, int> start_pos = FindOrDie(markers_, start_marker);
-      pair<int, int> end_pos = FindOrDie(markers_, end_marker);
+      std::pair<int, int> start_pos = FindOrDie(markers_, start_marker);
+      std::pair<int, int> end_pos = FindOrDie(markers_, end_marker);
 
       RepeatedField<int> expected_span;
       expected_span.Add(start_pos.first);
@@ -2295,9 +2513,9 @@
     }
   };
 
-  typedef multimap<SpanKey, const SourceCodeInfo::Location*> SpanMap;
+  typedef std::multimap<SpanKey, const SourceCodeInfo::Location*> SpanMap;
   SpanMap spans_;
-  map<char, pair<int, int> > markers_;
+  std::map<char, std::pair<int, int> > markers_;
   string text_without_markers_;
 
   void ExtractMarkers(const char* text) {
diff --git a/src/google/protobuf/compiler/php/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc
new file mode 100644
index 0000000..a58e175
--- /dev/null
+++ b/src/google/protobuf/compiler/php/php_generator.cc
@@ -0,0 +1,1563 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/compiler/php/php_generator.h>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#include <sstream>
+
+const std::string kDescriptorFile = "google/protobuf/descriptor.proto";
+const std::string kEmptyFile = "google/protobuf/empty.proto";
+const std::string kEmptyMetadataFile = "GPBMetadata/Google/Protobuf/GPBEmpty.php";
+const std::string kDescriptorMetadataFile =
+    "GPBMetadata/Google/Protobuf/Internal/Descriptor.php";
+const std::string kDescriptorDirName = "Google/Protobuf/Internal";
+const std::string kDescriptorPackageName = "Google\\Protobuf\\Internal";
+const char* const kReservedNames[] = {
+    "abstract",   "and",        "array",        "as",           "break",
+    "callable",   "case",       "catch",        "class",        "clone",
+    "const",      "continue",   "declare",      "default",      "die",
+    "do",         "echo",       "else",         "elseif",       "empty",
+    "enddeclare", "endfor",     "endforeach",   "endif",        "endswitch",
+    "endwhile",   "eval",       "exit",         "extends",      "final",
+    "for",        "foreach",    "function",     "global",       "goto",
+    "if",         "implements", "include",      "include_once", "instanceof",
+    "insteadof",  "interface",  "isset",        "list",         "namespace",
+    "new",        "or",         "print",        "private",      "protected",
+    "public",     "require",    "require_once", "return",       "static",
+    "switch",     "throw",      "trait",        "try",          "unset",
+    "use",        "var",        "while",        "xor",          "int",
+    "float",      "bool",       "string",       "true",         "false",
+    "null",       "void",       "iterable"};
+const char* const kValidConstantNames[] = {
+    "int",   "float", "bool", "string",   "true",
+    "false", "null",  "void", "iterable",
+};
+const int kReservedNamesSize = 73;
+const int kValidConstantNamesSize = 9;
+const int kFieldSetter = 1;
+const int kFieldGetter = 2;
+const int kFieldProperty = 3;
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace php {
+
+// Forward decls.
+std::string PhpName(const std::string& full_name, bool is_descriptor);
+std::string DefaultForField(FieldDescriptor* field);
+std::string IntToString(int32 value);
+std::string FilenameToClassname(const string& filename);
+std::string GeneratedMetadataFileName(const FileDescriptor* file,
+                                      bool is_descriptor);
+std::string LabelForField(FieldDescriptor* field);
+std::string TypeName(FieldDescriptor* field);
+std::string UnderscoresToCamelCase(const string& name, bool cap_first_letter);
+std::string EscapeDollor(const string& to_escape);
+std::string BinaryToHex(const string& binary);
+void Indent(io::Printer* printer);
+void Outdent(io::Printer* printer);
+void GenerateMessageDocComment(io::Printer* printer, const Descriptor* message,
+                               int is_descriptor);
+void GenerateMessageConstructorDocComment(io::Printer* printer,
+                                          const Descriptor* message,
+                                          int is_descriptor);
+void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field,
+                             int is_descriptor, int function_type);
+void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_,
+                            int is_descriptor);
+void GenerateEnumValueDocComment(io::Printer* printer,
+                                 const EnumValueDescriptor* value);
+void GenerateServiceDocComment(io::Printer* printer,
+                               const ServiceDescriptor* service);
+void GenerateServiceMethodDocComment(io::Printer* printer,
+                              const MethodDescriptor* method);
+
+
+std::string ReservedNamePrefix(const string& classname,
+                                const FileDescriptor* file) {
+  bool is_reserved = false;
+
+  string lower = classname;
+  transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
+
+  for (int i = 0; i < kReservedNamesSize; i++) {
+    if (lower == kReservedNames[i]) {
+      is_reserved = true;
+      break;
+    }
+  }
+
+  if (is_reserved) {
+    if (file->package() == "google.protobuf") {
+      return "GPB";
+    } else {
+      return "PB";
+    }
+  }
+
+  return "";
+}
+
+template <typename DescriptorType>
+std::string DescriptorFullName(const DescriptorType* desc, bool is_descriptor) {
+  if (is_descriptor) {
+    return StringReplace(desc->full_name(),
+                         "google.protobuf",
+                         "google.protobuf.internal", false);
+  } else {
+    return desc->full_name();
+  }
+}
+
+template <typename DescriptorType>
+std::string ClassNamePrefix(const string& classname,
+                            const DescriptorType* desc) {
+  const string& prefix = (desc->file()->options()).php_class_prefix();
+  if (prefix != "") {
+    return prefix;
+  }
+
+  return ReservedNamePrefix(classname, desc->file());
+}
+
+template <typename DescriptorType>
+std::string GeneratedClassNameImpl(const DescriptorType* desc) {
+  std::string classname = ClassNamePrefix(desc->name(), desc) + desc->name();
+  const Descriptor* containing = desc->containing_type();
+  while (containing != NULL) {
+    classname = ClassNamePrefix(containing->name(), desc) + containing->name()
+       + '\\' + classname;
+    containing = containing->containing_type();
+  }
+  return classname;
+}
+
+std::string GeneratedClassNameImpl(const ServiceDescriptor* desc) {
+  std::string classname = desc->name();
+  return ClassNamePrefix(classname, desc) + classname;
+}
+
+std::string GeneratedClassName(const Descriptor* desc) {
+  return GeneratedClassNameImpl(desc);
+}
+
+std::string GeneratedClassName(const EnumDescriptor* desc) {
+  return GeneratedClassNameImpl(desc);
+}
+
+std::string GeneratedClassName(const ServiceDescriptor* desc) {
+  return GeneratedClassNameImpl(desc);
+}
+
+template <typename DescriptorType>
+std::string LegacyGeneratedClassName(const DescriptorType* desc) {
+  std::string classname = desc->name();
+  const Descriptor* containing = desc->containing_type();
+  while (containing != NULL) {
+    classname = containing->name() + '_' + classname;
+    containing = containing->containing_type();
+  }
+  return ClassNamePrefix(classname, desc) + classname;
+}
+
+std::string ClassNamePrefix(const string& classname) {
+  string lower = classname;
+  transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
+
+  for (int i = 0; i < kReservedNamesSize; i++) {
+    if (lower == kReservedNames[i]) {
+      return "PB";
+    }
+  }
+
+  return "";
+}
+
+std::string ConstantNamePrefix(const string& classname) {
+  bool is_reserved = false;
+
+  string lower = classname;
+  transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
+
+  for (int i = 0; i < kReservedNamesSize; i++) {
+    if (lower == kReservedNames[i]) {
+      is_reserved = true;
+      break;
+    }
+  }
+
+  for (int i = 0; i < kValidConstantNamesSize; i++) {
+    if (lower == kValidConstantNames[i]) {
+      is_reserved = false;
+      break;
+    }
+  }
+
+  if (is_reserved) {
+    return "PB";
+  }
+
+  return "";
+}
+
+template <typename DescriptorType>
+std::string RootPhpNamespace(const DescriptorType* desc, bool is_descriptor) {
+  if (desc->file()->options().has_php_namespace()) {
+    const string& php_namespace = desc->file()->options().php_namespace();
+    if (php_namespace != "") {
+      return php_namespace;
+    }
+    return "";
+  }
+
+  if (desc->file()->package() != "") {
+    return PhpName(desc->file()->package(), is_descriptor);
+  }
+  return "";
+}
+
+template <typename DescriptorType>
+std::string FullClassName(const DescriptorType* desc, bool is_descriptor) {
+  string classname = GeneratedClassNameImpl(desc);
+  string php_namespace = RootPhpNamespace(desc, is_descriptor);
+  if (php_namespace != "") {
+    return php_namespace + "\\" + classname;
+  }
+  return classname;
+}
+
+template <typename DescriptorType>
+std::string LegacyFullClassName(const DescriptorType* desc, bool is_descriptor) {
+  string classname = LegacyGeneratedClassName(desc);
+  string php_namespace = RootPhpNamespace(desc, is_descriptor);
+  if (php_namespace != "") {
+    return php_namespace + "\\" + classname;
+  }
+  return classname;
+}
+
+std::string PhpName(const std::string& full_name, bool is_descriptor) {
+  if (is_descriptor) {
+    return kDescriptorPackageName;
+  }
+
+  std::string segment;
+  std::string result;
+  bool cap_next_letter = true;
+  for (int i = 0; i < full_name.size(); i++) {
+    if ('a' <= full_name[i] && full_name[i] <= 'z' && cap_next_letter) {
+      segment += full_name[i] + ('A' - 'a');
+      cap_next_letter = false;
+    } else if (full_name[i] == '.') {
+      result += ClassNamePrefix(segment) + segment + '\\';
+      segment = "";
+      cap_next_letter = true;
+    } else {
+      segment += full_name[i];
+      cap_next_letter = false;
+    }
+  }
+  result += ClassNamePrefix(segment) + segment;
+  return result;
+}
+
+std::string DefaultForField(const FieldDescriptor* field) {
+  switch (field->type()) {
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_UINT32:
+    case FieldDescriptor::TYPE_UINT64:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_SFIXED32:
+    case FieldDescriptor::TYPE_SFIXED64:
+    case FieldDescriptor::TYPE_ENUM: return "0";
+    case FieldDescriptor::TYPE_DOUBLE:
+    case FieldDescriptor::TYPE_FLOAT: return "0.0";
+    case FieldDescriptor::TYPE_BOOL: return "false";
+    case FieldDescriptor::TYPE_STRING:
+    case FieldDescriptor::TYPE_BYTES: return "''";
+    case FieldDescriptor::TYPE_MESSAGE:
+    case FieldDescriptor::TYPE_GROUP: return "null";
+    default: assert(false); return "";
+  }
+}
+
+std::string GeneratedMetadataFileName(const FileDescriptor* file,
+                                      bool is_descriptor) {
+  const string& proto_file = file->name();
+  int start_index = 0;
+  int first_index = proto_file.find_first_of("/", start_index);
+  std::string result = "";
+  std::string segment = "";
+
+  if (proto_file == kEmptyFile) {
+    return kEmptyMetadataFile;
+  }
+  if (is_descriptor) {
+    return kDescriptorMetadataFile;
+  }
+
+  // Append directory name.
+  std::string file_no_suffix;
+  int lastindex = proto_file.find_last_of(".");
+  if (proto_file == kEmptyFile) {
+    return kEmptyMetadataFile;
+  } else {
+    file_no_suffix = proto_file.substr(0, lastindex);
+  }
+
+  if (file->options().has_php_metadata_namespace()) {
+    const string& php_metadata_namespace =
+        file->options().php_metadata_namespace();
+    if (php_metadata_namespace != "" && php_metadata_namespace != "\\") {
+      result += php_metadata_namespace;
+      std::replace(result.begin(), result.end(), '\\', '/');
+      if (result.at(result.size() - 1) != '/') {
+        result += "/";
+      }
+    }
+  } else {
+    result += "GPBMetadata/";
+    while (first_index != string::npos) {
+      segment = UnderscoresToCamelCase(
+          file_no_suffix.substr(start_index, first_index - start_index), true);
+      result += ReservedNamePrefix(segment, file) + segment + "/";
+      start_index = first_index + 1;
+      first_index = file_no_suffix.find_first_of("/", start_index);
+    }
+  }
+
+  // Append file name.
+  int file_name_start = file_no_suffix.find_last_of("/");
+  if (file_name_start == string::npos) {
+    file_name_start = 0;
+  } else {
+    file_name_start += 1;
+  }
+  segment = UnderscoresToCamelCase(
+      file_no_suffix.substr(file_name_start, first_index - file_name_start), true);
+
+  return result + ReservedNamePrefix(segment, file) + segment + ".php";
+}
+
+template <typename DescriptorType>
+std::string GeneratedClassFileName(const DescriptorType* desc,
+                                     bool is_descriptor) {
+  std::string result = FullClassName(desc, is_descriptor);
+  for (int i = 0; i < result.size(); i++) {
+    if (result[i] == '\\') {
+      result[i] = '/';
+    }
+  }
+  return result + ".php";
+}
+
+template <typename DescriptorType>
+std::string LegacyGeneratedClassFileName(const DescriptorType* desc,
+                                     bool is_descriptor) {
+  std::string result = LegacyFullClassName(desc, is_descriptor);
+
+  for (int i = 0; i < result.size(); i++) {
+    if (result[i] == '\\') {
+      result[i] = '/';
+    }
+  }
+  return result + ".php";
+}
+
+std::string GeneratedServiceFileName(const ServiceDescriptor* service,
+                                    bool is_descriptor) {
+  std::string result = FullClassName(service, is_descriptor) + "Interface";
+  for (int i = 0; i < result.size(); i++) {
+    if (result[i] == '\\') {
+      result[i] = '/';
+    }
+  }
+  return result + ".php";
+}
+
+std::string IntToString(int32 value) {
+  std::ostringstream os;
+  os << value;
+  return os.str();
+}
+
+std::string LabelForField(const FieldDescriptor* field) {
+  switch (field->label()) {
+    case FieldDescriptor::LABEL_OPTIONAL: return "optional";
+    case FieldDescriptor::LABEL_REQUIRED: return "required";
+    case FieldDescriptor::LABEL_REPEATED: return "repeated";
+    default: assert(false); return "";
+  }
+}
+
+std::string TypeName(const FieldDescriptor* field) {
+  switch (field->type()) {
+    case FieldDescriptor::TYPE_INT32: return "int32";
+    case FieldDescriptor::TYPE_INT64: return "int64";
+    case FieldDescriptor::TYPE_UINT32: return "uint32";
+    case FieldDescriptor::TYPE_UINT64: return "uint64";
+    case FieldDescriptor::TYPE_SINT32: return "sint32";
+    case FieldDescriptor::TYPE_SINT64: return "sint64";
+    case FieldDescriptor::TYPE_FIXED32: return "fixed32";
+    case FieldDescriptor::TYPE_FIXED64: return "fixed64";
+    case FieldDescriptor::TYPE_SFIXED32: return "sfixed32";
+    case FieldDescriptor::TYPE_SFIXED64: return "sfixed64";
+    case FieldDescriptor::TYPE_DOUBLE: return "double";
+    case FieldDescriptor::TYPE_FLOAT: return "float";
+    case FieldDescriptor::TYPE_BOOL: return "bool";
+    case FieldDescriptor::TYPE_ENUM: return "enum";
+    case FieldDescriptor::TYPE_STRING: return "string";
+    case FieldDescriptor::TYPE_BYTES: return "bytes";
+    case FieldDescriptor::TYPE_MESSAGE: return "message";
+    case FieldDescriptor::TYPE_GROUP: return "group";
+    default: assert(false); return "";
+  }
+}
+
+std::string PhpSetterTypeName(const FieldDescriptor* field, bool is_descriptor) {
+  if (field->is_map()) {
+    return "array|\\Google\\Protobuf\\Internal\\MapField";
+  }
+  string type;
+  switch (field->type()) {
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_UINT32:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_SFIXED32:
+    case FieldDescriptor::TYPE_ENUM:
+      type = "int";
+      break;
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_UINT64:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_SFIXED64:
+      type = "int|string";
+      break;
+    case FieldDescriptor::TYPE_DOUBLE:
+    case FieldDescriptor::TYPE_FLOAT:
+      type = "float";
+      break;
+    case FieldDescriptor::TYPE_BOOL:
+      type = "bool";
+      break;
+    case FieldDescriptor::TYPE_STRING:
+    case FieldDescriptor::TYPE_BYTES:
+      type = "string";
+      break;
+    case FieldDescriptor::TYPE_MESSAGE:
+      type = "\\" + FullClassName(field->message_type(), is_descriptor);
+      break;
+    case FieldDescriptor::TYPE_GROUP:
+      return "null";
+    default: assert(false); return "";
+  }
+  if (field->is_repeated()) {
+    // accommodate for edge case with multiple types.
+    size_t start_pos = type.find("|");
+    if (start_pos != std::string::npos) {
+      type.replace(start_pos, 1, "[]|");
+    }
+    type += "[]|\\Google\\Protobuf\\Internal\\RepeatedField";
+  }
+  return type;
+}
+
+std::string PhpGetterTypeName(const FieldDescriptor* field, bool is_descriptor) {
+  if (field->is_map()) {
+    return "\\Google\\Protobuf\\Internal\\MapField";
+  }
+  if (field->is_repeated()) {
+    return "\\Google\\Protobuf\\Internal\\RepeatedField";
+  }
+  switch (field->type()) {
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_UINT32:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_SFIXED32:
+    case FieldDescriptor::TYPE_ENUM: return "int";
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_UINT64:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_SFIXED64: return "int|string";
+    case FieldDescriptor::TYPE_DOUBLE:
+    case FieldDescriptor::TYPE_FLOAT: return "float";
+    case FieldDescriptor::TYPE_BOOL: return "bool";
+    case FieldDescriptor::TYPE_STRING:
+    case FieldDescriptor::TYPE_BYTES: return "string";
+    case FieldDescriptor::TYPE_MESSAGE:
+      return "\\" + FullClassName(field->message_type(), is_descriptor);
+    case FieldDescriptor::TYPE_GROUP: return "null";
+    default: assert(false); return "";
+  }
+}
+
+std::string EnumOrMessageSuffix(
+    const FieldDescriptor* field, bool is_descriptor) {
+  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+    return ", '" + DescriptorFullName(field->message_type(), is_descriptor) + "'";
+  }
+  if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+    return ", '" + DescriptorFullName(field->enum_type(), is_descriptor) + "'";
+  }
+  return "";
+}
+
+// Converts a name to camel-case. If cap_first_letter is true, capitalize the
+// first letter.
+std::string UnderscoresToCamelCase(const string& input, bool cap_first_letter) {
+  std::string result;
+  for (int i = 0; i < input.size(); i++) {
+    if ('a' <= input[i] && input[i] <= 'z') {
+      if (cap_first_letter) {
+        result += input[i] + ('A' - 'a');
+      } else {
+        result += input[i];
+      }
+      cap_first_letter = false;
+    } else if ('A' <= input[i] && input[i] <= 'Z') {
+      if (i == 0 && !cap_first_letter) {
+        // Force first letter to lower-case unless explicitly told to
+        // capitalize it.
+        result += input[i] + ('a' - 'A');
+      } else {
+        // Capital letters after the first are left as-is.
+        result += input[i];
+      }
+      cap_first_letter = false;
+    } else if ('0' <= input[i] && input[i] <= '9') {
+      result += input[i];
+      cap_first_letter = true;
+    } else {
+      cap_first_letter = true;
+    }
+  }
+  // Add a trailing "_" if the name should be altered.
+  if (input[input.size() - 1] == '#') {
+    result += '_';
+  }
+  return result;
+}
+
+std::string EscapeDollor(const string& to_escape) {
+  return StringReplace(to_escape, "$", "\\$", true);
+}
+
+std::string BinaryToHex(const string& src) {
+  string dest;
+  size_t i;
+  unsigned char symbol[16] = {
+    '0', '1', '2', '3',
+    '4', '5', '6', '7',
+    '8', '9', 'a', 'b',
+    'c', 'd', 'e', 'f',
+  };
+
+  dest.resize(src.size() * 2);
+  char* append_ptr = &dest[0];
+
+  for (i = 0; i < src.size(); i++) {
+    *append_ptr++ = symbol[(src[i] & 0xf0) >> 4];
+    *append_ptr++ = symbol[src[i] & 0x0f];
+  }
+
+  return dest;
+}
+
+void Indent(io::Printer* printer) {
+  printer->Indent();
+  printer->Indent();
+}
+void Outdent(io::Printer* printer) {
+  printer->Outdent();
+  printer->Outdent();
+}
+
+void GenerateField(const FieldDescriptor* field, io::Printer* printer,
+                   bool is_descriptor) {
+  if (field->is_repeated()) {
+    GenerateFieldDocComment(printer, field, is_descriptor, kFieldProperty);
+    printer->Print(
+        "private $^name^;\n",
+        "name", field->name());
+  } else if (field->containing_oneof()) {
+    // Oneof fields are handled by GenerateOneofField.
+    return;
+  } else {
+    GenerateFieldDocComment(printer, field, is_descriptor, kFieldProperty);
+    printer->Print(
+        "private $^name^ = ^default^;\n",
+        "name", field->name(),
+        "default", DefaultForField(field));
+  }
+
+  if (is_descriptor) {
+    printer->Print(
+        "private $has_^name^ = false;\n",
+        "name", field->name());
+  }
+}
+
+void GenerateOneofField(const OneofDescriptor* oneof, io::Printer* printer) {
+  // Oneof property needs to be protected in order to be accessed by parent
+  // class in implementation.
+  printer->Print(
+      "protected $^name^;\n",
+      "name", oneof->name());
+}
+
+void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor,
+                           io::Printer* printer) {
+  const OneofDescriptor* oneof = field->containing_oneof();
+
+  // Generate getter.
+  if (oneof != NULL) {
+    GenerateFieldDocComment(printer, field, is_descriptor, kFieldGetter);
+    printer->Print(
+        "public function get^camel_name^()\n"
+        "{\n"
+        "    return $this->readOneof(^number^);\n"
+        "}\n\n",
+        "camel_name", UnderscoresToCamelCase(field->name(), true),
+        "number", IntToString(field->number()));
+  } else {
+    GenerateFieldDocComment(printer, field, is_descriptor, kFieldGetter);
+    printer->Print(
+        "public function get^camel_name^()\n"
+        "{\n"
+        "    return $this->^name^;\n"
+        "}\n\n",
+        "camel_name", UnderscoresToCamelCase(field->name(), true), "name",
+        field->name());
+  }
+
+  // Generate setter.
+  GenerateFieldDocComment(printer, field, is_descriptor, kFieldSetter);
+  printer->Print(
+      "public function set^camel_name^($var)\n"
+      "{\n",
+      "camel_name", UnderscoresToCamelCase(field->name(), true));
+
+  Indent(printer);
+
+  // Type check.
+  if (field->is_map()) {
+    const Descriptor* map_entry = field->message_type();
+    const FieldDescriptor* key = map_entry->FindFieldByName("key");
+    const FieldDescriptor* value = map_entry->FindFieldByName("value");
+    printer->Print(
+        "$arr = GPBUtil::checkMapField($var, "
+        "\\Google\\Protobuf\\Internal\\GPBType::^key_type^, "
+        "\\Google\\Protobuf\\Internal\\GPBType::^value_type^",
+        "key_type", ToUpper(key->type_name()),
+        "value_type", ToUpper(value->type_name()));
+    if (value->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      printer->Print(
+          ", \\^class_name^);\n",
+          "class_name",
+          FullClassName(value->message_type(), is_descriptor) + "::class");
+    } else if (value->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+      printer->Print(
+          ", \\^class_name^);\n",
+          "class_name",
+          FullClassName(value->enum_type(), is_descriptor) + "::class");
+    } else {
+      printer->Print(");\n");
+    }
+  } else if (field->is_repeated()) {
+    printer->Print(
+        "$arr = GPBUtil::checkRepeatedField($var, "
+        "\\Google\\Protobuf\\Internal\\GPBType::^type^",
+        "type", ToUpper(field->type_name()));
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      printer->Print(
+          ", \\^class_name^);\n",
+          "class_name",
+          FullClassName(field->message_type(), is_descriptor) + "::class");
+    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+      printer->Print(
+          ", \\^class_name^);\n",
+          "class_name",
+          FullClassName(field->enum_type(), is_descriptor) + "::class");
+    } else {
+      printer->Print(");\n");
+    }
+  } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+    printer->Print(
+        "GPBUtil::checkMessage($var, \\^class_name^::class);\n",
+        "class_name", LegacyFullClassName(field->message_type(), is_descriptor));
+  } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+    printer->Print(
+        "GPBUtil::checkEnum($var, \\^class_name^::class);\n",
+        "class_name", LegacyFullClassName(field->enum_type(), is_descriptor));
+  } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+    printer->Print(
+        "GPBUtil::checkString($var, ^utf8^);\n",
+        "utf8",
+        field->type() == FieldDescriptor::TYPE_STRING ? "True": "False");
+  } else {
+    printer->Print(
+        "GPBUtil::check^type^($var);\n",
+        "type", UnderscoresToCamelCase(field->cpp_type_name(), true));
+  }
+
+  if (oneof != NULL) {
+    printer->Print(
+        "$this->writeOneof(^number^, $var);\n",
+        "number", IntToString(field->number()));
+  } else if (field->is_repeated()) {
+    printer->Print(
+        "$this->^name^ = $arr;\n",
+        "name", field->name());
+  } else {
+    printer->Print(
+        "$this->^name^ = $var;\n",
+        "name", field->name());
+  }
+
+  // Set has bit for proto2 only.
+  if (is_descriptor) {
+    printer->Print(
+        "$this->has_^field_name^ = true;\n",
+        "field_name", field->name());
+  }
+
+  printer->Print("\nreturn $this;\n");
+
+  Outdent(printer);
+
+  printer->Print(
+      "}\n\n");
+
+  // Generate has method for proto2 only.
+  if (is_descriptor) {
+    printer->Print(
+        "public function has^camel_name^()\n"
+        "{\n"
+        "    return $this->has_^field_name^;\n"
+        "}\n\n",
+        "camel_name", UnderscoresToCamelCase(field->name(), true),
+        "field_name", field->name());
+  }
+}
+
+void GenerateEnumToPool(const EnumDescriptor* en, io::Printer* printer) {
+  printer->Print(
+      "$pool->addEnum('^name^', "
+      "\\Google\\Protobuf\\Internal\\^class_name^::class)\n",
+      "name", DescriptorFullName(en, true),
+      "class_name", en->name());
+  Indent(printer);
+
+  for (int i = 0; i < en->value_count(); i++) {
+    const EnumValueDescriptor* value = en->value(i);
+    printer->Print(
+        "->value(\"^name^\", ^number^)\n",
+        "name", ConstantNamePrefix(value->name()) + value->name(),
+        "number", IntToString(value->number()));
+  }
+  printer->Print("->finalizeToPool();\n\n");
+  Outdent(printer);
+}
+
+void GenerateServiceMethod(const MethodDescriptor* method,
+                           io::Printer* printer) {
+  printer->Print(
+        "public function ^camel_name^(\\^request_name^ $request);\n\n",
+        "camel_name", UnderscoresToCamelCase(method->name(), false),
+        "request_name", FullClassName(
+          method->input_type(), false)
+  );
+}
+
+void GenerateMessageToPool(const string& name_prefix, const Descriptor* message,
+                           io::Printer* printer) {
+  // Don't generate MapEntry messages -- we use the PHP extension's native
+  // support for map fields instead.
+  if (message->options().map_entry()) {
+    return;
+  }
+  string class_name = (name_prefix.empty() ? "" : name_prefix + "\\") +
+    ReservedNamePrefix(message->name(), message->file()) + message->name();
+
+  printer->Print(
+      "$pool->addMessage('^message^', "
+      "\\Google\\Protobuf\\Internal\\^class_name^::class)\n",
+      "message", DescriptorFullName(message, true),
+      "class_name", class_name);
+
+  Indent(printer);
+
+  for (int i = 0; i < message->field_count(); i++) {
+    const FieldDescriptor* field = message->field(i);
+    if (field->is_map()) {
+      const FieldDescriptor* key =
+          field->message_type()->FindFieldByName("key");
+      const FieldDescriptor* val =
+          field->message_type()->FindFieldByName("value");
+      printer->Print(
+          "->map('^field^', \\Google\\Protobuf\\Internal\\GPBType::^key^, "
+          "\\Google\\Protobuf\\Internal\\GPBType::^value^, ^number^^other^)\n",
+          "field", field->name(),
+          "key", ToUpper(key->type_name()),
+          "value", ToUpper(val->type_name()),
+          "number", SimpleItoa(field->number()),
+          "other", EnumOrMessageSuffix(val, true));
+    } else if (!field->containing_oneof()) {
+      printer->Print(
+          "->^label^('^field^', "
+          "\\Google\\Protobuf\\Internal\\GPBType::^type^, ^number^^other^)\n",
+          "field", field->name(),
+          "label", LabelForField(field),
+          "type", ToUpper(field->type_name()),
+          "number", SimpleItoa(field->number()),
+          "other", EnumOrMessageSuffix(field, true));
+    }
+  }
+
+  // oneofs.
+  for (int i = 0; i < message->oneof_decl_count(); i++) {
+    const OneofDescriptor* oneof = message->oneof_decl(i);
+    printer->Print("->oneof(^name^)\n",
+                   "name", oneof->name());
+    Indent(printer);
+    for (int index = 0; index < oneof->field_count(); index++) {
+      const FieldDescriptor* field = oneof->field(index);
+      printer->Print(
+          "->value('^field^', "
+          "\\Google\\Protobuf\\Internal\\GPBType::^type^, ^number^^other^)\n",
+          "field", field->name(),
+          "type", ToUpper(field->type_name()),
+          "number", SimpleItoa(field->number()),
+          "other", EnumOrMessageSuffix(field, true));
+    }
+    printer->Print("->finish()\n");
+    Outdent(printer);
+  }
+
+  printer->Print(
+      "->finalizeToPool();\n");
+
+  Outdent(printer);
+
+  printer->Print(
+      "\n");
+
+  for (int i = 0; i < message->nested_type_count(); i++) {
+    GenerateMessageToPool(class_name, message->nested_type(i), printer);
+  }
+  for (int i = 0; i < message->enum_type_count(); i++) {
+    GenerateEnumToPool(message->enum_type(i), printer);
+  }
+}
+
+void GenerateAddFileToPool(const FileDescriptor* file, bool is_descriptor,
+                           io::Printer* printer) {
+    printer->Print(
+        "public static $is_initialized = false;\n\n"
+        "public static function initOnce() {\n");
+    Indent(printer);
+
+    printer->Print(
+        "$pool = \\Google\\Protobuf\\Internal\\"
+        "DescriptorPool::getGeneratedPool();\n\n"
+        "if (static::$is_initialized == true) {\n"
+        "  return;\n"
+        "}\n");
+
+  if (is_descriptor) {
+    for (int i = 0; i < file->message_type_count(); i++) {
+      GenerateMessageToPool("", file->message_type(i), printer);
+    }
+    for (int i = 0; i < file->enum_type_count(); i++) {
+      GenerateEnumToPool(file->enum_type(i), printer);
+    }
+
+    printer->Print(
+        "$pool->finish();\n");
+  } else {
+    for (int i = 0; i < file->dependency_count(); i++) {
+      const std::string& name = file->dependency(i)->name();
+      // Currently, descriptor.proto is not ready for external usage. Skip to
+      // import it for now, so that its dependencies can still work as long as
+      // they don't use protos defined in descriptor.proto.
+      if (name == kDescriptorFile) {
+        continue;
+      }
+      std::string dependency_filename =
+          GeneratedMetadataFileName(file->dependency(i), is_descriptor);
+      printer->Print(
+          "\\^name^::initOnce();\n",
+          "name", FilenameToClassname(dependency_filename));
+    }
+
+    // Add messages and enums to descriptor pool.
+    FileDescriptorSet files;
+    FileDescriptorProto* file_proto = files.add_file();
+    file->CopyTo(file_proto);
+
+    // Filter out descriptor.proto as it cannot be depended on for now.
+    RepeatedPtrField<string>* dependency = file_proto->mutable_dependency();
+    for (RepeatedPtrField<string>::iterator it = dependency->begin();
+         it != dependency->end(); ++it) {
+      if (*it != kDescriptorFile) {
+        dependency->erase(it);
+        break;
+      }
+    }
+
+    // Filter out all extensions, since we do not support extension yet.
+    file_proto->clear_extension();
+    RepeatedPtrField<DescriptorProto>* message_type =
+        file_proto->mutable_message_type();
+    for (RepeatedPtrField<DescriptorProto>::iterator it = message_type->begin();
+         it != message_type->end(); ++it) {
+      it->clear_extension();
+    }
+
+    string files_data;
+    files.SerializeToString(&files_data);
+
+    printer->Print("$pool->internalAddGeneratedFile(hex2bin(\n");
+    Indent(printer);
+
+    // Only write 30 bytes per line.
+    static const int kBytesPerLine = 30;
+    for (int i = 0; i < files_data.size(); i += kBytesPerLine) {
+      printer->Print(
+          "\"^data^\"^dot^\n",
+          "data", BinaryToHex(files_data.substr(i, kBytesPerLine)),
+          "dot", i + kBytesPerLine < files_data.size() ? " ." : "");
+    }
+
+    Outdent(printer);
+    printer->Print(
+        "));\n\n");
+  }
+  printer->Print(
+      "static::$is_initialized = true;\n");
+  Outdent(printer);
+  printer->Print("}\n");
+}
+
+void GenerateUseDeclaration(bool is_descriptor, io::Printer* printer) {
+  if (!is_descriptor) {
+    printer->Print(
+        "use Google\\Protobuf\\Internal\\GPBType;\n"
+        "use Google\\Protobuf\\Internal\\RepeatedField;\n"
+        "use Google\\Protobuf\\Internal\\GPBUtil;\n\n");
+  } else {
+    printer->Print(
+        "use Google\\Protobuf\\Internal\\GPBType;\n"
+        "use Google\\Protobuf\\Internal\\GPBWire;\n"
+        "use Google\\Protobuf\\Internal\\RepeatedField;\n"
+        "use Google\\Protobuf\\Internal\\InputStream;\n"
+        "use Google\\Protobuf\\Internal\\GPBUtil;\n\n");
+  }
+}
+
+void GenerateHead(const FileDescriptor* file, io::Printer* printer) {
+  printer->Print(
+    "<?php\n"
+    "# Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+    "# source: ^filename^\n"
+    "\n",
+    "filename", file->name());
+}
+
+std::string FilenameToClassname(const string& filename) {
+  int lastindex = filename.find_last_of(".");
+  std::string result = filename.substr(0, lastindex);
+  for (int i = 0; i < result.size(); i++) {
+    if (result[i] == '/') {
+      result[i] = '\\';
+    }
+  }
+  return result;
+}
+
+void GenerateMetadataFile(const FileDescriptor* file,
+                          bool is_descriptor,
+                          GeneratorContext* generator_context) {
+  std::string filename = GeneratedMetadataFileName(file, is_descriptor);
+  std::unique_ptr<io::ZeroCopyOutputStream> output(
+      generator_context->Open(filename));
+  io::Printer printer(output.get(), '^');
+
+  GenerateHead(file, &printer);
+
+  std::string fullname = FilenameToClassname(filename);
+  int lastindex = fullname.find_last_of("\\");
+
+  if (lastindex != string::npos) {
+    printer.Print(
+        "namespace ^name^;\n\n",
+        "name", fullname.substr(0, lastindex));
+
+    printer.Print(
+        "class ^name^\n"
+        "{\n",
+        "name", fullname.substr(lastindex + 1));
+  } else {
+    printer.Print(
+        "class ^name^\n"
+        "{\n",
+        "name", fullname);
+  }
+  Indent(&printer);
+
+  GenerateAddFileToPool(file, is_descriptor, &printer);
+
+  Outdent(&printer);
+  printer.Print("}\n\n");
+}
+
+template <typename DescriptorType>
+void LegacyGenerateClassFile(const FileDescriptor* file, const DescriptorType* desc,
+                         bool is_descriptor,
+                         GeneratorContext* generator_context) {
+
+  std::string filename = LegacyGeneratedClassFileName(desc, is_descriptor);
+  std::unique_ptr<io::ZeroCopyOutputStream> output(
+      generator_context->Open(filename));
+  io::Printer printer(output.get(), '^');
+
+  GenerateHead(file, &printer);
+
+  std::string php_namespace = RootPhpNamespace(desc, is_descriptor);
+  if (php_namespace != "") {
+    printer.Print(
+        "namespace ^name^;\n\n",
+        "name", php_namespace);
+  }
+  std::string newname = FullClassName(desc, is_descriptor);
+  printer.Print("if (false) {\n");
+  Indent(&printer);
+  printer.Print("/**\n");
+  printer.Print(" * This class is deprecated. Use ^new^ instead.\n",
+      "new", newname);
+  printer.Print(" * @deprecated\n");
+  printer.Print(" */\n");
+  printer.Print("class ^old^ {}\n",
+      "old", LegacyGeneratedClassName(desc));
+  Outdent(&printer);
+  printer.Print("}\n");
+  printer.Print("class_exists(^new^::class);\n",
+      "new", GeneratedClassNameImpl(desc));
+  printer.Print("@trigger_error('^old^ is deprecated and will be removed in "
+      "the next major release. Use ^fullname^ instead', E_USER_DEPRECATED);\n\n",
+      "old", LegacyFullClassName(desc, is_descriptor),
+      "fullname", newname);
+}
+
+void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en,
+                      bool is_descriptor, GeneratorContext* generator_context) {
+  std::string filename = GeneratedClassFileName(en, is_descriptor);
+  std::unique_ptr<io::ZeroCopyOutputStream> output(
+      generator_context->Open(filename));
+  io::Printer printer(output.get(), '^');
+
+  GenerateHead(file, &printer);
+
+  std::string fullname = FilenameToClassname(filename);
+  int lastindex = fullname.find_last_of("\\");
+
+  if (lastindex != string::npos) {
+    printer.Print(
+        "namespace ^name^;\n\n",
+        "name", fullname.substr(0, lastindex));
+  }
+
+  if (lastindex != string::npos) {
+    fullname = fullname.substr(lastindex + 1);
+  }
+
+  GenerateEnumDocComment(&printer, en, is_descriptor);
+
+  printer.Print(
+      "class ^name^\n"
+      "{\n",
+      "name", fullname);
+  Indent(&printer);
+
+  for (int i = 0; i < en->value_count(); i++) {
+    const EnumValueDescriptor* value = en->value(i);
+    GenerateEnumValueDocComment(&printer, value);
+    printer.Print("const ^name^ = ^number^;\n",
+                  "name", ConstantNamePrefix(value->name()) + value->name(),
+                  "number", IntToString(value->number()));
+  }
+
+  Outdent(&printer);
+  printer.Print("}\n\n");
+
+  // write legacy file for backwards compatiblity with nested messages and enums
+  if (en->containing_type() != NULL) {
+    printer.Print(
+        "// Adding a class alias for backwards compatibility with the previous class name.\n");
+    printer.Print(
+        "class_alias(^new^::class, \\^old^::class);\n\n",
+        "new", fullname,
+        "old", LegacyFullClassName(en, is_descriptor));
+    LegacyGenerateClassFile(file, en, is_descriptor, generator_context);
+  }
+}
+
+void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
+                         bool is_descriptor,
+                         GeneratorContext* generator_context) {
+  // Don't generate MapEntry messages -- we use the PHP extension's native
+  // support for map fields instead.
+  if (message->options().map_entry()) {
+    return;
+  }
+
+  std::string filename = GeneratedClassFileName(message, is_descriptor);
+  std::unique_ptr<io::ZeroCopyOutputStream> output(
+      generator_context->Open(filename));
+  io::Printer printer(output.get(), '^');
+
+  GenerateHead(file, &printer);
+
+  std::string fullname = FilenameToClassname(filename);
+  int lastindex = fullname.find_last_of("\\");
+
+  if (lastindex != string::npos) {
+    printer.Print(
+        "namespace ^name^;\n\n",
+        "name", fullname.substr(0, lastindex));
+  }
+
+  GenerateUseDeclaration(is_descriptor, &printer);
+
+  GenerateMessageDocComment(&printer, message, is_descriptor);
+  if (lastindex != string::npos) {
+    fullname = fullname.substr(lastindex + 1);
+  }
+
+  printer.Print(
+      "class ^name^ extends \\Google\\Protobuf\\Internal\\Message\n"
+      "{\n",
+      "name", fullname);
+  Indent(&printer);
+
+  // Field and oneof definitions.
+  for (int i = 0; i < message->field_count(); i++) {
+    const FieldDescriptor* field = message->field(i);
+    GenerateField(field, &printer, is_descriptor);
+  }
+  for (int i = 0; i < message->oneof_decl_count(); i++) {
+    const OneofDescriptor* oneof = message->oneof_decl(i);
+    GenerateOneofField(oneof, &printer);
+  }
+  printer.Print("\n");
+
+  GenerateMessageConstructorDocComment(&printer, message, is_descriptor);
+  printer.Print(
+      "public function __construct($data = NULL) {\n");
+  Indent(&printer);
+
+  std::string metadata_filename =
+      GeneratedMetadataFileName(file, is_descriptor);
+  std::string metadata_fullname = FilenameToClassname(metadata_filename);
+  printer.Print(
+      "\\^fullname^::initOnce();\n"
+      "parent::__construct($data);\n",
+      "fullname", metadata_fullname);
+
+  Outdent(&printer);
+  printer.Print("}\n\n");
+
+  // Field and oneof accessors.
+  for (int i = 0; i < message->field_count(); i++) {
+    const FieldDescriptor* field = message->field(i);
+    GenerateFieldAccessor(field, is_descriptor, &printer);
+  }
+  for (int i = 0; i < message->oneof_decl_count(); i++) {
+    const OneofDescriptor* oneof = message->oneof_decl(i);
+    printer.Print(
+      "/**\n"
+      " * @return string\n"
+      " */\n"
+      "public function get^camel_name^()\n"
+      "{\n"
+      "    return $this->whichOneof(\"^name^\");\n"
+      "}\n\n",
+      "camel_name", UnderscoresToCamelCase(oneof->name(), true), "name",
+      oneof->name());
+  }
+
+  Outdent(&printer);
+  printer.Print("}\n\n");
+
+  // write legacy file for backwards compatiblity with nested messages and enums
+  if (message->containing_type() != NULL) {
+    printer.Print(
+        "// Adding a class alias for backwards compatibility with the previous class name.\n");
+    printer.Print(
+        "class_alias(^new^::class, \\^old^::class);\n\n",
+        "new", fullname,
+        "old", LegacyFullClassName(message, is_descriptor));
+    LegacyGenerateClassFile(file, message, is_descriptor, generator_context);
+  }
+
+  // Nested messages and enums.
+  for (int i = 0; i < message->nested_type_count(); i++) {
+    GenerateMessageFile(file, message->nested_type(i), is_descriptor,
+                        generator_context);
+  }
+  for (int i = 0; i < message->enum_type_count(); i++) {
+    GenerateEnumFile(file, message->enum_type(i), is_descriptor,
+                     generator_context);
+  }
+}
+
+void GenerateServiceFile(const FileDescriptor* file,
+  const ServiceDescriptor* service, bool is_descriptor,
+  GeneratorContext* generator_context) {
+  std::string filename = GeneratedServiceFileName(service, is_descriptor);
+  std::unique_ptr<io::ZeroCopyOutputStream> output(
+      generator_context->Open(filename));
+  io::Printer printer(output.get(), '^');
+
+  GenerateHead(file, &printer);
+
+  std::string fullname = FilenameToClassname(filename);
+  int lastindex = fullname.find_last_of("\\");
+
+  if (!file->options().php_namespace().empty() ||
+      (!file->options().has_php_namespace() && !file->package().empty()) ||
+      lastindex != string::npos) {
+    printer.Print(
+        "namespace ^name^;\n\n",
+        "name", fullname.substr(0, lastindex));
+  }
+
+  GenerateServiceDocComment(&printer, service);
+
+  if (lastindex != string::npos) {
+      printer.Print(
+        "interface ^name^\n"
+        "{\n",
+        "name", fullname.substr(lastindex + 1));
+  } else {
+      printer.Print(
+        "interface ^name^\n"
+        "{\n",
+        "name", fullname);
+  }
+
+  Indent(&printer);
+
+  for (int i = 0; i < service->method_count(); i++) {
+    const MethodDescriptor* method = service->method(i);
+    GenerateServiceMethodDocComment(&printer, method);
+    GenerateServiceMethod(method, &printer);
+  }
+
+  Outdent(&printer);
+  printer.Print("}\n\n");
+}
+
+void GenerateFile(const FileDescriptor* file, bool is_descriptor,
+                  GeneratorContext* generator_context) {
+  GenerateMetadataFile(file, is_descriptor, generator_context);
+  for (int i = 0; i < file->message_type_count(); i++) {
+    GenerateMessageFile(file, file->message_type(i), is_descriptor,
+                        generator_context);
+  }
+  for (int i = 0; i < file->enum_type_count(); i++) {
+    GenerateEnumFile(file, file->enum_type(i), is_descriptor,
+                     generator_context);
+  }
+  if (file->options().php_generic_services()) {
+    for (int i = 0; i < file->service_count(); i++) {
+      GenerateServiceFile(file, file->service(i), is_descriptor,
+                       generator_context);
+    }
+  }
+}
+
+static string EscapePhpdoc(const string& input) {
+  string result;
+  result.reserve(input.size() * 2);
+
+  char prev = '*';
+
+  for (string::size_type i = 0; i < input.size(); i++) {
+    char c = input[i];
+    switch (c) {
+      case '*':
+        // Avoid "/*".
+        if (prev == '/') {
+          result.append("&#42;");
+        } else {
+          result.push_back(c);
+        }
+        break;
+      case '/':
+        // Avoid "*/".
+        if (prev == '*') {
+          result.append("&#47;");
+        } else {
+          result.push_back(c);
+        }
+        break;
+      case '@':
+        // '@' starts phpdoc tags including the @deprecated tag, which will
+        // cause a compile-time error if inserted before a declaration that
+        // does not have a corresponding @Deprecated annotation.
+        result.append("&#64;");
+        break;
+      default:
+        result.push_back(c);
+        break;
+    }
+
+    prev = c;
+  }
+
+  return result;
+}
+
+static void GenerateDocCommentBodyForLocation(
+    io::Printer* printer, const SourceLocation& location, bool trailingNewline,
+    int indentCount) {
+  string comments = location.leading_comments.empty() ?
+      location.trailing_comments : location.leading_comments;
+  if (!comments.empty()) {
+    // TODO(teboring):  Ideally we should parse the comment text as Markdown and
+    //   write it back as HTML, but this requires a Markdown parser.  For now
+    //   we just use the proto comments unchanged.
+
+    // If the comment itself contains block comment start or end markers,
+    // HTML-escape them so that they don't accidentally close the doc comment.
+    comments = EscapePhpdoc(comments);
+
+    std::vector<string> lines = Split(comments, "\n");
+    while (!lines.empty() && lines.back().empty()) {
+      lines.pop_back();
+    }
+
+    for (int i = 0; i < lines.size(); i++) {
+      // Most lines should start with a space.  Watch out for lines that start
+      // with a /, since putting that right after the leading asterisk will
+      // close the comment.
+      if (indentCount == 0 && !lines[i].empty() && lines[i][0] == '/') {
+        printer->Print(" * ^line^\n", "line", lines[i]);
+      } else {
+        std::string indent = std::string(indentCount, ' ');
+        printer->Print(" *^ind^^line^\n", "ind", indent, "line", lines[i]);
+      }
+    }
+    if (trailingNewline) {
+      printer->Print(" *\n");
+    }
+  }
+}
+
+template <typename DescriptorType>
+static void GenerateDocCommentBody(
+    io::Printer* printer, const DescriptorType* descriptor) {
+  SourceLocation location;
+  if (descriptor->GetSourceLocation(&location)) {
+    GenerateDocCommentBodyForLocation(printer, location, true, 0);
+  }
+}
+
+static string FirstLineOf(const string& value) {
+  string result = value;
+
+  string::size_type pos = result.find_first_of('\n');
+  if (pos != string::npos) {
+    result.erase(pos);
+  }
+
+  return result;
+}
+
+void GenerateMessageDocComment(io::Printer* printer,
+                               const Descriptor* message, int is_descriptor) {
+  printer->Print("/**\n");
+  GenerateDocCommentBody(printer, message);
+  printer->Print(
+    " * Generated from protobuf message <code>^messagename^</code>\n"
+    " */\n",
+    "fullname", EscapePhpdoc(FullClassName(message, is_descriptor)),
+    "messagename", EscapePhpdoc(message->full_name()));
+}
+
+void GenerateMessageConstructorDocComment(io::Printer* printer,
+                                          const Descriptor* message,
+                                          int is_descriptor) {
+  // In theory we should have slightly different comments for setters, getters,
+  // etc., but in practice everyone already knows the difference between these
+  // so it's redundant information.
+
+  // We start the comment with the main body based on the comments from the
+  // .proto file (if present). We then end with the field declaration, e.g.:
+  //   optional string foo = 5;
+  // If the field is a group, the debug string might end with {.
+  printer->Print("/**\n");
+  printer->Print(" * Constructor.\n");
+  printer->Print(" *\n");
+  printer->Print(" * @param array $data {\n");
+  printer->Print(" *     Optional. Data for populating the Message object.\n");
+  printer->Print(" *\n");
+  for (int i = 0; i < message->field_count(); i++) {
+    const FieldDescriptor* field = message->field(i);
+    printer->Print(" *     @type ^php_type^ $^var^\n",
+      "php_type", PhpSetterTypeName(field, is_descriptor),
+      "var", field->name());
+    SourceLocation location;
+    if (field->GetSourceLocation(&location)) {
+      GenerateDocCommentBodyForLocation(printer, location, false, 10);
+    }
+  }
+  printer->Print(" * }\n");
+  printer->Print(" */\n");
+}
+
+void GenerateServiceDocComment(io::Printer* printer,
+                               const ServiceDescriptor* service) {
+  printer->Print("/**\n");
+  GenerateDocCommentBody(printer, service);
+  printer->Print(
+    " * Protobuf type <code>^fullname^</code>\n"
+    " */\n",
+    "fullname", EscapePhpdoc(service->full_name()));
+}
+
+void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field,
+                             int is_descriptor, int function_type) {
+  // In theory we should have slightly different comments for setters, getters,
+  // etc., but in practice everyone already knows the difference between these
+  // so it's redundant information.
+
+  // We start the comment with the main body based on the comments from the
+  // .proto file (if present). We then end with the field declaration, e.g.:
+  //   optional string foo = 5;
+  // If the field is a group, the debug string might end with {.
+  printer->Print("/**\n");
+  GenerateDocCommentBody(printer, field);
+  printer->Print(
+    " * Generated from protobuf field <code>^def^</code>\n",
+    "def", EscapePhpdoc(FirstLineOf(field->DebugString())));
+  if (function_type == kFieldSetter) {
+    printer->Print(" * @param ^php_type^ $var\n",
+      "php_type", PhpSetterTypeName(field, is_descriptor));
+    printer->Print(" * @return $this\n");
+  } else if (function_type == kFieldGetter) {
+    printer->Print(" * @return ^php_type^\n",
+      "php_type", PhpGetterTypeName(field, is_descriptor));
+  }
+  printer->Print(" */\n");
+}
+
+void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_,
+                            int is_descriptor) {
+  printer->Print("/**\n");
+  GenerateDocCommentBody(printer, enum_);
+  printer->Print(
+    " * Protobuf type <code>^fullname^</code>\n"
+    " */\n",
+    "fullname", EscapePhpdoc(enum_->full_name()));
+}
+
+void GenerateEnumValueDocComment(io::Printer* printer,
+                                 const EnumValueDescriptor* value) {
+  printer->Print("/**\n");
+  GenerateDocCommentBody(printer, value);
+  printer->Print(
+    " * Generated from protobuf enum <code>^def^</code>\n"
+    " */\n",
+    "def", EscapePhpdoc(FirstLineOf(value->DebugString())));
+}
+
+void GenerateServiceMethodDocComment(io::Printer* printer,
+                              const MethodDescriptor* method) {
+  printer->Print("/**\n");
+  GenerateDocCommentBody(printer, method);
+  printer->Print(
+    " * Method <code>^method_name^</code>\n"
+    " *\n",
+    "method_name", EscapePhpdoc(UnderscoresToCamelCase(method->name(), false)));
+  printer->Print(
+    " * @param \\^input_type^ $request\n",
+    "input_type", EscapePhpdoc(FullClassName(method->input_type(), false)));
+  printer->Print(
+    " * @return \\^return_type^\n"
+    " */\n",
+    "return_type", EscapePhpdoc(FullClassName(method->output_type(), false)));
+}
+
+bool Generator::Generate(const FileDescriptor* file, const string& parameter,
+                         GeneratorContext* generator_context,
+                         string* error) const {
+  bool is_descriptor = parameter == "internal";
+
+  if (is_descriptor && file->name() != kDescriptorFile) {
+    *error =
+        "Can only generate PHP code for google/protobuf/descriptor.proto.\n";
+    return false;
+  }
+
+  if (!is_descriptor && file->syntax() != FileDescriptor::SYNTAX_PROTO3) {
+    *error =
+        "Can only generate PHP code for proto3 .proto files.\n"
+        "Please add 'syntax = \"proto3\";' to the top of your .proto file.\n";
+    return false;
+  }
+
+  GenerateFile(file, is_descriptor, generator_context);
+
+  return true;
+}
+
+}  // namespace php
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.h b/src/google/protobuf/compiler/php/php_generator.h
similarity index 61%
copy from src/google/protobuf/compiler/javanano/javanano_extension.h
copy to src/google/protobuf/compiler/php/php_generator.h
index 4843e29..b851d9b 100644
--- a/src/google/protobuf/compiler/javanano/javanano_extension.h
+++ b/src/google/protobuf/compiler/php/php_generator.h
@@ -1,6 +1,6 @@
 // Protocol Buffers - Google's data interchange format
 // Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
+// https://developers.google.com/protocol-buffers/
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -28,47 +28,41 @@
 // (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: bduff@google.com (Brian Duff)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
+#ifndef GOOGLE_PROTOBUF_COMPILER_PHP_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_PHP_GENERATOR_H__
 
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
-#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/descriptor.h>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/javanano/javanano_params.h>
-#include <google/protobuf/descriptor.pb.h>
-
+#include <string>
 
 namespace google {
 namespace protobuf {
-  namespace io {
-    class Printer;             // printer.h
-  }
-}
-
-namespace protobuf {
 namespace compiler {
-namespace javanano {
+namespace php {
 
-class ExtensionGenerator {
- public:
-  explicit ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params);
-  ~ExtensionGenerator();
-
-  void Generate(io::Printer* printer) const;
-
- private:
-  const Params& params_;
-  const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
+class LIBPROTOC_EXPORT Generator
+    : public google::protobuf::compiler::CodeGenerator {
+  virtual bool Generate(
+      const FileDescriptor* file,
+      const string& parameter,
+      GeneratorContext* generator_context,
+      string* error) const;
 };
 
-}  // namespace javanano
+// To skip reserved keywords in php, some generated classname are prefixed.
+// Other code generators may need following API to figure out the actual
+// classname.
+LIBPROTOC_EXPORT std::string GeneratedClassName(
+    const google::protobuf::Descriptor* desc);
+LIBPROTOC_EXPORT std::string GeneratedClassName(
+    const google::protobuf::EnumDescriptor* desc);
+LIBPROTOC_EXPORT std::string GeneratedClassName(
+    const google::protobuf::ServiceDescriptor* desc);
+
+}  // namespace php
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
 
-#endif  // GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
+#endif  // GOOGLE_PROTOBUF_COMPILER_PHP_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc
index 2bebf1f..9c1c757 100644
--- a/src/google/protobuf/compiler/plugin.cc
+++ b/src/google/protobuf/compiler/plugin.cc
@@ -36,14 +36,7 @@
 #include <set>
 
 #ifdef _WIN32
-#include <io.h>
 #include <fcntl.h>
-#ifndef STDIN_FILENO
-#define STDIN_FILENO 0
-#endif
-#ifndef STDOUT_FILENO
-#define STDOUT_FILENO 1
-#endif
 #else
 #include <unistd.h>
 #endif
@@ -52,19 +45,29 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/plugin.pb.h>
 #include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/descriptor.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/stubs/io_win32.h>
 
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 
+#if defined(_WIN32)
+// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
+// them like we do below.
+using google::protobuf::internal::win32::setmode;
+#endif
+
 class GeneratorResponseContext : public GeneratorContext {
  public:
-  GeneratorResponseContext(CodeGeneratorResponse* response,
-                           const vector<const FileDescriptor*>& parsed_files)
-      : response_(response),
+  GeneratorResponseContext(
+      const Version& compiler_version,
+      CodeGeneratorResponse* response,
+      const std::vector<const FileDescriptor*>& parsed_files)
+      : compiler_version_(compiler_version),
+        response_(response),
         parsed_files_(parsed_files) {}
   virtual ~GeneratorResponseContext() {}
 
@@ -84,15 +87,62 @@
     return new io::StringOutputStream(file->mutable_content());
   }
 
-  void ListParsedFiles(vector<const FileDescriptor*>* output) {
+  void ListParsedFiles(std::vector<const FileDescriptor*>* output) {
     *output = parsed_files_;
   }
 
+  void GetCompilerVersion(Version* version) const {
+    *version = compiler_version_;
+  }
+
  private:
+  Version compiler_version_;
   CodeGeneratorResponse* response_;
-  const vector<const FileDescriptor*>& parsed_files_;
+  const std::vector<const FileDescriptor*>& parsed_files_;
 };
 
+bool GenerateCode(const CodeGeneratorRequest& request,
+    const CodeGenerator& generator, CodeGeneratorResponse* response,
+    string* error_msg) {
+  DescriptorPool pool;
+  for (int i = 0; i < request.proto_file_size(); i++) {
+    const FileDescriptor* file = pool.BuildFile(request.proto_file(i));
+    if (file == NULL) {
+      // BuildFile() already wrote an error message.
+      return false;
+    }
+  }
+
+  std::vector<const FileDescriptor*> parsed_files;
+  for (int i = 0; i < request.file_to_generate_size(); i++) {
+    parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i)));
+    if (parsed_files.back() == NULL) {
+      *error_msg = "protoc asked plugin to generate a file but "
+                   "did not provide a descriptor for the file: " +
+                   request.file_to_generate(i);
+      return false;
+    }
+  }
+
+  GeneratorResponseContext context(
+      request.compiler_version(), response, parsed_files);
+
+
+  string error;
+  bool succeeded = generator.GenerateAll(
+      parsed_files, request.parameter(), &context, &error);
+
+  if (!succeeded && error.empty()) {
+    error = "Code generator returned false but provided no error "
+            "description.";
+  }
+  if (!error.empty()) {
+    response->set_error(error);
+  }
+
+  return true;
+}
+
 int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
 
   if (argc > 1) {
@@ -101,8 +151,8 @@
   }
 
 #ifdef _WIN32
-  _setmode(STDIN_FILENO, _O_BINARY);
-  _setmode(STDOUT_FILENO, _O_BINARY);
+  setmode(STDIN_FILENO, _O_BINARY);
+  setmode(STDOUT_FILENO, _O_BINARY);
 #endif
 
   CodeGeneratorRequest request;
@@ -112,62 +162,18 @@
     return 1;
   }
 
-  DescriptorPool pool;
-  for (int i = 0; i < request.proto_file_size(); i++) {
-    const FileDescriptor* file = pool.BuildFile(request.proto_file(i));
-    if (file == NULL) {
-      // BuildFile() already wrote an error message.
-      return 1;
-    }
-  }
-
-  vector<const FileDescriptor*> parsed_files;
-  for (int i = 0; i < request.file_to_generate_size(); i++) {
-    parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i)));
-    if (parsed_files.back() == NULL) {
-      std::cerr << argv[0] << ": protoc asked plugin to generate a file but "
-                              "did not provide a descriptor for the file: "
-                << request.file_to_generate(i) << std::endl;
-      return 1;
-    }
-  }
-
+  string error_msg;
   CodeGeneratorResponse response;
-  GeneratorResponseContext context(&response, parsed_files);
 
-  if (generator->HasGenerateAll()) {
-    string error;
-    bool succeeded = generator->GenerateAll(
-        parsed_files, request.parameter(), &context, &error);
-
-    if (!succeeded && error.empty()) {
-      error = "Code generator returned false but provided no error "
-              "description.";
-    }
-    if (!error.empty()) {
-      response.set_error(error);
+  if (GenerateCode(request, *generator, &response, &error_msg)) {
+    if (!response.SerializeToFileDescriptor(STDOUT_FILENO)) {
+      std::cerr << argv[0] << ": Error writing to stdout." << std::endl;
+      return 1;
     }
   } else {
-    for (int i = 0; i < parsed_files.size(); i++) {
-      const FileDescriptor* file = parsed_files[i];
-
-      string error;
-      bool succeeded = generator->Generate(
-          file, request.parameter(), &context, &error);
-
-      if (!succeeded && error.empty()) {
-        error = "Code generator returned false but provided no error "
-                "description.";
-      }
-      if (!error.empty()) {
-        response.set_error(file->name() + ": " + error);
-        break;
-      }
+    if (!error_msg.empty()) {
+      std::cerr << argv[0] << ": " << error_msg << std::endl;
     }
-  }
-
-  if (!response.SerializeToFileDescriptor(STDOUT_FILENO)) {
-    std::cerr << argv[0] << ": Error writing to stdout." << std::endl;
     return 1;
   }
 
diff --git a/src/google/protobuf/compiler/plugin.h b/src/google/protobuf/compiler/plugin.h
index 679f9bd..d2793a9 100644
--- a/src/google/protobuf/compiler/plugin.h
+++ b/src/google/protobuf/compiler/plugin.h
@@ -40,6 +40,13 @@
 //   }
 // You must link your plugin against libprotobuf and libprotoc.
 //
+// The core part of PluginMain is to invoke the given CodeGenerator on a
+// CodeGeneratorRequest to generate a CodeGeneratorResponse. This part is
+// abstracted out and made into function GenerateCode so that it can be reused,
+// for example, to implement a variant of PluginMain that does some
+// preprocessing on the input CodeGeneratorRequest before feeding the request
+// to the given code generator.
+//
 // To get protoc to use the plugin, do one of the following:
 // * Place the plugin binary somewhere in the PATH and give it the name
 //   "protoc-gen-NAME" (replacing "NAME" with the name of your plugin).  If you
@@ -55,16 +62,27 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
 #define GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
 
+#include <string>
+
 #include <google/protobuf/stubs/common.h>
 namespace google {
 namespace protobuf {
 namespace compiler {
 
 class CodeGenerator;    // code_generator.h
+class CodeGeneratorRequest;
+class CodeGeneratorResponse;
 
 // Implements main() for a protoc plugin exposing the given code generator.
 LIBPROTOC_EXPORT int PluginMain(int argc, char* argv[], const CodeGenerator* generator);
 
+// Generates code using the given code generator. Returns true if the code
+// generation is successful. If the code geneartion fails, error_msg may be
+// populated to describe the failure cause.
+bool GenerateCode(const CodeGeneratorRequest& request,
+    const CodeGenerator& generator, CodeGeneratorResponse* response,
+    string* error_msg);
+
 }  // namespace compiler
 }  // namespace protobuf
 
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index a2da8ee..ef52def 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -1,206 +1,668 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/compiler/plugin.proto
 
-#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
 #include <google/protobuf/compiler/plugin.pb.h>
 
 #include <algorithm>
 
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/port.h>
-#include <google/protobuf/stubs/once.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/wire_format_lite_inl.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/reflection_ops.h>
 #include <google/protobuf/wire_format.h>
+// This is a temporary google only hack
+#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
+#include "third_party/protobuf/version.h"
+#endif
 // @@protoc_insertion_point(includes)
 
+namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto {
+extern PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_CodeGeneratorResponse_File;
+extern PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_Version;
+}  // namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto
+namespace protobuf_google_2fprotobuf_2fdescriptor_2eproto {
+extern PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fdescriptor_2eproto ::google::protobuf::internal::SCCInfo<6> scc_info_FileDescriptorProto;
+}  // namespace protobuf_google_2fprotobuf_2fdescriptor_2eproto
+namespace google {
+namespace protobuf {
+namespace compiler {
+class VersionDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<Version>
+      _instance;
+} _Version_default_instance_;
+class CodeGeneratorRequestDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorRequest>
+      _instance;
+} _CodeGeneratorRequest_default_instance_;
+class CodeGeneratorResponse_FileDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorResponse_File>
+      _instance;
+} _CodeGeneratorResponse_File_default_instance_;
+class CodeGeneratorResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorResponse>
+      _instance;
+} _CodeGeneratorResponse_default_instance_;
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto {
+static void InitDefaultsVersion() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::google::protobuf::compiler::_Version_default_instance_;
+    new (ptr) ::google::protobuf::compiler::Version();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::google::protobuf::compiler::Version::InitAsDefaultInstance();
+}
+
+LIBPROTOC_EXPORT ::google::protobuf::internal::SCCInfo<0> scc_info_Version =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsVersion}, {}};
+
+static void InitDefaultsCodeGeneratorRequest() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::google::protobuf::compiler::_CodeGeneratorRequest_default_instance_;
+    new (ptr) ::google::protobuf::compiler::CodeGeneratorRequest();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::google::protobuf::compiler::CodeGeneratorRequest::InitAsDefaultInstance();
+}
+
+LIBPROTOC_EXPORT ::google::protobuf::internal::SCCInfo<2> scc_info_CodeGeneratorRequest =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsCodeGeneratorRequest}, {
+      &protobuf_google_2fprotobuf_2fdescriptor_2eproto::scc_info_FileDescriptorProto.base,
+      &protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_Version.base,}};
+
+static void InitDefaultsCodeGeneratorResponse_File() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::google::protobuf::compiler::_CodeGeneratorResponse_File_default_instance_;
+    new (ptr) ::google::protobuf::compiler::CodeGeneratorResponse_File();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::google::protobuf::compiler::CodeGeneratorResponse_File::InitAsDefaultInstance();
+}
+
+LIBPROTOC_EXPORT ::google::protobuf::internal::SCCInfo<0> scc_info_CodeGeneratorResponse_File =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsCodeGeneratorResponse_File}, {}};
+
+static void InitDefaultsCodeGeneratorResponse() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::google::protobuf::compiler::_CodeGeneratorResponse_default_instance_;
+    new (ptr) ::google::protobuf::compiler::CodeGeneratorResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::google::protobuf::compiler::CodeGeneratorResponse::InitAsDefaultInstance();
+}
+
+LIBPROTOC_EXPORT ::google::protobuf::internal::SCCInfo<1> scc_info_CodeGeneratorResponse =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsCodeGeneratorResponse}, {
+      &protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_CodeGeneratorResponse_File.base,}};
+
+void InitDefaults() {
+  ::google::protobuf::internal::InitSCC(&scc_info_Version.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_CodeGeneratorRequest.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_CodeGeneratorResponse_File.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_CodeGeneratorResponse.base);
+}
+
+::google::protobuf::Metadata file_level_metadata[4];
+
+const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::Version, _has_bits_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::Version, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::Version, major_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::Version, minor_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::Version, patch_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::Version, suffix_),
+  1,
+  2,
+  3,
+  0,
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _has_bits_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, file_to_generate_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, parameter_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, proto_file_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, compiler_version_),
+  ~0u,
+  0,
+  ~0u,
+  1,
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _has_bits_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, name_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, insertion_point_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, content_),
+  0,
+  1,
+  2,
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _has_bits_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, error_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, file_),
+  0,
+  ~0u,
+};
+static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  { 0, 9, sizeof(::google::protobuf::compiler::Version)},
+  { 13, 22, sizeof(::google::protobuf::compiler::CodeGeneratorRequest)},
+  { 26, 34, sizeof(::google::protobuf::compiler::CodeGeneratorResponse_File)},
+  { 37, 44, sizeof(::google::protobuf::compiler::CodeGeneratorResponse)},
+};
+
+static ::google::protobuf::Message const * const file_default_instances[] = {
+  reinterpret_cast<const ::google::protobuf::Message*>(&::google::protobuf::compiler::_Version_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::google::protobuf::compiler::_CodeGeneratorRequest_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::google::protobuf::compiler::_CodeGeneratorResponse_File_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::google::protobuf::compiler::_CodeGeneratorResponse_default_instance_),
+};
+
+void protobuf_AssignDescriptors() {
+  AddDescriptors();
+  AssignDescriptors(
+      "google/protobuf/compiler/plugin.proto", schemas, file_default_instances, TableStruct::offsets,
+      file_level_metadata, NULL, NULL);
+}
+
+void protobuf_AssignDescriptorsOnce() {
+  static ::google::protobuf::internal::once_flag once;
+  ::google::protobuf::internal::call_once(once, protobuf_AssignDescriptors);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD;
+void protobuf_RegisterTypes(const ::std::string&) {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 4);
+}
+
+void AddDescriptorsImpl() {
+  InitDefaults();
+  static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+      "\n%google/protobuf/compiler/plugin.proto\022"
+      "\030google.protobuf.compiler\032 google/protob"
+      "uf/descriptor.proto\"F\n\007Version\022\r\n\005major\030"
+      "\001 \001(\005\022\r\n\005minor\030\002 \001(\005\022\r\n\005patch\030\003 \001(\005\022\016\n\006s"
+      "uffix\030\004 \001(\t\"\272\001\n\024CodeGeneratorRequest\022\030\n\020"
+      "file_to_generate\030\001 \003(\t\022\021\n\tparameter\030\002 \001("
+      "\t\0228\n\nproto_file\030\017 \003(\0132$.google.protobuf."
+      "FileDescriptorProto\022;\n\020compiler_version\030"
+      "\003 \001(\0132!.google.protobuf.compiler.Version"
+      "\"\252\001\n\025CodeGeneratorResponse\022\r\n\005error\030\001 \001("
+      "\t\022B\n\004file\030\017 \003(\01324.google.protobuf.compil"
+      "er.CodeGeneratorResponse.File\032>\n\004File\022\014\n"
+      "\004name\030\001 \001(\t\022\027\n\017insertion_point\030\002 \001(\t\022\017\n\007"
+      "content\030\017 \001(\tBg\n\034com.google.protobuf.com"
+      "pilerB\014PluginProtosZ9github.com/golang/p"
+      "rotobuf/protoc-gen-go/plugin;plugin_go"
+  };
+  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+      descriptor, 638);
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+    "google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes);
+  ::protobuf_google_2fprotobuf_2fdescriptor_2eproto::AddDescriptors();
+}
+
+void AddDescriptors() {
+  static ::google::protobuf::internal::once_flag once;
+  ::google::protobuf::internal::call_once(once, AddDescriptorsImpl);
+}
+// Force AddDescriptors() to be called at dynamic initialization time.
+struct StaticDescriptorInitializer {
+  StaticDescriptorInitializer() {
+    AddDescriptors();
+  }
+} static_descriptor_initializer;
+}  // namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto
 namespace google {
 namespace protobuf {
 namespace compiler {
 
-namespace {
+// ===================================================================
 
-const ::google::protobuf::Descriptor* CodeGeneratorRequest_descriptor_ = NULL;
-const ::google::protobuf::internal::GeneratedMessageReflection*
-  CodeGeneratorRequest_reflection_ = NULL;
-const ::google::protobuf::Descriptor* CodeGeneratorResponse_descriptor_ = NULL;
-const ::google::protobuf::internal::GeneratedMessageReflection*
-  CodeGeneratorResponse_reflection_ = NULL;
-const ::google::protobuf::Descriptor* CodeGeneratorResponse_File_descriptor_ = NULL;
-const ::google::protobuf::internal::GeneratedMessageReflection*
-  CodeGeneratorResponse_File_reflection_ = NULL;
-
-}  // namespace
-
-
-void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-  protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
-  const ::google::protobuf::FileDescriptor* file =
-    ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
-      "google/protobuf/compiler/plugin.proto");
-  GOOGLE_CHECK(file != NULL);
-  CodeGeneratorRequest_descriptor_ = file->message_type(0);
-  static const int CodeGeneratorRequest_offsets_[3] = {
-    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, file_to_generate_),
-    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, parameter_),
-    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, proto_file_),
-  };
-  CodeGeneratorRequest_reflection_ =
-    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
-      CodeGeneratorRequest_descriptor_,
-      CodeGeneratorRequest::default_instance_,
-      CodeGeneratorRequest_offsets_,
-      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _has_bits_[0]),
-      -1,
-      -1,
-      sizeof(CodeGeneratorRequest),
-      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _internal_metadata_),
-      -1);
-  CodeGeneratorResponse_descriptor_ = file->message_type(1);
-  static const int CodeGeneratorResponse_offsets_[2] = {
-    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, error_),
-    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, file_),
-  };
-  CodeGeneratorResponse_reflection_ =
-    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
-      CodeGeneratorResponse_descriptor_,
-      CodeGeneratorResponse::default_instance_,
-      CodeGeneratorResponse_offsets_,
-      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _has_bits_[0]),
-      -1,
-      -1,
-      sizeof(CodeGeneratorResponse),
-      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _internal_metadata_),
-      -1);
-  CodeGeneratorResponse_File_descriptor_ = CodeGeneratorResponse_descriptor_->nested_type(0);
-  static const int CodeGeneratorResponse_File_offsets_[3] = {
-    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, name_),
-    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, insertion_point_),
-    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, content_),
-  };
-  CodeGeneratorResponse_File_reflection_ =
-    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
-      CodeGeneratorResponse_File_descriptor_,
-      CodeGeneratorResponse_File::default_instance_,
-      CodeGeneratorResponse_File_offsets_,
-      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _has_bits_[0]),
-      -1,
-      -1,
-      sizeof(CodeGeneratorResponse_File),
-      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _internal_metadata_),
-      -1);
+void Version::InitAsDefaultInstance() {
 }
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Version::kMajorFieldNumber;
+const int Version::kMinorFieldNumber;
+const int Version::kPatchFieldNumber;
+const int Version::kSuffixFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
 
-namespace {
-
-GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
-inline void protobuf_AssignDescriptorsOnce() {
-  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
-                 &protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
+Version::Version()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  ::google::protobuf::internal::InitSCC(
+      &protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_Version.base);
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.compiler.Version)
 }
-
-void protobuf_RegisterTypes(const ::std::string&) {
-  protobuf_AssignDescriptorsOnce();
-  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
-      CodeGeneratorRequest_descriptor_, &CodeGeneratorRequest::default_instance());
-  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
-      CodeGeneratorResponse_descriptor_, &CodeGeneratorResponse::default_instance());
-  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
-      CodeGeneratorResponse_File_descriptor_, &CodeGeneratorResponse_File::default_instance());
-}
-
-}  // namespace
-
-void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-  delete CodeGeneratorRequest::default_instance_;
-  delete CodeGeneratorRequest_reflection_;
-  delete CodeGeneratorResponse::default_instance_;
-  delete CodeGeneratorResponse_reflection_;
-  delete CodeGeneratorResponse_File::default_instance_;
-  delete CodeGeneratorResponse_File_reflection_;
-}
-
-void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-  static bool already_here = false;
-  if (already_here) return;
-  already_here = true;
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  ::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
-  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
-    "\n%google/protobuf/compiler/plugin.proto\022"
-    "\030google.protobuf.compiler\032 google/protob"
-    "uf/descriptor.proto\"}\n\024CodeGeneratorRequ"
-    "est\022\030\n\020file_to_generate\030\001 \003(\t\022\021\n\tparamet"
-    "er\030\002 \001(\t\0228\n\nproto_file\030\017 \003(\0132$.google.pr"
-    "otobuf.FileDescriptorProto\"\252\001\n\025CodeGener"
-    "atorResponse\022\r\n\005error\030\001 \001(\t\022B\n\004file\030\017 \003("
-    "\01324.google.protobuf.compiler.CodeGenerat"
-    "orResponse.File\032>\n\004File\022\014\n\004name\030\001 \001(\t\022\027\n"
-    "\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(\tB"
-    "7\n\034com.google.protobuf.compilerB\014PluginP"
-    "rotosZ\tplugin_go", 456);
-  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
-    "google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes);
-  CodeGeneratorRequest::default_instance_ = new CodeGeneratorRequest();
-  CodeGeneratorResponse::default_instance_ = new CodeGeneratorResponse();
-  CodeGeneratorResponse_File::default_instance_ = new CodeGeneratorResponse_File();
-  CodeGeneratorRequest::default_instance_->InitAsDefaultInstance();
-  CodeGeneratorResponse::default_instance_->InitAsDefaultInstance();
-  CodeGeneratorResponse_File::default_instance_->InitAsDefaultInstance();
-  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
-}
-
-// Force AddDescriptors() to be called at static initialization time.
-struct StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto {
-  StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-    protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+Version::Version(const Version& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(NULL),
+      _has_bits_(from._has_bits_) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  suffix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.has_suffix()) {
+    suffix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.suffix_);
   }
-} static_descriptor_initializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto_;
-
-namespace {
-
-static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
-static void MergeFromFail(int line) {
-  GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+  ::memcpy(&major_, &from.major_,
+    static_cast<size_t>(reinterpret_cast<char*>(&patch_) -
+    reinterpret_cast<char*>(&major_)) + sizeof(patch_));
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.Version)
 }
 
-}  // namespace
+void Version::SharedCtor() {
+  suffix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&major_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&patch_) -
+      reinterpret_cast<char*>(&major_)) + sizeof(patch_));
+}
+
+Version::~Version() {
+  // @@protoc_insertion_point(destructor:google.protobuf.compiler.Version)
+  SharedDtor();
+}
+
+void Version::SharedDtor() {
+  suffix_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void Version::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const ::google::protobuf::Descriptor* Version::descriptor() {
+  ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
+}
+
+const Version& Version::default_instance() {
+  ::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_Version.base);
+  return *internal_default_instance();
+}
+
+
+void Version::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.Version)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 0x00000001u) {
+    suffix_.ClearNonDefaultToEmptyNoArena();
+  }
+  if (cached_has_bits & 14u) {
+    ::memset(&major_, 0, static_cast<size_t>(
+        reinterpret_cast<char*>(&patch_) -
+        reinterpret_cast<char*>(&major_)) + sizeof(patch_));
+  }
+  _has_bits_.Clear();
+  _internal_metadata_.Clear();
+}
+
+bool Version::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.compiler.Version)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional int32 major = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
+          set_has_major();
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &major_)));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // optional int32 minor = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) {
+          set_has_minor();
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &minor_)));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // optional int32 patch = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(24u /* 24 & 0xFF */)) {
+          set_has_patch();
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &patch_)));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // optional string suffix = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_suffix()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->suffix().data(), static_cast<int>(this->suffix().length()),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.compiler.Version.suffix");
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.compiler.Version)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.Version)
+  return false;
+#undef DO_
+}
+
+void Version::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.Version)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  // optional int32 major = 1;
+  if (cached_has_bits & 0x00000002u) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->major(), output);
+  }
+
+  // optional int32 minor = 2;
+  if (cached_has_bits & 0x00000004u) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->minor(), output);
+  }
+
+  // optional int32 patch = 3;
+  if (cached_has_bits & 0x00000008u) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->patch(), output);
+  }
+
+  // optional string suffix = 4;
+  if (cached_has_bits & 0x00000001u) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->suffix().data(), static_cast<int>(this->suffix().length()),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.compiler.Version.suffix");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->suffix(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.Version)
+}
+
+::google::protobuf::uint8* Version::InternalSerializeWithCachedSizesToArray(
+    bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.Version)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  // optional int32 major = 1;
+  if (cached_has_bits & 0x00000002u) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->major(), target);
+  }
+
+  // optional int32 minor = 2;
+  if (cached_has_bits & 0x00000004u) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->minor(), target);
+  }
+
+  // optional int32 patch = 3;
+  if (cached_has_bits & 0x00000008u) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->patch(), target);
+  }
+
+  // optional string suffix = 4;
+  if (cached_has_bits & 0x00000001u) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->suffix().data(), static_cast<int>(this->suffix().length()),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.compiler.Version.suffix");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->suffix(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.Version)
+  return target;
+}
+
+size_t Version::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.Version)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  if (_has_bits_[0 / 32] & 15u) {
+    // optional string suffix = 4;
+    if (has_suffix()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->suffix());
+    }
+
+    // optional int32 major = 1;
+    if (has_major()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->major());
+    }
+
+    // optional int32 minor = 2;
+    if (has_minor()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->minor());
+    }
+
+    // optional int32 patch = 3;
+    if (has_patch()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->patch());
+    }
+
+  }
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void Version::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.Version)
+  GOOGLE_DCHECK_NE(&from, this);
+  const Version* source =
+      ::google::protobuf::internal::DynamicCastToGenerated<const Version>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.Version)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.Version)
+    MergeFrom(*source);
+  }
+}
+
+void Version::MergeFrom(const Version& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.Version)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = from._has_bits_[0];
+  if (cached_has_bits & 15u) {
+    if (cached_has_bits & 0x00000001u) {
+      set_has_suffix();
+      suffix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.suffix_);
+    }
+    if (cached_has_bits & 0x00000002u) {
+      major_ = from.major_;
+    }
+    if (cached_has_bits & 0x00000004u) {
+      minor_ = from.minor_;
+    }
+    if (cached_has_bits & 0x00000008u) {
+      patch_ = from.patch_;
+    }
+    _has_bits_[0] |= cached_has_bits;
+  }
+}
+
+void Version::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.Version)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Version::CopyFrom(const Version& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.Version)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Version::IsInitialized() const {
+  return true;
+}
+
+void Version::Swap(Version* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Version::InternalSwap(Version* other) {
+  using std::swap;
+  suffix_.Swap(&other->suffix_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(major_, other->major_);
+  swap(minor_, other->minor_);
+  swap(patch_, other->patch_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+}
+
+::google::protobuf::Metadata Version::GetMetadata() const {
+  protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages];
+}
 
 
 // ===================================================================
 
+void CodeGeneratorRequest::InitAsDefaultInstance() {
+  ::google::protobuf::compiler::_CodeGeneratorRequest_default_instance_._instance.get_mutable()->compiler_version_ = const_cast< ::google::protobuf::compiler::Version*>(
+      ::google::protobuf::compiler::Version::internal_default_instance());
+}
+void CodeGeneratorRequest::clear_proto_file() {
+  proto_file_.Clear();
+}
 #if !defined(_MSC_VER) || _MSC_VER >= 1900
 const int CodeGeneratorRequest::kFileToGenerateFieldNumber;
 const int CodeGeneratorRequest::kParameterFieldNumber;
 const int CodeGeneratorRequest::kProtoFileFieldNumber;
+const int CodeGeneratorRequest::kCompilerVersionFieldNumber;
 #endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
 
 CodeGeneratorRequest::CodeGeneratorRequest()
   : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  ::google::protobuf::internal::InitSCC(
+      &protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_CodeGeneratorRequest.base);
   SharedCtor();
   // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorRequest)
 }
-
-void CodeGeneratorRequest::InitAsDefaultInstance() {
-}
-
 CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from)
   : ::google::protobuf::Message(),
-    _internal_metadata_(NULL) {
-  SharedCtor();
-  MergeFrom(from);
+      _internal_metadata_(NULL),
+      _has_bits_(from._has_bits_),
+      file_to_generate_(from.file_to_generate_),
+      proto_file_(from.proto_file_) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  parameter_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.has_parameter()) {
+    parameter_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.parameter_);
+  }
+  if (from.has_compiler_version()) {
+    compiler_version_ = new ::google::protobuf::compiler::Version(*from.compiler_version_);
+  } else {
+    compiler_version_ = NULL;
+  }
   // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorRequest)
 }
 
 void CodeGeneratorRequest::SharedCtor() {
-  ::google::protobuf::internal::GetEmptyString();
-  _cached_size_ = 0;
   parameter_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  compiler_version_ = NULL;
 }
 
 CodeGeneratorRequest::~CodeGeneratorRequest() {
@@ -210,119 +672,119 @@
 
 void CodeGeneratorRequest::SharedDtor() {
   parameter_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  if (this != default_instance_) {
-  }
+  if (this != internal_default_instance()) delete compiler_version_;
 }
 
 void CodeGeneratorRequest::SetCachedSize(int size) const {
-  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
-  _cached_size_ = size;
-  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  _cached_size_.Set(size);
 }
 const ::google::protobuf::Descriptor* CodeGeneratorRequest::descriptor() {
-  protobuf_AssignDescriptorsOnce();
-  return CodeGeneratorRequest_descriptor_;
+  ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
 }
 
 const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() {
-  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
-  return *default_instance_;
+  ::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_CodeGeneratorRequest.base);
+  return *internal_default_instance();
 }
 
-CodeGeneratorRequest* CodeGeneratorRequest::default_instance_ = NULL;
-
-CodeGeneratorRequest* CodeGeneratorRequest::New(::google::protobuf::Arena* arena) const {
-  CodeGeneratorRequest* n = new CodeGeneratorRequest;
-  if (arena != NULL) {
-    arena->Own(n);
-  }
-  return n;
-}
 
 void CodeGeneratorRequest::Clear() {
-  if (has_parameter()) {
-    parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  }
+// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   file_to_generate_.Clear();
   proto_file_.Clear();
-  ::memset(_has_bits_, 0, sizeof(_has_bits_));
-  if (_internal_metadata_.have_unknown_fields()) {
-    mutable_unknown_fields()->Clear();
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 3u) {
+    if (cached_has_bits & 0x00000001u) {
+      parameter_.ClearNonDefaultToEmptyNoArena();
+    }
+    if (cached_has_bits & 0x00000002u) {
+      GOOGLE_DCHECK(compiler_version_ != NULL);
+      compiler_version_->Clear();
+    }
   }
+  _has_bits_.Clear();
+  _internal_metadata_.Clear();
 }
 
 bool CodeGeneratorRequest::MergePartialFromCodedStream(
     ::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
   ::google::protobuf::uint32 tag;
   // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorRequest)
   for (;;) {
-    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
     tag = p.first;
     if (!p.second) goto handle_unusual;
     switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // repeated string file_to_generate = 1;
       case 1: {
-        if (tag == 10) {
-         parse_file_to_generate:
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->add_file_to_generate()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
             this->file_to_generate(this->file_to_generate_size() - 1).data(),
-            this->file_to_generate(this->file_to_generate_size() - 1).length(),
+            static_cast<int>(this->file_to_generate(this->file_to_generate_size() - 1).length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
         } else {
           goto handle_unusual;
         }
-        if (input->ExpectTag(10)) goto parse_file_to_generate;
-        if (input->ExpectTag(18)) goto parse_parameter;
         break;
       }
 
       // optional string parameter = 2;
       case 2: {
-        if (tag == 18) {
-         parse_parameter:
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_parameter()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->parameter().data(), this->parameter().length(),
+            this->parameter().data(), static_cast<int>(this->parameter().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.compiler.CodeGeneratorRequest.parameter");
         } else {
           goto handle_unusual;
         }
-        if (input->ExpectTag(122)) goto parse_proto_file;
+        break;
+      }
+
+      // optional .google.protobuf.compiler.Version compiler_version = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_compiler_version()));
+        } else {
+          goto handle_unusual;
+        }
         break;
       }
 
       // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
       case 15: {
-        if (tag == 122) {
-         parse_proto_file:
-          DO_(input->IncrementRecursionDepth());
-         parse_loop_proto_file:
-          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(122u /* 122 & 0xFF */)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
                 input, add_proto_file()));
         } else {
           goto handle_unusual;
         }
-        if (input->ExpectTag(122)) goto parse_loop_proto_file;
-        input->UnsafeDecrementRecursionDepth();
-        if (input->ExpectAtEnd()) goto success;
         break;
       }
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -339,56 +801,74 @@
 void CodeGeneratorRequest::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
   // repeated string file_to_generate = 1;
-  for (int i = 0; i < this->file_to_generate_size(); i++) {
+  for (int i = 0, n = this->file_to_generate_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->file_to_generate(i).data(), this->file_to_generate(i).length(),
+      this->file_to_generate(i).data(), static_cast<int>(this->file_to_generate(i).length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
     ::google::protobuf::internal::WireFormatLite::WriteString(
       1, this->file_to_generate(i), output);
   }
 
+  cached_has_bits = _has_bits_[0];
   // optional string parameter = 2;
-  if (has_parameter()) {
+  if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->parameter().data(), this->parameter().length(),
+      this->parameter().data(), static_cast<int>(this->parameter().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorRequest.parameter");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
       2, this->parameter(), output);
   }
 
-  // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
-  for (unsigned int i = 0, n = this->proto_file_size(); i < n; i++) {
+  // optional .google.protobuf.compiler.Version compiler_version = 3;
+  if (cached_has_bits & 0x00000002u) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      15, this->proto_file(i), output);
+      3, this->_internal_compiler_version(), output);
+  }
+
+  // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->proto_file_size()); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      15,
+      this->proto_file(static_cast<int>(i)),
+      output);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorRequest)
 }
 
-::google::protobuf::uint8* CodeGeneratorRequest::SerializeWithCachedSizesToArray(
-    ::google::protobuf::uint8* target) const {
+::google::protobuf::uint8* CodeGeneratorRequest::InternalSerializeWithCachedSizesToArray(
+    bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
   // repeated string file_to_generate = 1;
-  for (int i = 0; i < this->file_to_generate_size(); i++) {
+  for (int i = 0, n = this->file_to_generate_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->file_to_generate(i).data(), this->file_to_generate(i).length(),
+      this->file_to_generate(i).data(), static_cast<int>(this->file_to_generate(i).length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
     target = ::google::protobuf::internal::WireFormatLite::
       WriteStringToArray(1, this->file_to_generate(i), target);
   }
 
+  cached_has_bits = _has_bits_[0];
   // optional string parameter = 2;
-  if (has_parameter()) {
+  if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->parameter().data(), this->parameter().length(),
+      this->parameter().data(), static_cast<int>(this->parameter().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorRequest.parameter");
     target =
@@ -396,98 +876,129 @@
         2, this->parameter(), target);
   }
 
-  // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
-  for (unsigned int i = 0, n = this->proto_file_size(); i < n; i++) {
+  // optional .google.protobuf.compiler.Version compiler_version = 3;
+  if (cached_has_bits & 0x00000002u) {
     target = ::google::protobuf::internal::WireFormatLite::
-      WriteMessageNoVirtualToArray(
-        15, this->proto_file(i), target);
+      InternalWriteMessageToArray(
+        3, this->_internal_compiler_version(), deterministic, target);
+  }
+
+  // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->proto_file_size()); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        15, this->proto_file(static_cast<int>(i)), deterministic, target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorRequest)
   return target;
 }
 
-int CodeGeneratorRequest::ByteSize() const {
-  int total_size = 0;
+size_t CodeGeneratorRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorRequest)
+  size_t total_size = 0;
 
-  // optional string parameter = 2;
-  if (has_parameter()) {
-    total_size += 1 +
-      ::google::protobuf::internal::WireFormatLite::StringSize(
-        this->parameter());
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
   }
-
   // repeated string file_to_generate = 1;
-  total_size += 1 * this->file_to_generate_size();
-  for (int i = 0; i < this->file_to_generate_size(); i++) {
+  total_size += 1 *
+      ::google::protobuf::internal::FromIntSize(this->file_to_generate_size());
+  for (int i = 0, n = this->file_to_generate_size(); i < n; i++) {
     total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
       this->file_to_generate(i));
   }
 
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
-  total_size += 1 * this->proto_file_size();
-  for (int i = 0; i < this->proto_file_size(); i++) {
-    total_size +=
-      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-        this->proto_file(i));
+  {
+    unsigned int count = static_cast<unsigned int>(this->proto_file_size());
+    total_size += 1UL * count;
+    for (unsigned int i = 0; i < count; i++) {
+      total_size +=
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          this->proto_file(static_cast<int>(i)));
+    }
   }
 
-  if (_internal_metadata_.have_unknown_fields()) {
-    total_size +=
-      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+  if (_has_bits_[0 / 32] & 3u) {
+    // optional string parameter = 2;
+    if (has_parameter()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->parameter());
+    }
+
+    // optional .google.protobuf.compiler.Version compiler_version = 3;
+    if (has_compiler_version()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          *compiler_version_);
+    }
+
   }
-  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
-  _cached_size_ = total_size;
-  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
   return total_size;
 }
 
 void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) {
-  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
-  const CodeGeneratorRequest* source = 
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const CodeGeneratorRequest* source =
       ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorRequest>(
           &from);
   if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorRequest)
     ::google::protobuf::internal::ReflectionOps::Merge(from, this);
   } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorRequest)
     MergeFrom(*source);
   }
 }
 
 void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
-  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
   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_parameter()) {
+  cached_has_bits = from._has_bits_[0];
+  if (cached_has_bits & 3u) {
+    if (cached_has_bits & 0x00000001u) {
       set_has_parameter();
       parameter_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.parameter_);
     }
-  }
-  if (from._internal_metadata_.have_unknown_fields()) {
-    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+    if (cached_has_bits & 0x00000002u) {
+      mutable_compiler_version()->::google::protobuf::compiler::Version::MergeFrom(from.compiler_version());
+    }
   }
 }
 
 void CodeGeneratorRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.CodeGeneratorRequest)
   if (&from == this) return;
   Clear();
   MergeFrom(from);
 }
 
 void CodeGeneratorRequest::CopyFrom(const CodeGeneratorRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.CodeGeneratorRequest)
   if (&from == this) return;
   Clear();
   MergeFrom(from);
 }
 
 bool CodeGeneratorRequest::IsInitialized() const {
-
   if (!::google::protobuf::internal::AllAreInitialized(this->proto_file())) return false;
   return true;
 }
@@ -497,166 +1008,26 @@
   InternalSwap(other);
 }
 void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) {
-  file_to_generate_.UnsafeArenaSwap(&other->file_to_generate_);
-  parameter_.Swap(&other->parameter_);
-  proto_file_.UnsafeArenaSwap(&other->proto_file_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  using std::swap;
+  file_to_generate_.InternalSwap(CastToBase(&other->file_to_generate_));
+  CastToBase(&proto_file_)->InternalSwap(CastToBase(&other->proto_file_));
+  parameter_.Swap(&other->parameter_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(compiler_version_, other->compiler_version_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata CodeGeneratorRequest::GetMetadata() const {
-  protobuf_AssignDescriptorsOnce();
-  ::google::protobuf::Metadata metadata;
-  metadata.descriptor = CodeGeneratorRequest_descriptor_;
-  metadata.reflection = CodeGeneratorRequest_reflection_;
-  return metadata;
+  protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages];
 }
 
-#if PROTOBUF_INLINE_NOT_IN_HEADERS
-// CodeGeneratorRequest
-
-// repeated string file_to_generate = 1;
-int CodeGeneratorRequest::file_to_generate_size() const {
-  return file_to_generate_.size();
-}
-void CodeGeneratorRequest::clear_file_to_generate() {
-  file_to_generate_.Clear();
-}
- const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
-  return file_to_generate_.Get(index);
-}
- ::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) {
-  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
-  return file_to_generate_.Mutable(index);
-}
- void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) {
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
-  file_to_generate_.Mutable(index)->assign(value);
-}
- void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) {
-  file_to_generate_.Mutable(index)->assign(value);
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
-}
- void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) {
-  file_to_generate_.Mutable(index)->assign(
-    reinterpret_cast<const char*>(value), size);
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
-}
- ::std::string* CodeGeneratorRequest::add_file_to_generate() {
-  return file_to_generate_.Add();
-}
- void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) {
-  file_to_generate_.Add()->assign(value);
-  // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
-}
- void CodeGeneratorRequest::add_file_to_generate(const char* value) {
-  file_to_generate_.Add()->assign(value);
-  // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
-}
- void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) {
-  file_to_generate_.Add()->assign(reinterpret_cast<const char*>(value), size);
-  // @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
-}
- const ::google::protobuf::RepeatedPtrField< ::std::string>&
-CodeGeneratorRequest::file_to_generate() const {
-  // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
-  return file_to_generate_;
-}
- ::google::protobuf::RepeatedPtrField< ::std::string>*
-CodeGeneratorRequest::mutable_file_to_generate() {
-  // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
-  return &file_to_generate_;
-}
-
-// optional string parameter = 2;
-bool CodeGeneratorRequest::has_parameter() const {
-  return (_has_bits_[0] & 0x00000002u) != 0;
-}
-void CodeGeneratorRequest::set_has_parameter() {
-  _has_bits_[0] |= 0x00000002u;
-}
-void CodeGeneratorRequest::clear_has_parameter() {
-  _has_bits_[0] &= ~0x00000002u;
-}
-void CodeGeneratorRequest::clear_parameter() {
-  parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  clear_has_parameter();
-}
- const ::std::string& CodeGeneratorRequest::parameter() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-  return parameter_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
- void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
-  set_has_parameter();
-  parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-}
- void CodeGeneratorRequest::set_parameter(const char* value) {
-  set_has_parameter();
-  parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-}
- void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
-  set_has_parameter();
-  parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      ::std::string(reinterpret_cast<const char*>(value), size));
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-}
- ::std::string* CodeGeneratorRequest::mutable_parameter() {
-  set_has_parameter();
-  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-  return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
- ::std::string* CodeGeneratorRequest::release_parameter() {
-  clear_has_parameter();
-  return parameter_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
- void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
-  if (parameter != NULL) {
-    set_has_parameter();
-  } else {
-    clear_has_parameter();
-  }
-  parameter_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parameter);
-  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-}
-
-// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
-int CodeGeneratorRequest::proto_file_size() const {
-  return proto_file_.size();
-}
-void CodeGeneratorRequest::clear_proto_file() {
-  proto_file_.Clear();
-}
-const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
-  return proto_file_.Get(index);
-}
-::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) {
-  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
-  return proto_file_.Mutable(index);
-}
-::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
-  // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
-  return proto_file_.Add();
-}
-::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
-CodeGeneratorRequest::mutable_proto_file() {
-  // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
-  return &proto_file_;
-}
-const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
-CodeGeneratorRequest::proto_file() const {
-  // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
-  return proto_file_;
-}
-
-#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
 
+void CodeGeneratorResponse_File::InitAsDefaultInstance() {
+}
 #if !defined(_MSC_VER) || _MSC_VER >= 1900
 const int CodeGeneratorResponse_File::kNameFieldNumber;
 const int CodeGeneratorResponse_File::kInsertionPointFieldNumber;
@@ -665,28 +1036,35 @@
 
 CodeGeneratorResponse_File::CodeGeneratorResponse_File()
   : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  ::google::protobuf::internal::InitSCC(
+      &protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_CodeGeneratorResponse_File.base);
   SharedCtor();
   // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
 }
-
-void CodeGeneratorResponse_File::InitAsDefaultInstance() {
-}
-
 CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from)
   : ::google::protobuf::Message(),
-    _internal_metadata_(NULL) {
-  SharedCtor();
-  MergeFrom(from);
+      _internal_metadata_(NULL),
+      _has_bits_(from._has_bits_) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.has_name()) {
+    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+  }
+  insertion_point_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.has_insertion_point()) {
+    insertion_point_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.insertion_point_);
+  }
+  content_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.has_content()) {
+    content_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.content_);
+  }
   // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
 }
 
 void CodeGeneratorResponse_File::SharedCtor() {
-  ::google::protobuf::internal::GetEmptyString();
-  _cached_size_ = 0;
   name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   insertion_point_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   content_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
 CodeGeneratorResponse_File::~CodeGeneratorResponse_File() {
@@ -698,122 +1076,109 @@
   name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   insertion_point_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   content_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  if (this != default_instance_) {
-  }
 }
 
 void CodeGeneratorResponse_File::SetCachedSize(int size) const {
-  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
-  _cached_size_ = size;
-  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  _cached_size_.Set(size);
 }
 const ::google::protobuf::Descriptor* CodeGeneratorResponse_File::descriptor() {
-  protobuf_AssignDescriptorsOnce();
-  return CodeGeneratorResponse_File_descriptor_;
+  ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
 }
 
 const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance() {
-  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
-  return *default_instance_;
+  ::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_CodeGeneratorResponse_File.base);
+  return *internal_default_instance();
 }
 
-CodeGeneratorResponse_File* CodeGeneratorResponse_File::default_instance_ = NULL;
-
-CodeGeneratorResponse_File* CodeGeneratorResponse_File::New(::google::protobuf::Arena* arena) const {
-  CodeGeneratorResponse_File* n = new CodeGeneratorResponse_File;
-  if (arena != NULL) {
-    arena->Own(n);
-  }
-  return n;
-}
 
 void CodeGeneratorResponse_File::Clear() {
-  if (_has_bits_[0 / 32] & 7u) {
-    if (has_name()) {
-      name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 7u) {
+    if (cached_has_bits & 0x00000001u) {
+      name_.ClearNonDefaultToEmptyNoArena();
     }
-    if (has_insertion_point()) {
-      insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    if (cached_has_bits & 0x00000002u) {
+      insertion_point_.ClearNonDefaultToEmptyNoArena();
     }
-    if (has_content()) {
-      content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    if (cached_has_bits & 0x00000004u) {
+      content_.ClearNonDefaultToEmptyNoArena();
     }
   }
-  ::memset(_has_bits_, 0, sizeof(_has_bits_));
-  if (_internal_metadata_.have_unknown_fields()) {
-    mutable_unknown_fields()->Clear();
-  }
+  _has_bits_.Clear();
+  _internal_metadata_.Clear();
 }
 
 bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
     ::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
   ::google::protobuf::uint32 tag;
   // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse.File)
   for (;;) {
-    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
     tag = p.first;
     if (!p.second) goto handle_unusual;
     switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // optional string name = 1;
       case 1: {
-        if (tag == 10) {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->name().data(), this->name().length(),
+            this->name().data(), static_cast<int>(this->name().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.compiler.CodeGeneratorResponse.File.name");
         } else {
           goto handle_unusual;
         }
-        if (input->ExpectTag(18)) goto parse_insertion_point;
         break;
       }
 
       // optional string insertion_point = 2;
       case 2: {
-        if (tag == 18) {
-         parse_insertion_point:
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_insertion_point()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->insertion_point().data(), this->insertion_point().length(),
+            this->insertion_point().data(), static_cast<int>(this->insertion_point().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
         } else {
           goto handle_unusual;
         }
-        if (input->ExpectTag(122)) goto parse_content;
         break;
       }
 
       // optional string content = 15;
       case 15: {
-        if (tag == 122) {
-         parse_content:
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(122u /* 122 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_content()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->content().data(), this->content().length(),
+            this->content().data(), static_cast<int>(this->content().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.compiler.CodeGeneratorResponse.File.content");
         } else {
           goto handle_unusual;
         }
-        if (input->ExpectAtEnd()) goto success;
         break;
       }
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -830,10 +1195,14 @@
 void CodeGeneratorResponse_File::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
   // optional string name = 1;
-  if (has_name()) {
+  if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorResponse.File.name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -841,9 +1210,9 @@
   }
 
   // optional string insertion_point = 2;
-  if (has_insertion_point()) {
+  if (cached_has_bits & 0x00000002u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->insertion_point().data(), this->insertion_point().length(),
+      this->insertion_point().data(), static_cast<int>(this->insertion_point().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -851,9 +1220,9 @@
   }
 
   // optional string content = 15;
-  if (has_content()) {
+  if (cached_has_bits & 0x00000004u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->content().data(), this->content().length(),
+      this->content().data(), static_cast<int>(this->content().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorResponse.File.content");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -862,18 +1231,23 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorResponse.File)
 }
 
-::google::protobuf::uint8* CodeGeneratorResponse_File::SerializeWithCachedSizesToArray(
-    ::google::protobuf::uint8* target) const {
+::google::protobuf::uint8* CodeGeneratorResponse_File::InternalSerializeWithCachedSizesToArray(
+    bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
   // optional string name = 1;
-  if (has_name()) {
+  if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorResponse.File.name");
     target =
@@ -882,9 +1256,9 @@
   }
 
   // optional string insertion_point = 2;
-  if (has_insertion_point()) {
+  if (cached_has_bits & 0x00000002u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->insertion_point().data(), this->insertion_point().length(),
+      this->insertion_point().data(), static_cast<int>(this->insertion_point().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
     target =
@@ -893,9 +1267,9 @@
   }
 
   // optional string content = 15;
-  if (has_content()) {
+  if (cached_has_bits & 0x00000004u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->content().data(), this->content().length(),
+      this->content().data(), static_cast<int>(this->content().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorResponse.File.content");
     target =
@@ -905,15 +1279,21 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse.File)
   return target;
 }
 
-int CodeGeneratorResponse_File::ByteSize() const {
-  int total_size = 0;
+size_t CodeGeneratorResponse_File::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+  size_t total_size = 0;
 
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
   if (_has_bits_[0 / 32] & 7u) {
     // optional string name = 1;
     if (has_name()) {
@@ -937,64 +1317,65 @@
     }
 
   }
-  if (_internal_metadata_.have_unknown_fields()) {
-    total_size +=
-      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
-  }
-  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
-  _cached_size_ = total_size;
-  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
   return total_size;
 }
 
 void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& from) {
-  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
-  const CodeGeneratorResponse_File* source = 
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+  GOOGLE_DCHECK_NE(&from, this);
+  const CodeGeneratorResponse_File* source =
       ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse_File>(
           &from);
   if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorResponse.File)
     ::google::protobuf::internal::ReflectionOps::Merge(from, this);
   } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorResponse.File)
     MergeFrom(*source);
   }
 }
 
 void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) {
-  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
-  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from.has_name()) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = from._has_bits_[0];
+  if (cached_has_bits & 7u) {
+    if (cached_has_bits & 0x00000001u) {
       set_has_name();
       name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
     }
-    if (from.has_insertion_point()) {
+    if (cached_has_bits & 0x00000002u) {
       set_has_insertion_point();
       insertion_point_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.insertion_point_);
     }
-    if (from.has_content()) {
+    if (cached_has_bits & 0x00000004u) {
       set_has_content();
       content_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.content_);
     }
   }
-  if (from._internal_metadata_.have_unknown_fields()) {
-    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
-  }
 }
 
 void CodeGeneratorResponse_File::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
   if (&from == this) return;
   Clear();
   MergeFrom(from);
 }
 
 void CodeGeneratorResponse_File::CopyFrom(const CodeGeneratorResponse_File& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
   if (&from == this) return;
   Clear();
   MergeFrom(from);
 }
 
 bool CodeGeneratorResponse_File::IsInitialized() const {
-
   return true;
 }
 
@@ -1003,25 +1384,27 @@
   InternalSwap(other);
 }
 void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other) {
-  name_.Swap(&other->name_);
-  insertion_point_.Swap(&other->insertion_point_);
-  content_.Swap(&other->content_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  using std::swap;
+  name_.Swap(&other->name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  insertion_point_.Swap(&other->insertion_point_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  content_.Swap(&other->content_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata CodeGeneratorResponse_File::GetMetadata() const {
-  protobuf_AssignDescriptorsOnce();
-  ::google::protobuf::Metadata metadata;
-  metadata.descriptor = CodeGeneratorResponse_File_descriptor_;
-  metadata.reflection = CodeGeneratorResponse_File_reflection_;
-  return metadata;
+  protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages];
 }
 
 
-// -------------------------------------------------------------------
+// ===================================================================
 
+void CodeGeneratorResponse::InitAsDefaultInstance() {
+}
 #if !defined(_MSC_VER) || _MSC_VER >= 1900
 const int CodeGeneratorResponse::kErrorFieldNumber;
 const int CodeGeneratorResponse::kFileFieldNumber;
@@ -1029,26 +1412,26 @@
 
 CodeGeneratorResponse::CodeGeneratorResponse()
   : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  ::google::protobuf::internal::InitSCC(
+      &protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_CodeGeneratorResponse.base);
   SharedCtor();
   // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse)
 }
-
-void CodeGeneratorResponse::InitAsDefaultInstance() {
-}
-
 CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from)
   : ::google::protobuf::Message(),
-    _internal_metadata_(NULL) {
-  SharedCtor();
-  MergeFrom(from);
+      _internal_metadata_(NULL),
+      _has_bits_(from._has_bits_),
+      file_(from.file_) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  error_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.has_error()) {
+    error_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.error_);
+  }
   // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse)
 }
 
 void CodeGeneratorResponse::SharedCtor() {
-  ::google::protobuf::internal::GetEmptyString();
-  _cached_size_ = 0;
   error_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
 CodeGeneratorResponse::~CodeGeneratorResponse() {
@@ -1058,98 +1441,82 @@
 
 void CodeGeneratorResponse::SharedDtor() {
   error_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  if (this != default_instance_) {
-  }
 }
 
 void CodeGeneratorResponse::SetCachedSize(int size) const {
-  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
-  _cached_size_ = size;
-  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  _cached_size_.Set(size);
 }
 const ::google::protobuf::Descriptor* CodeGeneratorResponse::descriptor() {
-  protobuf_AssignDescriptorsOnce();
-  return CodeGeneratorResponse_descriptor_;
+  ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
 }
 
 const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() {
-  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
-  return *default_instance_;
+  ::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_CodeGeneratorResponse.base);
+  return *internal_default_instance();
 }
 
-CodeGeneratorResponse* CodeGeneratorResponse::default_instance_ = NULL;
-
-CodeGeneratorResponse* CodeGeneratorResponse::New(::google::protobuf::Arena* arena) const {
-  CodeGeneratorResponse* n = new CodeGeneratorResponse;
-  if (arena != NULL) {
-    arena->Own(n);
-  }
-  return n;
-}
 
 void CodeGeneratorResponse::Clear() {
-  if (has_error()) {
-    error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  }
+// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   file_.Clear();
-  ::memset(_has_bits_, 0, sizeof(_has_bits_));
-  if (_internal_metadata_.have_unknown_fields()) {
-    mutable_unknown_fields()->Clear();
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 0x00000001u) {
+    error_.ClearNonDefaultToEmptyNoArena();
   }
+  _has_bits_.Clear();
+  _internal_metadata_.Clear();
 }
 
 bool CodeGeneratorResponse::MergePartialFromCodedStream(
     ::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
   ::google::protobuf::uint32 tag;
   // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse)
   for (;;) {
-    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
     tag = p.first;
     if (!p.second) goto handle_unusual;
     switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
       // optional string error = 1;
       case 1: {
-        if (tag == 10) {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_error()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->error().data(), this->error().length(),
+            this->error().data(), static_cast<int>(this->error().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.compiler.CodeGeneratorResponse.error");
         } else {
           goto handle_unusual;
         }
-        if (input->ExpectTag(122)) goto parse_file;
         break;
       }
 
       // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
       case 15: {
-        if (tag == 122) {
-         parse_file:
-          DO_(input->IncrementRecursionDepth());
-         parse_loop_file:
-          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(122u /* 122 & 0xFF */)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
                 input, add_file()));
         } else {
           goto handle_unusual;
         }
-        if (input->ExpectTag(122)) goto parse_loop_file;
-        input->UnsafeDecrementRecursionDepth();
-        if (input->ExpectAtEnd()) goto success;
         break;
       }
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -1166,10 +1533,14 @@
 void CodeGeneratorResponse::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
   // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
   // optional string error = 1;
-  if (has_error()) {
+  if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->error().data(), this->error().length(),
+      this->error().data(), static_cast<int>(this->error().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorResponse.error");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -1177,25 +1548,33 @@
   }
 
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
-  for (unsigned int i = 0, n = this->file_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->file_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      15, this->file(i), output);
+      15,
+      this->file(static_cast<int>(i)),
+      output);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorResponse)
 }
 
-::google::protobuf::uint8* CodeGeneratorResponse::SerializeWithCachedSizesToArray(
-    ::google::protobuf::uint8* target) const {
+::google::protobuf::uint8* CodeGeneratorResponse::InternalSerializeWithCachedSizesToArray(
+    bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
   // optional string error = 1;
-  if (has_error()) {
+  if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->error().data(), this->error().length(),
+      this->error().data(), static_cast<int>(this->error().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorResponse.error");
     target =
@@ -1204,22 +1583,40 @@
   }
 
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
-  for (unsigned int i = 0, n = this->file_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->file_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
-      WriteMessageNoVirtualToArray(
-        15, this->file(i), target);
+      InternalWriteMessageToArray(
+        15, this->file(static_cast<int>(i)), deterministic, target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse)
   return target;
 }
 
-int CodeGeneratorResponse::ByteSize() const {
-  int total_size = 0;
+size_t CodeGeneratorResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+  {
+    unsigned int count = static_cast<unsigned int>(this->file_size());
+    total_size += 1UL * count;
+    for (unsigned int i = 0; i < count; i++) {
+      total_size +=
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          this->file(static_cast<int>(i)));
+    }
+  }
 
   // optional string error = 1;
   if (has_error()) {
@@ -1228,65 +1625,55 @@
         this->error());
   }
 
-  // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
-  total_size += 1 * this->file_size();
-  for (int i = 0; i < this->file_size(); i++) {
-    total_size +=
-      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-        this->file(i));
-  }
-
-  if (_internal_metadata_.have_unknown_fields()) {
-    total_size +=
-      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
-  }
-  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
-  _cached_size_ = total_size;
-  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
   return total_size;
 }
 
 void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) {
-  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
-  const CodeGeneratorResponse* source = 
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const CodeGeneratorResponse* source =
       ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse>(
           &from);
   if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorResponse)
     ::google::protobuf::internal::ReflectionOps::Merge(from, this);
   } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorResponse)
     MergeFrom(*source);
   }
 }
 
 void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
-  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
   file_.MergeFrom(from.file_);
-  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    if (from.has_error()) {
-      set_has_error();
-      error_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.error_);
-    }
-  }
-  if (from._internal_metadata_.have_unknown_fields()) {
-    mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+  if (from.has_error()) {
+    set_has_error();
+    error_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.error_);
   }
 }
 
 void CodeGeneratorResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse)
   if (&from == this) return;
   Clear();
   MergeFrom(from);
 }
 
 void CodeGeneratorResponse::CopyFrom(const CodeGeneratorResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse)
   if (&from == this) return;
   Clear();
   MergeFrom(from);
 }
 
 bool CodeGeneratorResponse::IsInitialized() const {
-
   return true;
 }
 
@@ -1295,276 +1682,39 @@
   InternalSwap(other);
 }
 void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
-  error_.Swap(&other->error_);
-  file_.UnsafeArenaSwap(&other->file_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  using std::swap;
+  CastToBase(&file_)->InternalSwap(CastToBase(&other->file_));
+  error_.Swap(&other->error_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata CodeGeneratorResponse::GetMetadata() const {
-  protobuf_AssignDescriptorsOnce();
-  ::google::protobuf::Metadata metadata;
-  metadata.descriptor = CodeGeneratorResponse_descriptor_;
-  metadata.reflection = CodeGeneratorResponse_reflection_;
-  return metadata;
+  protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages];
 }
 
-#if PROTOBUF_INLINE_NOT_IN_HEADERS
-// CodeGeneratorResponse_File
-
-// optional string name = 1;
-bool CodeGeneratorResponse_File::has_name() const {
-  return (_has_bits_[0] & 0x00000001u) != 0;
-}
-void CodeGeneratorResponse_File::set_has_name() {
-  _has_bits_[0] |= 0x00000001u;
-}
-void CodeGeneratorResponse_File::clear_has_name() {
-  _has_bits_[0] &= ~0x00000001u;
-}
-void CodeGeneratorResponse_File::clear_name() {
-  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  clear_has_name();
-}
- const ::std::string& CodeGeneratorResponse_File::name() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
- void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
-  set_has_name();
-  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-}
- void CodeGeneratorResponse_File::set_name(const char* value) {
-  set_has_name();
-  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-}
- void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
-  set_has_name();
-  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      ::std::string(reinterpret_cast<const char*>(value), size));
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-}
- ::std::string* CodeGeneratorResponse_File::mutable_name() {
-  set_has_name();
-  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
- ::std::string* CodeGeneratorResponse_File::release_name() {
-  clear_has_name();
-  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
- void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
-  if (name != NULL) {
-    set_has_name();
-  } else {
-    clear_has_name();
-  }
-  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
-  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-}
-
-// optional string insertion_point = 2;
-bool CodeGeneratorResponse_File::has_insertion_point() const {
-  return (_has_bits_[0] & 0x00000002u) != 0;
-}
-void CodeGeneratorResponse_File::set_has_insertion_point() {
-  _has_bits_[0] |= 0x00000002u;
-}
-void CodeGeneratorResponse_File::clear_has_insertion_point() {
-  _has_bits_[0] &= ~0x00000002u;
-}
-void CodeGeneratorResponse_File::clear_insertion_point() {
-  insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  clear_has_insertion_point();
-}
- const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-  return insertion_point_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
- void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
-  set_has_insertion_point();
-  insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-}
- void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
-  set_has_insertion_point();
-  insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-}
- void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
-  set_has_insertion_point();
-  insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      ::std::string(reinterpret_cast<const char*>(value), size));
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-}
- ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
-  set_has_insertion_point();
-  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-  return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
- ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
-  clear_has_insertion_point();
-  return insertion_point_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
- void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
-  if (insertion_point != NULL) {
-    set_has_insertion_point();
-  } else {
-    clear_has_insertion_point();
-  }
-  insertion_point_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), insertion_point);
-  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-}
-
-// optional string content = 15;
-bool CodeGeneratorResponse_File::has_content() const {
-  return (_has_bits_[0] & 0x00000004u) != 0;
-}
-void CodeGeneratorResponse_File::set_has_content() {
-  _has_bits_[0] |= 0x00000004u;
-}
-void CodeGeneratorResponse_File::clear_has_content() {
-  _has_bits_[0] &= ~0x00000004u;
-}
-void CodeGeneratorResponse_File::clear_content() {
-  content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  clear_has_content();
-}
- const ::std::string& CodeGeneratorResponse_File::content() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-  return content_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
- void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
-  set_has_content();
-  content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-}
- void CodeGeneratorResponse_File::set_content(const char* value) {
-  set_has_content();
-  content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-}
- void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
-  set_has_content();
-  content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      ::std::string(reinterpret_cast<const char*>(value), size));
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-}
- ::std::string* CodeGeneratorResponse_File::mutable_content() {
-  set_has_content();
-  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-  return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
- ::std::string* CodeGeneratorResponse_File::release_content() {
-  clear_has_content();
-  return content_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
- void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
-  if (content != NULL) {
-    set_has_content();
-  } else {
-    clear_has_content();
-  }
-  content_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), content);
-  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-}
-
-// -------------------------------------------------------------------
-
-// CodeGeneratorResponse
-
-// optional string error = 1;
-bool CodeGeneratorResponse::has_error() const {
-  return (_has_bits_[0] & 0x00000001u) != 0;
-}
-void CodeGeneratorResponse::set_has_error() {
-  _has_bits_[0] |= 0x00000001u;
-}
-void CodeGeneratorResponse::clear_has_error() {
-  _has_bits_[0] &= ~0x00000001u;
-}
-void CodeGeneratorResponse::clear_error() {
-  error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  clear_has_error();
-}
- const ::std::string& CodeGeneratorResponse::error() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error)
-  return error_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
- void CodeGeneratorResponse::set_error(const ::std::string& value) {
-  set_has_error();
-  error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error)
-}
- void CodeGeneratorResponse::set_error(const char* value) {
-  set_has_error();
-  error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error)
-}
- void CodeGeneratorResponse::set_error(const char* value, size_t size) {
-  set_has_error();
-  error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      ::std::string(reinterpret_cast<const char*>(value), size));
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error)
-}
- ::std::string* CodeGeneratorResponse::mutable_error() {
-  set_has_error();
-  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error)
-  return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
- ::std::string* CodeGeneratorResponse::release_error() {
-  clear_has_error();
-  return error_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
- void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
-  if (error != NULL) {
-    set_has_error();
-  } else {
-    clear_has_error();
-  }
-  error_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error);
-  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
-}
-
-// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
-int CodeGeneratorResponse::file_size() const {
-  return file_.size();
-}
-void CodeGeneratorResponse::clear_file() {
-  file_.Clear();
-}
-const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file)
-  return file_.Get(index);
-}
-::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) {
-  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file)
-  return file_.Mutable(index);
-}
-::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
-  // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file)
-  return file_.Add();
-}
-::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
-CodeGeneratorResponse::mutable_file() {
-  // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file)
-  return &file_;
-}
-const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
-CodeGeneratorResponse::file() const {
-  // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file)
-  return file_;
-}
-
-#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // @@protoc_insertion_point(namespace_scope)
-
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
+namespace google {
+namespace protobuf {
+template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::compiler::Version* Arena::CreateMaybeMessage< ::google::protobuf::compiler::Version >(Arena* arena) {
+  return Arena::CreateInternal< ::google::protobuf::compiler::Version >(arena);
+}
+template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::compiler::CodeGeneratorRequest* Arena::CreateMaybeMessage< ::google::protobuf::compiler::CodeGeneratorRequest >(Arena* arena) {
+  return Arena::CreateInternal< ::google::protobuf::compiler::CodeGeneratorRequest >(arena);
+}
+template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::compiler::CodeGeneratorResponse_File* Arena::CreateMaybeMessage< ::google::protobuf::compiler::CodeGeneratorResponse_File >(Arena* arena) {
+  return Arena::CreateInternal< ::google::protobuf::compiler::CodeGeneratorResponse_File >(arena);
+}
+template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::compiler::CodeGeneratorResponse* Arena::CreateMaybeMessage< ::google::protobuf::compiler::CodeGeneratorResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::google::protobuf::compiler::CodeGeneratorResponse >(arena);
+}
+}  // namespace protobuf
+}  // namespace google
 
 // @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index 0a03e97..78d3bba 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -1,51 +1,242 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/compiler/plugin.proto
 
-#ifndef PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
-#define PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
+#ifndef PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto
+#define PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto
 
 #include <string>
 
 #include <google/protobuf/stubs/common.h>
 
-#if GOOGLE_PROTOBUF_VERSION < 3000000
+#if GOOGLE_PROTOBUF_VERSION < 3006001
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please update
 #error your headers.
 #endif
-#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#if 3006001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please
 #error regenerate this file with a newer version of protoc.
 #endif
 
+#include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/arena.h>
 #include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/inlined_string_field.h>
 #include <google/protobuf/metadata.h>
 #include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>
-#include <google/protobuf/extension_set.h>
+#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
+#include <google/protobuf/extension_set.h>  // IWYU pragma: export
 #include <google/protobuf/unknown_field_set.h>
 #include <google/protobuf/descriptor.pb.h>
 // @@protoc_insertion_point(includes)
+#define PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto LIBPROTOC_EXPORT
+#ifdef major
+#undef major
+#endif
+#ifdef minor
+#undef minor
+#endif
 
+namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto {
+// Internal implementation detail -- do not use these members.
+struct LIBPROTOC_EXPORT TableStruct {
+  static const ::google::protobuf::internal::ParseTableField entries[];
+  static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
+  static const ::google::protobuf::internal::ParseTable schema[4];
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
+  static const ::google::protobuf::uint32 offsets[];
+};
+void LIBPROTOC_EXPORT AddDescriptors();
+}  // namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto
+namespace google {
+namespace protobuf {
+namespace compiler {
+class CodeGeneratorRequest;
+class CodeGeneratorRequestDefaultTypeInternal;
+LIBPROTOC_EXPORT extern CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_;
+class CodeGeneratorResponse;
+class CodeGeneratorResponseDefaultTypeInternal;
+LIBPROTOC_EXPORT extern CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_;
+class CodeGeneratorResponse_File;
+class CodeGeneratorResponse_FileDefaultTypeInternal;
+LIBPROTOC_EXPORT extern CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_;
+class Version;
+class VersionDefaultTypeInternal;
+LIBPROTOC_EXPORT extern VersionDefaultTypeInternal _Version_default_instance_;
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+namespace google {
+namespace protobuf {
+template<> LIBPROTOC_EXPORT ::google::protobuf::compiler::CodeGeneratorRequest* Arena::CreateMaybeMessage<::google::protobuf::compiler::CodeGeneratorRequest>(Arena*);
+template<> LIBPROTOC_EXPORT ::google::protobuf::compiler::CodeGeneratorResponse* Arena::CreateMaybeMessage<::google::protobuf::compiler::CodeGeneratorResponse>(Arena*);
+template<> LIBPROTOC_EXPORT ::google::protobuf::compiler::CodeGeneratorResponse_File* Arena::CreateMaybeMessage<::google::protobuf::compiler::CodeGeneratorResponse_File>(Arena*);
+template<> LIBPROTOC_EXPORT ::google::protobuf::compiler::Version* Arena::CreateMaybeMessage<::google::protobuf::compiler::Version>(Arena*);
+}  // namespace protobuf
+}  // namespace google
 namespace google {
 namespace protobuf {
 namespace compiler {
 
-// Internal implementation detail -- do not call these.
-void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
-void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
-void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
-
-class CodeGeneratorRequest;
-class CodeGeneratorResponse;
-class CodeGeneratorResponse_File;
-
 // ===================================================================
 
-class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message {
+class LIBPROTOC_EXPORT Version : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.Version) */ {
+ public:
+  Version();
+  virtual ~Version();
+
+  Version(const Version& from);
+
+  inline Version& operator=(const Version& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  Version(Version&& from) noexcept
+    : Version() {
+    *this = ::std::move(from);
+  }
+
+  inline Version& operator=(Version&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Version& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const Version* internal_default_instance() {
+    return reinterpret_cast<const Version*>(
+               &_Version_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    0;
+
+  void Swap(Version* other);
+  friend void swap(Version& a, Version& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Version* New() const final {
+    return CreateMaybeMessage<Version>(NULL);
+  }
+
+  Version* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<Version>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const Version& from);
+  void MergeFrom(const Version& from);
+  void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      bool deterministic, ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(Version* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return NULL;
+  }
+  inline void* MaybeArenaPtr() const {
+    return NULL;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional string suffix = 4;
+  bool has_suffix() const;
+  void clear_suffix();
+  static const int kSuffixFieldNumber = 4;
+  const ::std::string& suffix() const;
+  void set_suffix(const ::std::string& value);
+  #if LANG_CXX11
+  void set_suffix(::std::string&& value);
+  #endif
+  void set_suffix(const char* value);
+  void set_suffix(const char* value, size_t size);
+  ::std::string* mutable_suffix();
+  ::std::string* release_suffix();
+  void set_allocated_suffix(::std::string* suffix);
+
+  // optional int32 major = 1;
+  bool has_major() const;
+  void clear_major();
+  static const int kMajorFieldNumber = 1;
+  ::google::protobuf::int32 major() const;
+  void set_major(::google::protobuf::int32 value);
+
+  // optional int32 minor = 2;
+  bool has_minor() const;
+  void clear_minor();
+  static const int kMinorFieldNumber = 2;
+  ::google::protobuf::int32 minor() const;
+  void set_minor(::google::protobuf::int32 value);
+
+  // optional int32 patch = 3;
+  bool has_patch() const;
+  void clear_patch();
+  static const int kPatchFieldNumber = 3;
+  ::google::protobuf::int32 patch() const;
+  void set_patch(::google::protobuf::int32 value);
+
+  // @@protoc_insertion_point(class_scope:google.protobuf.compiler.Version)
+ private:
+  void set_has_major();
+  void clear_has_major();
+  void set_has_minor();
+  void clear_has_minor();
+  void set_has_patch();
+  void clear_has_patch();
+  void set_has_suffix();
+  void clear_has_suffix();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::HasBits<1> _has_bits_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  ::google::protobuf::internal::ArenaStringPtr suffix_;
+  ::google::protobuf::int32 major_;
+  ::google::protobuf::int32 minor_;
+  ::google::protobuf::int32 patch_;
+  friend struct ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorRequest) */ {
  public:
   CodeGeneratorRequest();
   virtual ~CodeGeneratorRequest();
@@ -56,11 +247,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  CodeGeneratorRequest(CodeGeneratorRequest&& from) noexcept
+    : CodeGeneratorRequest() {
+    *this = ::std::move(from);
+  }
 
+  inline CodeGeneratorRequest& operator=(CodeGeneratorRequest&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -68,42 +272,59 @@
   static const ::google::protobuf::Descriptor* descriptor();
   static const CodeGeneratorRequest& default_instance();
 
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const CodeGeneratorRequest* internal_default_instance() {
+    return reinterpret_cast<const CodeGeneratorRequest*>(
+               &_CodeGeneratorRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    1;
+
   void Swap(CodeGeneratorRequest* other);
+  friend void swap(CodeGeneratorRequest& a, CodeGeneratorRequest& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
-  inline CodeGeneratorRequest* New() const { return New(NULL); }
+  inline CodeGeneratorRequest* New() const final {
+    return CreateMaybeMessage<CodeGeneratorRequest>(NULL);
+  }
 
-  CodeGeneratorRequest* New(::google::protobuf::Arena* arena) const;
-  void CopyFrom(const ::google::protobuf::Message& from);
-  void MergeFrom(const ::google::protobuf::Message& from);
+  CodeGeneratorRequest* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<CodeGeneratorRequest>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
   void CopyFrom(const CodeGeneratorRequest& from);
   void MergeFrom(const CodeGeneratorRequest& from);
-  void Clear();
-  bool IsInitialized() const;
+  void Clear() final;
+  bool IsInitialized() const final;
 
-  int ByteSize() const;
+  size_t ByteSizeLong() const final;
   bool MergePartialFromCodedStream(
-      ::google::protobuf::io::CodedInputStream* input);
+      ::google::protobuf::io::CodedInputStream* input) final;
   void SerializeWithCachedSizes(
-      ::google::protobuf::io::CodedOutputStream* output) const;
-  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
-  int GetCachedSize() const { return _cached_size_; }
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      bool deterministic, ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
   private:
   void SharedCtor();
   void SharedDtor();
-  void SetCachedSize(int size) const;
+  void SetCachedSize(int size) const final;
   void InternalSwap(CodeGeneratorRequest* other);
   private:
   inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
-    return _internal_metadata_.arena();
+    return NULL;
   }
   inline void* MaybeArenaPtr() const {
-    return _internal_metadata_.raw_arena_ptr();
+    return NULL;
   }
   public:
 
-  ::google::protobuf::Metadata GetMetadata() const;
+  ::google::protobuf::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -116,60 +337,79 @@
   const ::std::string& file_to_generate(int index) const;
   ::std::string* mutable_file_to_generate(int index);
   void set_file_to_generate(int index, const ::std::string& value);
+  #if LANG_CXX11
+  void set_file_to_generate(int index, ::std::string&& value);
+  #endif
   void set_file_to_generate(int index, const char* value);
   void set_file_to_generate(int index, const char* value, size_t size);
   ::std::string* add_file_to_generate();
   void add_file_to_generate(const ::std::string& value);
+  #if LANG_CXX11
+  void add_file_to_generate(::std::string&& value);
+  #endif
   void add_file_to_generate(const char* value);
   void add_file_to_generate(const char* value, size_t size);
   const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const;
   ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate();
 
+  // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+  int proto_file_size() const;
+  void clear_proto_file();
+  static const int kProtoFileFieldNumber = 15;
+  ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index);
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+      mutable_proto_file();
+  const ::google::protobuf::FileDescriptorProto& proto_file(int index) const;
+  ::google::protobuf::FileDescriptorProto* add_proto_file();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+      proto_file() const;
+
   // optional string parameter = 2;
   bool has_parameter() const;
   void clear_parameter();
   static const int kParameterFieldNumber = 2;
   const ::std::string& parameter() const;
   void set_parameter(const ::std::string& value);
+  #if LANG_CXX11
+  void set_parameter(::std::string&& value);
+  #endif
   void set_parameter(const char* value);
   void set_parameter(const char* value, size_t size);
   ::std::string* mutable_parameter();
   ::std::string* release_parameter();
   void set_allocated_parameter(::std::string* parameter);
 
-  // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
-  int proto_file_size() const;
-  void clear_proto_file();
-  static const int kProtoFileFieldNumber = 15;
-  const ::google::protobuf::FileDescriptorProto& proto_file(int index) const;
-  ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index);
-  ::google::protobuf::FileDescriptorProto* add_proto_file();
-  ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
-      mutable_proto_file();
-  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
-      proto_file() const;
+  // optional .google.protobuf.compiler.Version compiler_version = 3;
+  bool has_compiler_version() const;
+  void clear_compiler_version();
+  static const int kCompilerVersionFieldNumber = 3;
+  private:
+  const ::google::protobuf::compiler::Version& _internal_compiler_version() const;
+  public:
+  const ::google::protobuf::compiler::Version& compiler_version() const;
+  ::google::protobuf::compiler::Version* release_compiler_version();
+  ::google::protobuf::compiler::Version* mutable_compiler_version();
+  void set_allocated_compiler_version(::google::protobuf::compiler::Version* compiler_version);
 
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
  private:
-  inline void set_has_parameter();
-  inline void clear_has_parameter();
+  void set_has_parameter();
+  void clear_has_parameter();
+  void set_has_compiler_version();
+  void clear_has_compiler_version();
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  ::google::protobuf::uint32 _has_bits_[1];
-  mutable int _cached_size_;
+  ::google::protobuf::internal::HasBits<1> _has_bits_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
   ::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_;
-  ::google::protobuf::internal::ArenaStringPtr parameter_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_;
-  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();
-
-  void InitAsDefaultInstance();
-  static CodeGeneratorRequest* default_instance_;
+  ::google::protobuf::internal::ArenaStringPtr parameter_;
+  ::google::protobuf::compiler::Version* compiler_version_;
+  friend struct ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct;
 };
 // -------------------------------------------------------------------
 
-class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::Message {
+class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse.File) */ {
  public:
   CodeGeneratorResponse_File();
   virtual ~CodeGeneratorResponse_File();
@@ -180,11 +420,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  CodeGeneratorResponse_File(CodeGeneratorResponse_File&& from) noexcept
+    : CodeGeneratorResponse_File() {
+    *this = ::std::move(from);
+  }
 
+  inline CodeGeneratorResponse_File& operator=(CodeGeneratorResponse_File&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -192,42 +445,59 @@
   static const ::google::protobuf::Descriptor* descriptor();
   static const CodeGeneratorResponse_File& default_instance();
 
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const CodeGeneratorResponse_File* internal_default_instance() {
+    return reinterpret_cast<const CodeGeneratorResponse_File*>(
+               &_CodeGeneratorResponse_File_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    2;
+
   void Swap(CodeGeneratorResponse_File* other);
+  friend void swap(CodeGeneratorResponse_File& a, CodeGeneratorResponse_File& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
-  inline CodeGeneratorResponse_File* New() const { return New(NULL); }
+  inline CodeGeneratorResponse_File* New() const final {
+    return CreateMaybeMessage<CodeGeneratorResponse_File>(NULL);
+  }
 
-  CodeGeneratorResponse_File* New(::google::protobuf::Arena* arena) const;
-  void CopyFrom(const ::google::protobuf::Message& from);
-  void MergeFrom(const ::google::protobuf::Message& from);
+  CodeGeneratorResponse_File* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<CodeGeneratorResponse_File>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
   void CopyFrom(const CodeGeneratorResponse_File& from);
   void MergeFrom(const CodeGeneratorResponse_File& from);
-  void Clear();
-  bool IsInitialized() const;
+  void Clear() final;
+  bool IsInitialized() const final;
 
-  int ByteSize() const;
+  size_t ByteSizeLong() const final;
   bool MergePartialFromCodedStream(
-      ::google::protobuf::io::CodedInputStream* input);
+      ::google::protobuf::io::CodedInputStream* input) final;
   void SerializeWithCachedSizes(
-      ::google::protobuf::io::CodedOutputStream* output) const;
-  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
-  int GetCachedSize() const { return _cached_size_; }
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      bool deterministic, ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
   private:
   void SharedCtor();
   void SharedDtor();
-  void SetCachedSize(int size) const;
+  void SetCachedSize(int size) const final;
   void InternalSwap(CodeGeneratorResponse_File* other);
   private:
   inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
-    return _internal_metadata_.arena();
+    return NULL;
   }
   inline void* MaybeArenaPtr() const {
-    return _internal_metadata_.raw_arena_ptr();
+    return NULL;
   }
   public:
 
-  ::google::protobuf::Metadata GetMetadata() const;
+  ::google::protobuf::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -239,6 +509,9 @@
   static const int kNameFieldNumber = 1;
   const ::std::string& name() const;
   void set_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_name(::std::string&& value);
+  #endif
   void set_name(const char* value);
   void set_name(const char* value, size_t size);
   ::std::string* mutable_name();
@@ -251,6 +524,9 @@
   static const int kInsertionPointFieldNumber = 2;
   const ::std::string& insertion_point() const;
   void set_insertion_point(const ::std::string& value);
+  #if LANG_CXX11
+  void set_insertion_point(::std::string&& value);
+  #endif
   void set_insertion_point(const char* value);
   void set_insertion_point(const char* value, size_t size);
   ::std::string* mutable_insertion_point();
@@ -263,6 +539,9 @@
   static const int kContentFieldNumber = 15;
   const ::std::string& content() const;
   void set_content(const ::std::string& value);
+  #if LANG_CXX11
+  void set_content(::std::string&& value);
+  #endif
   void set_content(const char* value);
   void set_content(const char* value, size_t size);
   ::std::string* mutable_content();
@@ -271,29 +550,24 @@
 
   // @@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();
+  void set_has_name();
+  void clear_has_name();
+  void set_has_insertion_point();
+  void clear_has_insertion_point();
+  void set_has_content();
+  void clear_has_content();
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  ::google::protobuf::uint32 _has_bits_[1];
-  mutable int _cached_size_;
+  ::google::protobuf::internal::HasBits<1> _has_bits_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
   ::google::protobuf::internal::ArenaStringPtr name_;
   ::google::protobuf::internal::ArenaStringPtr insertion_point_;
   ::google::protobuf::internal::ArenaStringPtr content_;
-  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();
-
-  void InitAsDefaultInstance();
-  static CodeGeneratorResponse_File* default_instance_;
+  friend struct ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct;
 };
 // -------------------------------------------------------------------
 
-class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Message {
+class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse) */ {
  public:
   CodeGeneratorResponse();
   virtual ~CodeGeneratorResponse();
@@ -304,11 +578,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  CodeGeneratorResponse(CodeGeneratorResponse&& from) noexcept
+    : CodeGeneratorResponse() {
+    *this = ::std::move(from);
+  }
 
+  inline CodeGeneratorResponse& operator=(CodeGeneratorResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -316,42 +603,59 @@
   static const ::google::protobuf::Descriptor* descriptor();
   static const CodeGeneratorResponse& default_instance();
 
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const CodeGeneratorResponse* internal_default_instance() {
+    return reinterpret_cast<const CodeGeneratorResponse*>(
+               &_CodeGeneratorResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    3;
+
   void Swap(CodeGeneratorResponse* other);
+  friend void swap(CodeGeneratorResponse& a, CodeGeneratorResponse& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
-  inline CodeGeneratorResponse* New() const { return New(NULL); }
+  inline CodeGeneratorResponse* New() const final {
+    return CreateMaybeMessage<CodeGeneratorResponse>(NULL);
+  }
 
-  CodeGeneratorResponse* New(::google::protobuf::Arena* arena) const;
-  void CopyFrom(const ::google::protobuf::Message& from);
-  void MergeFrom(const ::google::protobuf::Message& from);
+  CodeGeneratorResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<CodeGeneratorResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
   void CopyFrom(const CodeGeneratorResponse& from);
   void MergeFrom(const CodeGeneratorResponse& from);
-  void Clear();
-  bool IsInitialized() const;
+  void Clear() final;
+  bool IsInitialized() const final;
 
-  int ByteSize() const;
+  size_t ByteSizeLong() const final;
   bool MergePartialFromCodedStream(
-      ::google::protobuf::io::CodedInputStream* input);
+      ::google::protobuf::io::CodedInputStream* input) final;
   void SerializeWithCachedSizes(
-      ::google::protobuf::io::CodedOutputStream* output) const;
-  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
-  int GetCachedSize() const { return _cached_size_; }
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      bool deterministic, ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
   private:
   void SharedCtor();
   void SharedDtor();
-  void SetCachedSize(int size) const;
+  void SetCachedSize(int size) const final;
   void InternalSwap(CodeGeneratorResponse* other);
   private:
   inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
-    return _internal_metadata_.arena();
+    return NULL;
   }
   inline void* MaybeArenaPtr() const {
-    return _internal_metadata_.raw_arena_ptr();
+    return NULL;
   }
   public:
 
-  ::google::protobuf::Metadata GetMetadata() const;
+  ::google::protobuf::Metadata GetMetadata() const final;
 
   // nested types ----------------------------------------------------
 
@@ -359,53 +663,196 @@
 
   // accessors -------------------------------------------------------
 
+  // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+  int file_size() const;
+  void clear_file();
+  static const int kFileFieldNumber = 15;
+  ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index);
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
+      mutable_file();
+  const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const;
+  ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+      file() const;
+
   // optional string error = 1;
   bool has_error() const;
   void clear_error();
   static const int kErrorFieldNumber = 1;
   const ::std::string& error() const;
   void set_error(const ::std::string& value);
+  #if LANG_CXX11
+  void set_error(::std::string&& value);
+  #endif
   void set_error(const char* value);
   void set_error(const char* value, size_t size);
   ::std::string* mutable_error();
   ::std::string* release_error();
   void set_allocated_error(::std::string* error);
 
-  // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
-  int file_size() const;
-  void clear_file();
-  static const int kFileFieldNumber = 15;
-  const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const;
-  ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index);
-  ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file();
-  ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
-      mutable_file();
-  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
-      file() const;
-
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
  private:
-  inline void set_has_error();
-  inline void clear_has_error();
+  void set_has_error();
+  void clear_has_error();
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  ::google::protobuf::uint32 _has_bits_[1];
-  mutable int _cached_size_;
-  ::google::protobuf::internal::ArenaStringPtr error_;
+  ::google::protobuf::internal::HasBits<1> _has_bits_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_;
-  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();
-
-  void InitAsDefaultInstance();
-  static CodeGeneratorResponse* default_instance_;
+  ::google::protobuf::internal::ArenaStringPtr error_;
+  friend struct ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct;
 };
 // ===================================================================
 
 
 // ===================================================================
 
-#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
+// Version
+
+// optional int32 major = 1;
+inline bool Version::has_major() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void Version::set_has_major() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void Version::clear_has_major() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void Version::clear_major() {
+  major_ = 0;
+  clear_has_major();
+}
+inline ::google::protobuf::int32 Version::major() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.major)
+  return major_;
+}
+inline void Version::set_major(::google::protobuf::int32 value) {
+  set_has_major();
+  major_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.major)
+}
+
+// optional int32 minor = 2;
+inline bool Version::has_minor() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void Version::set_has_minor() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void Version::clear_has_minor() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void Version::clear_minor() {
+  minor_ = 0;
+  clear_has_minor();
+}
+inline ::google::protobuf::int32 Version::minor() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.minor)
+  return minor_;
+}
+inline void Version::set_minor(::google::protobuf::int32 value) {
+  set_has_minor();
+  minor_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.minor)
+}
+
+// optional int32 patch = 3;
+inline bool Version::has_patch() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void Version::set_has_patch() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void Version::clear_has_patch() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline void Version::clear_patch() {
+  patch_ = 0;
+  clear_has_patch();
+}
+inline ::google::protobuf::int32 Version::patch() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.patch)
+  return patch_;
+}
+inline void Version::set_patch(::google::protobuf::int32 value) {
+  set_has_patch();
+  patch_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.patch)
+}
+
+// optional string suffix = 4;
+inline bool Version::has_suffix() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void Version::set_has_suffix() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void Version::clear_has_suffix() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void Version::clear_suffix() {
+  suffix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_suffix();
+}
+inline const ::std::string& Version::suffix() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.suffix)
+  return suffix_.GetNoArena();
+}
+inline void Version::set_suffix(const ::std::string& value) {
+  set_has_suffix();
+  suffix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.suffix)
+}
+#if LANG_CXX11
+inline void Version::set_suffix(::std::string&& value) {
+  set_has_suffix();
+  suffix_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.Version.suffix)
+}
+#endif
+inline void Version::set_suffix(const char* value) {
+  GOOGLE_DCHECK(value != NULL);
+  set_has_suffix();
+  suffix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.Version.suffix)
+}
+inline void Version::set_suffix(const char* value, size_t size) {
+  set_has_suffix();
+  suffix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.Version.suffix)
+}
+inline ::std::string* Version::mutable_suffix() {
+  set_has_suffix();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.Version.suffix)
+  return suffix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Version::release_suffix() {
+  // @@protoc_insertion_point(field_release:google.protobuf.compiler.Version.suffix)
+  if (!has_suffix()) {
+    return NULL;
+  }
+  clear_has_suffix();
+  return suffix_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Version::set_allocated_suffix(::std::string* suffix) {
+  if (suffix != NULL) {
+    set_has_suffix();
+  } else {
+    clear_has_suffix();
+  }
+  suffix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), suffix);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.Version.suffix)
+}
+
+// -------------------------------------------------------------------
+
 // CodeGeneratorRequest
 
 // repeated string file_to_generate = 1;
@@ -427,7 +874,14 @@
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
   file_to_generate_.Mutable(index)->assign(value);
 }
+#if LANG_CXX11
+inline void CodeGeneratorRequest::set_file_to_generate(int index, ::std::string&& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+  file_to_generate_.Mutable(index)->assign(std::move(value));
+}
+#endif
 inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) {
+  GOOGLE_DCHECK(value != NULL);
   file_to_generate_.Mutable(index)->assign(value);
   // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
 }
@@ -437,13 +891,21 @@
   // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
 }
 inline ::std::string* CodeGeneratorRequest::add_file_to_generate() {
+  // @@protoc_insertion_point(field_add_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
   return file_to_generate_.Add();
 }
 inline void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) {
   file_to_generate_.Add()->assign(value);
   // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
 }
+#if LANG_CXX11
+inline void CodeGeneratorRequest::add_file_to_generate(::std::string&& value) {
+  file_to_generate_.Add(std::move(value));
+  // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+#endif
 inline void CodeGeneratorRequest::add_file_to_generate(const char* value) {
+  GOOGLE_DCHECK(value != NULL);
   file_to_generate_.Add()->assign(value);
   // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
 }
@@ -464,13 +926,13 @@
 
 // optional string parameter = 2;
 inline bool CodeGeneratorRequest::has_parameter() const {
-  return (_has_bits_[0] & 0x00000002u) != 0;
+  return (_has_bits_[0] & 0x00000001u) != 0;
 }
 inline void CodeGeneratorRequest::set_has_parameter() {
-  _has_bits_[0] |= 0x00000002u;
+  _has_bits_[0] |= 0x00000001u;
 }
 inline void CodeGeneratorRequest::clear_has_parameter() {
-  _has_bits_[0] &= ~0x00000002u;
+  _has_bits_[0] &= ~0x00000001u;
 }
 inline void CodeGeneratorRequest::clear_parameter() {
   parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
@@ -478,14 +940,23 @@
 }
 inline const ::std::string& CodeGeneratorRequest::parameter() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-  return parameter_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  return parameter_.GetNoArena();
 }
 inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
   set_has_parameter();
   parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter)
 }
+#if LANG_CXX11
+inline void CodeGeneratorRequest::set_parameter(::std::string&& value) {
+  set_has_parameter();
+  parameter_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+#endif
 inline void CodeGeneratorRequest::set_parameter(const char* value) {
+  GOOGLE_DCHECK(value != NULL);
   set_has_parameter();
   parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
   // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter)
@@ -502,8 +973,12 @@
   return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 inline ::std::string* CodeGeneratorRequest::release_parameter() {
+  // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+  if (!has_parameter()) {
+    return NULL;
+  }
   clear_has_parameter();
-  return parameter_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  return parameter_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
   if (parameter != NULL) {
@@ -519,32 +994,87 @@
 inline int CodeGeneratorRequest::proto_file_size() const {
   return proto_file_.size();
 }
-inline void CodeGeneratorRequest::clear_proto_file() {
-  proto_file_.Clear();
-}
-inline const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
-  return proto_file_.Get(index);
-}
 inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) {
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
   return proto_file_.Mutable(index);
 }
-inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
-  // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
-  return proto_file_.Add();
-}
 inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
 CodeGeneratorRequest::mutable_proto_file() {
   // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
   return &proto_file_;
 }
+inline const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+  return proto_file_.Get(index);
+}
+inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
+  // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+  return proto_file_.Add();
+}
 inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
 CodeGeneratorRequest::proto_file() const {
   // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
   return proto_file_;
 }
 
+// optional .google.protobuf.compiler.Version compiler_version = 3;
+inline bool CodeGeneratorRequest::has_compiler_version() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void CodeGeneratorRequest::set_has_compiler_version() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void CodeGeneratorRequest::clear_has_compiler_version() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void CodeGeneratorRequest::clear_compiler_version() {
+  if (compiler_version_ != NULL) compiler_version_->Clear();
+  clear_has_compiler_version();
+}
+inline const ::google::protobuf::compiler::Version& CodeGeneratorRequest::_internal_compiler_version() const {
+  return *compiler_version_;
+}
+inline const ::google::protobuf::compiler::Version& CodeGeneratorRequest::compiler_version() const {
+  const ::google::protobuf::compiler::Version* p = compiler_version_;
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::compiler::Version*>(
+      &::google::protobuf::compiler::_Version_default_instance_);
+}
+inline ::google::protobuf::compiler::Version* CodeGeneratorRequest::release_compiler_version() {
+  // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
+  clear_has_compiler_version();
+  ::google::protobuf::compiler::Version* temp = compiler_version_;
+  compiler_version_ = NULL;
+  return temp;
+}
+inline ::google::protobuf::compiler::Version* CodeGeneratorRequest::mutable_compiler_version() {
+  set_has_compiler_version();
+  if (compiler_version_ == NULL) {
+    auto* p = CreateMaybeMessage<::google::protobuf::compiler::Version>(GetArenaNoVirtual());
+    compiler_version_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
+  return compiler_version_;
+}
+inline void CodeGeneratorRequest::set_allocated_compiler_version(::google::protobuf::compiler::Version* compiler_version) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == NULL) {
+    delete compiler_version_;
+  }
+  if (compiler_version) {
+    ::google::protobuf::Arena* submessage_arena = NULL;
+    if (message_arena != submessage_arena) {
+      compiler_version = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, compiler_version, submessage_arena);
+    }
+    set_has_compiler_version();
+  } else {
+    clear_has_compiler_version();
+  }
+  compiler_version_ = compiler_version;
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
+}
+
 // -------------------------------------------------------------------
 
 // CodeGeneratorResponse_File
@@ -565,14 +1095,23 @@
 }
 inline const ::std::string& CodeGeneratorResponse_File::name() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  return name_.GetNoArena();
 }
 inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
   set_has_name();
   name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name)
 }
+#if LANG_CXX11
+inline void CodeGeneratorResponse_File::set_name(::std::string&& value) {
+  set_has_name();
+  name_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+#endif
 inline void CodeGeneratorResponse_File::set_name(const char* value) {
+  GOOGLE_DCHECK(value != NULL);
   set_has_name();
   name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
   // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name)
@@ -589,8 +1128,12 @@
   return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 inline ::std::string* CodeGeneratorResponse_File::release_name() {
+  // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+  if (!has_name()) {
+    return NULL;
+  }
   clear_has_name();
-  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  return name_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
   if (name != NULL) {
@@ -618,14 +1161,23 @@
 }
 inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-  return insertion_point_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  return insertion_point_.GetNoArena();
 }
 inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
   set_has_insertion_point();
   insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
 }
+#if LANG_CXX11
+inline void CodeGeneratorResponse_File::set_insertion_point(::std::string&& value) {
+  set_has_insertion_point();
+  insertion_point_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+#endif
 inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
+  GOOGLE_DCHECK(value != NULL);
   set_has_insertion_point();
   insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
   // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
@@ -642,8 +1194,12 @@
   return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
+  // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+  if (!has_insertion_point()) {
+    return NULL;
+  }
   clear_has_insertion_point();
-  return insertion_point_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  return insertion_point_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
   if (insertion_point != NULL) {
@@ -671,14 +1227,23 @@
 }
 inline const ::std::string& CodeGeneratorResponse_File::content() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-  return content_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  return content_.GetNoArena();
 }
 inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
   set_has_content();
   content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content)
 }
+#if LANG_CXX11
+inline void CodeGeneratorResponse_File::set_content(::std::string&& value) {
+  set_has_content();
+  content_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+#endif
 inline void CodeGeneratorResponse_File::set_content(const char* value) {
+  GOOGLE_DCHECK(value != NULL);
   set_has_content();
   content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
   // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content)
@@ -695,8 +1260,12 @@
   return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 inline ::std::string* CodeGeneratorResponse_File::release_content() {
+  // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+  if (!has_content()) {
+    return NULL;
+  }
   clear_has_content();
-  return content_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  return content_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
   if (content != NULL) {
@@ -728,14 +1297,23 @@
 }
 inline const ::std::string& CodeGeneratorResponse::error() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error)
-  return error_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  return error_.GetNoArena();
 }
 inline void CodeGeneratorResponse::set_error(const ::std::string& value) {
   set_has_error();
   error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error)
 }
+#if LANG_CXX11
+inline void CodeGeneratorResponse::set_error(::std::string&& value) {
+  set_has_error();
+  error_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+#endif
 inline void CodeGeneratorResponse::set_error(const char* value) {
+  GOOGLE_DCHECK(value != NULL);
   set_has_error();
   error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
   // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error)
@@ -752,8 +1330,12 @@
   return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 inline ::std::string* CodeGeneratorResponse::release_error() {
+  // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.error)
+  if (!has_error()) {
+    return NULL;
+  }
   clear_has_error();
-  return error_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  return error_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
   if (error != NULL) {
@@ -772,30 +1354,34 @@
 inline void CodeGeneratorResponse::clear_file() {
   file_.Clear();
 }
-inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file)
-  return file_.Get(index);
-}
 inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) {
   // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file)
   return file_.Mutable(index);
 }
-inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
-  // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file)
-  return file_.Add();
-}
 inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
 CodeGeneratorResponse::mutable_file() {
   // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file)
   return &file_;
 }
+inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file)
+  return file_.Get(index);
+}
+inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
+  // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file)
+  return file_.Add();
+}
 inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
 CodeGeneratorResponse::file() const {
   // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file)
   return file_;
 }
 
-#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
+// -------------------------------------------------------------------
+
 // -------------------------------------------------------------------
 
 // -------------------------------------------------------------------
@@ -809,4 +1395,4 @@
 
 // @@protoc_insertion_point(global_scope)
 
-#endif  // PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
+#endif  // PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto
diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto
index acaee1f..5b55745 100644
--- a/src/google/protobuf/compiler/plugin.proto
+++ b/src/google/protobuf/compiler/plugin.proto
@@ -49,10 +49,20 @@
 option java_package = "com.google.protobuf.compiler";
 option java_outer_classname = "PluginProtos";
 
-option go_package = "plugin_go";
+option go_package = "github.com/golang/protobuf/protoc-gen-go/plugin;plugin_go";
 
 import "google/protobuf/descriptor.proto";
 
+// The version number of protocol compiler.
+message Version {
+  optional int32 major = 1;
+  optional int32 minor = 2;
+  optional int32 patch = 3;
+  // A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should
+  // be empty for mainline stable releases.
+  optional string suffix = 4;
+}
+
 // An encoded CodeGeneratorRequest is written to the plugin's stdin.
 message CodeGeneratorRequest {
   // The .proto files that were explicitly listed on the command-line.  The
@@ -74,7 +84,14 @@
   // the entire set into memory at once.  However, as of this writing, this
   // is not similarly optimized on protoc's end -- it will store all fields in
   // memory at once before sending them to the plugin.
+  //
+  // Type names of fields and extensions in the FileDescriptorProto are always
+  // fully qualified.
   repeated FileDescriptorProto proto_file = 15;
+
+  // The version number of protocol compiler.
+  optional Version compiler_version = 3;
+
 }
 
 // The plugin writes an encoded CodeGeneratorResponse to stdout.
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index 4d500f9..01f28b3 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -44,13 +44,11 @@
 // performance-minded Python code leverage the fast C++ implementation
 // directly.
 
+#include <algorithm>
 #include <google/protobuf/stubs/hash.h>
 #include <limits>
 #include <map>
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 #include <string>
 #include <utility>
 #include <vector>
@@ -62,11 +60,12 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/io/printer.h>
-#include <google/protobuf/descriptor.h>
 #include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/descriptor.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
 
+
 namespace google {
 namespace protobuf {
 namespace compiler {
@@ -74,12 +73,21 @@
 
 namespace {
 
+// Reimplemented here because we can't bring in
+// absl/strings/string_view_utils.h because it needs C++11.
+bool StrStartsWith(StringPiece sp, StringPiece x) {
+  return sp.size() >= x.size() && sp.substr(0, x.size()) == x;
+}
+bool StrEndsWith(StringPiece sp, StringPiece x) {
+  return sp.size() >= x.size() && sp.substr(sp.size() - x.size()) == x;
+}
+
 // Returns a copy of |filename| with any trailing ".protodevel" or ".proto
 // suffix stripped.
 // TODO(robinson): Unify with copy in compiler/cpp/internal/helpers.cc.
 string StripProto(const string& filename) {
-  const char* suffix = HasSuffixString(filename, ".protodevel")
-      ? ".protodevel" : ".proto";
+  const char* suffix =
+      StrEndsWith(filename, ".protodevel") ? ".protodevel" : ".proto";
   return StripSuffixString(filename, suffix);
 }
 
@@ -87,8 +95,8 @@
 // Returns the Python module name expected for a given .proto filename.
 string ModuleName(const string& filename) {
   string basename = StripProto(filename);
-  StripString(&basename, "-", '_');
-  StripString(&basename, "/", '.');
+  ReplaceCharacters(&basename, "-", '_');
+  ReplaceCharacters(&basename, "/", '.');
   return basename + "_pb2";
 }
 
@@ -107,20 +115,25 @@
   return module_name;
 }
 
+// Keywords reserved by the Python language.
+const char* const kKeywords[] = {
+    "False",   "None",     "True",     "and",    "as",    "assert", "break",
+    "class",   "continue", "def",      "del",    "elif",  "else",   "except",
+    "finally", "for",      "from",     "global", "if",    "import", "in",
+    "is",      "lambda",   "nonlocal", "not",    "or",    "pass",   "raise",
+    "return",  "try",      "while",    "with",   "yield",
+};
+const char* const* kKeywordsEnd =
+    kKeywords + (sizeof(kKeywords) / sizeof(kKeywords[0]));
 
-// Returns an import statement of form "from X.Y.Z import T" for the given
-// .proto filename.
-string ModuleImportStatement(const string& filename) {
-  string module_name = ModuleName(filename);
-  int last_dot_pos = module_name.rfind('.');
-  if (last_dot_pos == string::npos) {
-    // NOTE(petya): this is not tested as it would require a protocol buffer
-    // outside of any package, and I don't think that is easily achievable.
-    return "import " + module_name;
-  } else {
-    return "from " + module_name.substr(0, last_dot_pos) + " import " +
-        module_name.substr(last_dot_pos + 1);
+bool ContainsPythonKeyword(const string& module_name) {
+  std::vector<string> tokens = Split(module_name, ".");
+  for (int i = 0; i < tokens.size(); ++i) {
+    if (std::find(kKeywords, kKeywordsEnd, tokens[i]) != kKeywordsEnd) {
+      return true;
+    }
   }
+  return false;
 }
 
 
@@ -186,11 +199,6 @@
         "from google.protobuf import service_reflection\n");
   }
 
-  // Avoid circular imports if this module is descriptor_pb2.
-  if (!descriptor_proto) {
-    printer->Print(
-        "from google.protobuf import descriptor_pb2\n");
-  }
   printer->Print(
       "# @@protoc_insertion_point(imports)\n\n"
       "_sym_db = _symbol_database.Default()\n");
@@ -224,34 +232,34 @@
       return SimpleItoa(field.default_value_uint64());
     case FieldDescriptor::CPPTYPE_DOUBLE: {
       double value = field.default_value_double();
-      if (value == numeric_limits<double>::infinity()) {
+      if (value == std::numeric_limits<double>::infinity()) {
         // Python pre-2.6 on Windows does not parse "inf" correctly.  However,
         // a numeric literal that is too big for a double will become infinity.
         return "1e10000";
-      } else if (value == -numeric_limits<double>::infinity()) {
+      } else if (value == -std::numeric_limits<double>::infinity()) {
         // See above.
         return "-1e10000";
       } else if (value != value) {
         // infinity * 0 = nan
         return "(1e10000 * 0)";
       } else {
-        return SimpleDtoa(value);
+        return "float(" + SimpleDtoa(value) + ")";
       }
     }
     case FieldDescriptor::CPPTYPE_FLOAT: {
       float value = field.default_value_float();
-      if (value == numeric_limits<float>::infinity()) {
+      if (value == std::numeric_limits<float>::infinity()) {
         // Python pre-2.6 on Windows does not parse "inf" correctly.  However,
         // a numeric literal that is too big for a double will become infinity.
         return "1e10000";
-      } else if (value == -numeric_limits<float>::infinity()) {
+      } else if (value == -std::numeric_limits<float>::infinity()) {
         // See above.
         return "-1e10000";
       } else if (value != value) {
         // infinity - infinity = nan
         return "(1e10000 * 0)";
       } else {
-        return SimpleFtoa(value);
+        return "float(" + SimpleFtoa(value) + ")";
       }
     }
     case FieldDescriptor::CPPTYPE_BOOL:
@@ -314,7 +322,7 @@
   file_ = file;
   string module_name = ModuleName(file->name());
   string filename = module_name;
-  StripString(&filename, ".", '/');
+  ReplaceCharacters(&filename, ".", '/');
   filename += ".py";
 
   FileDescriptorProto fdp;
@@ -322,7 +330,7 @@
   fdp.SerializeToString(&file_descriptor_serialized_);
 
 
-  google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+  std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
   GOOGLE_CHECK(output.get());
   io::Printer printer(output.get(), '$');
   printer_ = &printer;
@@ -344,7 +352,9 @@
   // can only be successfully parsed after we register corresponding
   // extensions. Therefore we parse all options again here to recognize
   // custom options that may be unknown when we define the descriptors.
+  // This does not apply to services because they are not used by extensions.
   FixAllDescriptorOptions();
+  PrintServiceDescriptors();
   if (HasGenericServices(file)) {
     PrintServices();
   }
@@ -359,10 +369,32 @@
 void Generator::PrintImports() const {
   for (int i = 0; i < file_->dependency_count(); ++i) {
     const string& filename = file_->dependency(i)->name();
-    string import_statement = ModuleImportStatement(filename);
+
+    string module_name = ModuleName(filename);
     string module_alias = ModuleAlias(filename);
-    printer_->Print("$statement$ as $alias$\n", "statement",
-                    import_statement, "alias", module_alias);
+    if (ContainsPythonKeyword(module_name)) {
+      // If the module path contains a Python keyword, we have to quote the
+      // module name and import it using importlib. Otherwise the usual kind of
+      // import statement would result in a syntax error from the presence of
+      // the keyword.
+      printer_->Print("import importlib\n");
+      printer_->Print("$alias$ = importlib.import_module('$name$')\n", "alias",
+                      module_alias, "name", module_name);
+    } else {
+      int last_dot_pos = module_name.rfind('.');
+      string import_statement;
+      if (last_dot_pos == string::npos) {
+        // NOTE(petya): this is not tested as it would require a protocol buffer
+        // outside of any package, and I don't think that is easily achievable.
+        import_statement = "import " + module_name;
+      } else {
+        import_statement = "from " + module_name.substr(0, last_dot_pos) +
+                           " import " + module_name.substr(last_dot_pos + 1);
+      }
+      printer_->Print("$statement$ as $alias$\n", "statement", import_statement,
+                      "alias", module_alias);
+    }
+
     CopyPublicDependenciesAliases(module_alias, file_->dependency(i));
   }
   printer_->Print("\n");
@@ -377,16 +409,18 @@
 
 // Prints the single file descriptor for this file.
 void Generator::PrintFileDescriptor() const {
-  map<string, string> m;
+  std::map<string, string> m;
   m["descriptor_name"] = kDescriptorKey;
   m["name"] = file_->name();
   m["package"] = file_->package();
   m["syntax"] = StringifySyntax(file_->syntax());
+  m["options"] = OptionsValue(file_->options().SerializeAsString());
   const char file_descriptor_template[] =
       "$descriptor_name$ = _descriptor.FileDescriptor(\n"
       "  name='$name$',\n"
       "  package='$package$',\n"
-      "  syntax='$syntax$',\n";
+      "  syntax='$syntax$',\n"
+      "  serialized_options=$options$,\n";
   printer_->Print(m, file_descriptor_template);
   printer_->Indent();
   printer_->Print(
@@ -402,21 +436,28 @@
     }
     printer_->Print("]");
   }
+  if (file_->public_dependency_count() > 0) {
+    printer_->Print(",\npublic_dependencies=[");
+    for (int i = 0; i < file_->public_dependency_count(); ++i) {
+      string module_alias = ModuleAlias(file_->public_dependency(i)->name());
+      printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias",
+                      module_alias);
+    }
+    printer_->Print("]");
+  }
 
   // TODO(falk): Also print options and fix the message_type, enum_type,
   //             service and extension later in the generation.
 
   printer_->Outdent();
   printer_->Print(")\n");
-  printer_->Print("_sym_db.RegisterFileDescriptor($name$)\n", "name",
-                  kDescriptorKey);
   printer_->Print("\n");
 }
 
 // Prints descriptors and module-level constants for all top-level
 // enums defined in |file|.
 void Generator::PrintTopLevelEnums() const {
-  vector<pair<string, int> > top_level_enum_values;
+  std::vector<std::pair<string, int> > top_level_enum_values;
   for (int i = 0; i < file_->enum_type_count(); ++i) {
     const EnumDescriptor& enum_descriptor = *file_->enum_type(i);
     PrintEnum(enum_descriptor);
@@ -453,7 +494,7 @@
 // enum name to a Python EnumDescriptor object equivalent to
 // enum_descriptor.
 void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const {
-  map<string, string> m;
+  std::map<string, string> m;
   string module_level_descriptor_name =
       ModuleLevelDescriptorName(enum_descriptor);
   m["descriptor_name"] = module_level_descriptor_name;
@@ -479,9 +520,9 @@
   printer_->Outdent();
   printer_->Print("],\n");
   printer_->Print("containing_type=None,\n");
-  printer_->Print("options=$options_value$,\n",
+  printer_->Print("serialized_options=$options_value$,\n",
                   "options_value",
-                  OptionsValue("EnumOptions", options_string));
+                  OptionsValue(options_string));
   EnumDescriptorProto edp;
   PrintSerializedPbInterval(enum_descriptor, edp);
   printer_->Outdent();
@@ -527,9 +568,16 @@
   }
 }
 
-void Generator::PrintServices() const {
+void Generator::PrintServiceDescriptors() const {
   for (int i = 0; i < file_->service_count(); ++i) {
     PrintServiceDescriptor(*file_->service(i));
+    AddServiceToFileDescriptor(*file_->service(i));
+    printer_->Print("\n");
+  }
+}
+
+void Generator::PrintServices() const {
+  for (int i = 0; i < file_->service_count(); ++i) {
     PrintServiceClass(*file_->service(i));
     PrintServiceStub(*file_->service(i));
     printer_->Print("\n");
@@ -547,18 +595,18 @@
       "$service_name$ = _descriptor.ServiceDescriptor(\n",
       "service_name", service_name);
   printer_->Indent();
-  map<string, string> m;
+  std::map<string, string> m;
   m["name"] = descriptor.name();
   m["full_name"] = descriptor.full_name();
   m["file"] = kDescriptorKey;
   m["index"] = SimpleItoa(descriptor.index());
-  m["options_value"] = OptionsValue("ServiceOptions", options_string);
+  m["options_value"] = OptionsValue(options_string);
   const char required_function_arguments[] =
       "name='$name$',\n"
       "full_name='$full_name$',\n"
       "file=$file$,\n"
       "index=$index$,\n"
-      "options=$options_value$,\n";
+      "serialized_options=$options_value$,\n";
   printer_->Print(m, required_function_arguments);
 
   ServiceDescriptorProto sdp;
@@ -576,7 +624,7 @@
     m["serialized_options"] = CEscape(options_string);
     m["input_type"] = ModuleLevelDescriptorName(*(method->input_type()));
     m["output_type"] = ModuleLevelDescriptorName(*(method->output_type()));
-    m["options_value"] = OptionsValue("MethodOptions", options_string);
+    m["options_value"] = OptionsValue(options_string);
     printer_->Print("_descriptor.MethodDescriptor(\n");
     printer_->Indent();
     printer_->Print(
@@ -587,13 +635,16 @@
         "containing_service=None,\n"
         "input_type=$input_type$,\n"
         "output_type=$output_type$,\n"
-        "options=$options_value$,\n");
+        "serialized_options=$options_value$,\n");
     printer_->Outdent();
     printer_->Print("),\n");
   }
 
   printer_->Outdent();
-  printer_->Print("])\n\n");
+  printer_->Print("])\n");
+  printer_->Print("_sym_db.RegisterServiceDescriptor($name$)\n", "name",
+                  service_name);
+  printer_->Print("\n");
 }
 
 
@@ -643,7 +694,7 @@
                   "descriptor_name",
                   ModuleLevelDescriptorName(message_descriptor));
   printer_->Indent();
-  map<string, string> m;
+  std::map<string, string> m;
   m["name"] = message_descriptor.name();
   m["full_name"] = message_descriptor.full_name();
   m["file"] = kDescriptorKey;
@@ -680,10 +731,10 @@
   string options_string;
   message_descriptor.options().SerializeToString(&options_string);
   printer_->Print(
-      "options=$options_value$,\n"
+      "serialized_options=$options_value$,\n"
       "is_extendable=$extendable$,\n"
       "syntax='$syntax$'",
-      "options_value", OptionsValue("MessageOptions", options_string),
+      "options_value", OptionsValue(options_string),
       "extendable", message_descriptor.extension_range_count() > 0 ?
                       "True" : "False",
       "syntax", StringifySyntax(message_descriptor.file()->syntax()));
@@ -703,15 +754,23 @@
   printer_->Indent();
   for (int i = 0; i < message_descriptor.oneof_decl_count(); ++i) {
     const OneofDescriptor* desc = message_descriptor.oneof_decl(i);
-    map<string, string> m;
+    std::map<string, string> m;
     m["name"] = desc->name();
     m["full_name"] = desc->full_name();
     m["index"] = SimpleItoa(desc->index());
+    string options_string =
+        OptionsValue(desc->options().SerializeAsString());
+    if (options_string == "None") {
+      m["serialized_options"] = "";
+    } else {
+      m["serialized_options"] = ", serialized_options=" + options_string;
+    }
     printer_->Print(
         m,
         "_descriptor.OneofDescriptor(\n"
         "  name='$name$', full_name='$full_name$',\n"
-        "  index=$index$, containing_type=None, fields=[]),\n");
+        "  index=$index$, containing_type=None, "
+        "fields=[]$serialized_options$),\n");
   }
   printer_->Outdent();
   printer_->Print("],\n");
@@ -737,7 +796,7 @@
 // Prints all messages in |file|.
 void Generator::PrintMessages() const {
   for (int i = 0; i < file_->message_type_count(); ++i) {
-    vector<string> to_register;
+    std::vector<string> to_register;
     PrintMessage(*file_->message_type(i), "", &to_register);
     for (int j = 0; j < to_register.size(); ++j) {
       printer_->Print("_sym_db.RegisterMessage($name$)\n", "name",
@@ -757,7 +816,7 @@
 // Collect nested message names to_register for the symbol_database.
 void Generator::PrintMessage(const Descriptor& message_descriptor,
                              const string& prefix,
-                             vector<string>* to_register) const {
+                             std::vector<string>* to_register) const {
   string qualified_name(prefix + message_descriptor.name());
   to_register->push_back(qualified_name);
   printer_->Print(
@@ -767,7 +826,7 @@
   printer_->Indent();
 
   PrintNestedMessages(message_descriptor, qualified_name + ".", to_register);
-  map<string, string> m;
+  std::map<string, string> m;
   m["descriptor_key"] = kDescriptorKey;
   m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor);
   printer_->Print(m, "$descriptor_key$ = $descriptor_name$,\n");
@@ -783,7 +842,7 @@
 // Mutually recursive with PrintMessage().
 void Generator::PrintNestedMessages(const Descriptor& containing_descriptor,
                                     const string& prefix,
-                                    vector<string>* to_register) const {
+                                    std::vector<string>* to_register) const {
   for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) {
     printer_->Print("\n");
     PrintMessage(*containing_descriptor.nested_type(i), prefix, to_register);
@@ -816,7 +875,7 @@
     FixContainingTypeInDescriptor(enum_descriptor, &descriptor);
   }
   for (int i = 0; i < descriptor.oneof_decl_count(); ++i) {
-    map<string, string> m;
+    std::map<string, string> m;
     const OneofDescriptor* oneof = descriptor.oneof_decl(i);
     m["descriptor_name"] = ModuleLevelDescriptorName(descriptor);
     m["oneof_name"] = oneof->name();
@@ -835,7 +894,7 @@
 }
 
 void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const {
-  map<string, string> m;
+  std::map<string, string> m;
   m["descriptor_name"] = kDescriptorKey;
   m["message_name"] = descriptor.name();
   m["message_descriptor_name"] = ModuleLevelDescriptorName(descriptor);
@@ -845,9 +904,21 @@
   printer_->Print(m, file_descriptor_template);
 }
 
+void Generator::AddServiceToFileDescriptor(
+    const ServiceDescriptor& descriptor) const {
+  std::map<string, string> m;
+  m["descriptor_name"] = kDescriptorKey;
+  m["service_name"] = descriptor.name();
+  m["service_descriptor_name"] = ModuleLevelServiceDescriptorName(descriptor);
+  const char file_descriptor_template[] =
+      "$descriptor_name$.services_by_name['$service_name$'] = "
+      "$service_descriptor_name$\n";
+  printer_->Print(m, file_descriptor_template);
+}
+
 void Generator::AddEnumToFileDescriptor(
     const EnumDescriptor& descriptor) const {
-  map<string, string> m;
+  std::map<string, string> m;
   m["descriptor_name"] = kDescriptorKey;
   m["enum_name"] = descriptor.name();
   m["enum_descriptor_name"] = ModuleLevelDescriptorName(descriptor);
@@ -859,7 +930,7 @@
 
 void Generator::AddExtensionToFileDescriptor(
     const FieldDescriptor& descriptor) const {
-  map<string, string> m;
+  std::map<string, string> m;
   m["descriptor_name"] = kDescriptorKey;
   m["field_name"] = descriptor.name();
   const char file_descriptor_template[] =
@@ -882,7 +953,7 @@
                                         const string& python_dict_name) const {
   const string field_referencing_expression = FieldReferencingExpression(
       containing_type, field, python_dict_name);
-  map<string, string> m;
+  std::map<string, string> m;
   m["field_ref"] = field_referencing_expression;
   const Descriptor* foreign_message_type = field.message_type();
   if (foreign_message_type) {
@@ -955,6 +1026,10 @@
   for (int i = 0; i < file_->extension_count(); ++i) {
     AddExtensionToFileDescriptor(*file_->extension(i));
   }
+  // TODO(jieluo): Move this register to PrintFileDescriptor() when
+  // FieldDescriptor.file is added in generated file.
+  printer_->Print("_sym_db.RegisterFileDescriptor($name$)\n", "name",
+                  kDescriptorKey);
   printer_->Print("\n");
 }
 
@@ -981,7 +1056,7 @@
   FixForeignFieldsInField(extension_field.extension_scope(), extension_field,
                           "extensions_by_name");
 
-  map<string, string> m;
+  std::map<string, string> m;
   // Confusingly, for FieldDescriptors that happen to be extensions,
   // containing_type() means "extended type."
   // On the other hand, extension_scope() will give us what we normally
@@ -1014,31 +1089,26 @@
   // More circular references.  ::sigh::
   string options_string;
   descriptor.options().SerializeToString(&options_string);
-  map<string, string> m;
+  std::map<string, string> m;
   m["name"] = descriptor.name();
   m["index"] = SimpleItoa(descriptor.index());
   m["number"] = SimpleItoa(descriptor.number());
-  m["options"] = OptionsValue("EnumValueOptions", options_string);
+  m["options"] = OptionsValue(options_string);
   printer_->Print(
       m,
       "_descriptor.EnumValueDescriptor(\n"
       "  name='$name$', index=$index$, number=$number$,\n"
-      "  options=$options$,\n"
+      "  serialized_options=$options$,\n"
       "  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 {
+// Returns a CEscaped string of serialized_options.
+string Generator::OptionsValue(const string& serialized_options) const {
   if (serialized_options.length() == 0 || GeneratingDescriptorProto()) {
     return "None";
   } else {
-    string full_class_name = "descriptor_pb2." + class_name;
-//##!PY25    return "_descriptor._ParseOptions(" + full_class_name + "(), b'"
-//##!PY25        + CEscape(serialized_options)+ "')";
-    return "_descriptor._ParseOptions(" + full_class_name + "(), _b('"  //##PY25
-        + CEscape(serialized_options)+ "'))";  //##PY25
+//##!PY25    return "b'('" + CEscape(serialized_options)+ "')";
+    return "_b('"+ CEscape(serialized_options) + "')";  //##PY25
   }
 }
 
@@ -1047,7 +1117,7 @@
     const FieldDescriptor& field, bool is_extension) const {
   string options_string;
   field.options().SerializeToString(&options_string);
-  map<string, string> m;
+  std::map<string, string> m;
   m["name"] = field.name();
   m["full_name"] = field.full_name();
   m["index"] = SimpleItoa(field.index());
@@ -1058,7 +1128,9 @@
   m["has_default_value"] = field.has_default_value() ? "True" : "False";
   m["default_value"] = StringifyDefaultValue(field);
   m["is_extension"] = is_extension ? "True" : "False";
-  m["options"] = OptionsValue("FieldOptions", options_string);
+  m["serialized_options"] = OptionsValue(options_string);
+  m["json_name"] = field.has_json_name() ?
+      ", json_name='" + field.json_name() + "'": "";
   // We always set message_type and enum_type to None at this point, and then
   // these fields in correctly after all referenced descriptors have been
   // defined and/or imported (see FixForeignFieldsInDescriptors()).
@@ -1069,7 +1141,7 @@
     "  has_default_value=$has_default_value$, default_value=$default_value$,\n"
     "  message_type=None, enum_type=None, containing_type=None,\n"
     "  is_extension=$is_extension$, extension_scope=None,\n"
-    "  options=$options$)";
+    "  serialized_options=$serialized_options$$json_name$, file=DESCRIPTOR)";
   printer_->Print(m, field_descriptor_decl);
 }
 
@@ -1198,23 +1270,18 @@
 void PrintDescriptorOptionsFixingCode(const string& descriptor,
                                       const string& options,
                                       io::Printer* printer) {
-  // TODO(xiaofeng): I have added a method _SetOptions() to DescriptorBase
-  // in proto2 python runtime but it couldn't be used here because appengine
-  // uses a snapshot version of the library in which the new method is not
-  // yet present. After appengine has synced their runtime library, the code
-  // below should be cleaned up to use _SetOptions().
+  // Reset the _options to None thus DescriptorBase.GetOptions() can
+  // parse _options again after extensions are registered.
   printer->Print(
-      "$descriptor$.has_options = True\n"
-      "$descriptor$._options = $options$\n",
-      "descriptor", descriptor, "options", options);
+      "$descriptor$._options = None\n",
+      "descriptor", descriptor);
 }
 }  // namespace
 
 // Prints expressions that set the options field of all descriptors.
 void Generator::FixAllDescriptorOptions() const {
   // Prints an expression that sets the file descriptor's options.
-  string file_options = OptionsValue(
-      "FileOptions", file_->options().SerializeAsString());
+  string file_options = OptionsValue(file_->options().SerializeAsString());
   if (file_options != "None") {
     PrintDescriptorOptionsFixingCode(kDescriptorKey, file_options, printer_);
   }
@@ -1235,19 +1302,30 @@
   }
 }
 
+void Generator::FixOptionsForOneof(const OneofDescriptor& oneof) const {
+  string oneof_options = OptionsValue(oneof.options().SerializeAsString());
+  if (oneof_options != "None") {
+    string oneof_name = strings::Substitute(
+        "$0.$1['$2']",
+        ModuleLevelDescriptorName(*oneof.containing_type()),
+        "oneofs_by_name", oneof.name());
+    PrintDescriptorOptionsFixingCode(oneof_name, oneof_options, printer_);
+  }
+}
+
 // Prints expressions that set the options for an enum descriptor and its
 // value descriptors.
 void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const {
   string descriptor_name = ModuleLevelDescriptorName(enum_descriptor);
   string enum_options = OptionsValue(
-      "EnumOptions", enum_descriptor.options().SerializeAsString());
+      enum_descriptor.options().SerializeAsString());
   if (enum_options != "None") {
     PrintDescriptorOptionsFixingCode(descriptor_name, enum_options, printer_);
   }
   for (int i = 0; i < enum_descriptor.value_count(); ++i) {
     const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(i);
     string value_options = OptionsValue(
-        "EnumValueOptions", value_descriptor.options().SerializeAsString());
+        value_descriptor.options().SerializeAsString());
     if (value_options != "None") {
       PrintDescriptorOptionsFixingCode(
           StringPrintf("%s.values_by_name[\"%s\"]", descriptor_name.c_str(),
@@ -1261,8 +1339,7 @@
 // extensions).
 void Generator::FixOptionsForField(
     const FieldDescriptor& field) const {
-  string field_options = OptionsValue(
-      "FieldOptions", field.options().SerializeAsString());
+  string field_options = OptionsValue(field.options().SerializeAsString());
   if (field_options != "None") {
     string field_name;
     if (field.is_extension()) {
@@ -1288,6 +1365,10 @@
   for (int i = 0; i < descriptor.nested_type_count(); ++i) {
     FixOptionsForMessage(*descriptor.nested_type(i));
   }
+  // Oneofs.
+  for (int i = 0; i < descriptor.oneof_decl_count(); ++i) {
+    FixOptionsForOneof(*descriptor.oneof_decl(i));
+  }
   // Enums.
   for (int i = 0; i < descriptor.enum_type_count(); ++i) {
     FixOptionsForEnum(*descriptor.enum_type(i));
@@ -1304,7 +1385,7 @@
   }
   // Message option for this message.
   string message_options = OptionsValue(
-      "MessageOptions", descriptor.options().SerializeAsString());
+      descriptor.options().SerializeAsString());
   if (message_options != "None") {
     string descriptor_name = ModuleLevelDescriptorName(descriptor);
     PrintDescriptorOptionsFixingCode(descriptor_name,
@@ -1318,8 +1399,17 @@
 void Generator::CopyPublicDependenciesAliases(
     const string& copy_from, const FileDescriptor* file) const {
   for (int i = 0; i < file->public_dependency_count(); ++i) {
+    string module_name = ModuleName(file->public_dependency(i)->name());
     string module_alias = ModuleAlias(file->public_dependency(i)->name());
-    printer_->Print("$alias$ = $copy_from$.$alias$\n", "alias", module_alias,
+    // There's no module alias in the dependent file if it was generated by
+    // an old protoc (less than 3.0.0-alpha-1). Use module name in this
+    // situation.
+    printer_->Print("try:\n"
+                    "  $alias$ = $copy_from$.$alias$\n"
+                    "except AttributeError:\n"
+                    "  $alias$ = $copy_from$.$module$\n",
+                    "alias", module_alias,
+                    "module", module_name,
                     "copy_from", copy_from);
     CopyPublicDependenciesAliases(copy_from, file->public_dependency(i));
   }
diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h
index aa0f5fc..8e4050d 100644
--- a/src/google/protobuf/compiler/python/python_generator.h
+++ b/src/google/protobuf/compiler/python/python_generator.h
@@ -48,6 +48,7 @@
 class EnumDescriptor;
 class EnumValueDescriptor;
 class FieldDescriptor;
+class OneofDescriptor;
 class ServiceDescriptor;
 
 namespace io { class Printer; }
@@ -96,10 +97,10 @@
 
   void PrintMessages() const;
   void PrintMessage(const Descriptor& message_descriptor, const string& prefix,
-                    vector<string>* to_register) const;
+                    std::vector<string>* to_register) const;
   void PrintNestedMessages(const Descriptor& containing_descriptor,
                            const string& prefix,
-                           vector<string>* to_register) const;
+                           std::vector<string>* to_register) const;
 
   void FixForeignFieldsInDescriptors() const;
   void FixForeignFieldsInDescriptor(
@@ -111,6 +112,7 @@
   void AddMessageToFileDescriptor(const Descriptor& descriptor) const;
   void AddEnumToFileDescriptor(const EnumDescriptor& descriptor) const;
   void AddExtensionToFileDescriptor(const FieldDescriptor& descriptor) const;
+  void AddServiceToFileDescriptor(const ServiceDescriptor& descriptor) const;
   string FieldReferencingExpression(const Descriptor* containing_type,
                                     const FieldDescriptor& field,
                                     const string& python_dict_name) const;
@@ -125,15 +127,15 @@
   void FixForeignFieldsInNestedExtensions(const Descriptor& descriptor) const;
 
   void PrintServices() const;
+  void PrintServiceDescriptors() const;
   void PrintServiceDescriptor(const ServiceDescriptor& descriptor) const;
   void PrintServiceClass(const ServiceDescriptor& descriptor) const;
   void PrintServiceStub(const ServiceDescriptor& descriptor) const;
   void PrintDescriptorKeyAndModuleName(
-      const ServiceDescriptor& descriptor) const ;
+      const ServiceDescriptor& descriptor) const;
 
   void PrintEnumValueDescriptor(const EnumValueDescriptor& descriptor) const;
-  string OptionsValue(const string& class_name,
-                      const string& serialized_options) const;
+  string OptionsValue(const string& serialized_options) const;
   bool GeneratingDescriptorProto() const;
 
   template <typename DescriptorT>
@@ -148,6 +150,7 @@
 
   void FixAllDescriptorOptions() const;
   void FixOptionsForField(const FieldDescriptor& field) const;
+  void FixOptionsForOneof(const OneofDescriptor& oneof) const;
   void FixOptionsForEnum(const EnumDescriptor& descriptor) const;
   void FixOptionsForMessage(const Descriptor& descriptor) const;
 
diff --git a/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
index e82bbae..2f09680 100644
--- a/src/google/protobuf/compiler/python/python_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
@@ -35,18 +35,17 @@
 //   worth.
 
 #include <memory>
-#ifndef _SHARED_PTR_H
-#include <google/protobuf/stubs/shared_ptr.h>
-#endif
 
 #include <google/protobuf/compiler/python/python_generator.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/io/printer.h>
 
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
-#include <google/protobuf/testing/file.h>
 
 namespace google {
 namespace protobuf {
@@ -72,7 +71,7 @@
 
   void TryInsert(const string& filename, const string& insertion_point,
                  GeneratorContext* context) const {
-    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+    std::unique_ptr<io::ZeroCopyOutputStream> output(
         context->OpenForInsert(filename, insertion_point));
     io::Printer printer(output.get(), '$');
     printer.Print("// inserted $name$\n", "name", insertion_point);
@@ -114,6 +113,53 @@
   EXPECT_EQ(0, cli.Run(5, argv));
 }
 
+// This test verifies that the generated Python output uses regular imports (as
+// opposed to importlib) in the usual case where the .proto file paths do not
+// not contain any Python keywords.
+TEST(PythonPluginTest, ImportTest) {
+  // Create files test1.proto and test2.proto with the former importing the
+  // latter.
+  GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test1.proto",
+                             "syntax = \"proto3\";\n"
+                             "package foo;\n"
+                             "import \"test2.proto\";"
+                             "message Message1 {\n"
+                             "  Message2 message_2 = 1;\n"
+                             "}\n",
+                             true));
+  GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test2.proto",
+                             "syntax = \"proto3\";\n"
+                             "package foo;\n"
+                             "message Message2 {}\n",
+                             true));
+
+  google::protobuf::compiler::CommandLineInterface cli;
+  cli.SetInputsAreProtoPathRelative(true);
+  python::Generator python_generator;
+  cli.RegisterGenerator("--python_out", &python_generator, "");
+  string proto_path = "-I" + TestTempDir();
+  string python_out = "--python_out=" + TestTempDir();
+  const char* argv[] = {"protoc", proto_path.c_str(), "-I.", python_out.c_str(),
+                        "test1.proto"};
+  ASSERT_EQ(0, cli.Run(5, argv));
+
+  // Loop over the lines of the generated code and verify that we find an
+  // ordinary Python import but do not find the string "importlib".
+  string output;
+  GOOGLE_CHECK_OK(File::GetContents(TestTempDir() + "/test1_pb2.py", &output,
+                             true));
+  std::vector<string> lines = Split(output, "\n");
+  string expected_import = "import test2_pb2";
+  bool found_expected_import = false;
+  for (int i = 0; i < lines.size(); ++i) {
+    if (lines[i].find(expected_import) != string::npos) {
+      found_expected_import = true;
+    }
+    EXPECT_EQ(string::npos, lines[i].find("importlib"));
+  }
+  EXPECT_TRUE(found_expected_import);
+}
+
 }  // namespace
 }  // namespace python
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_code.rb b/src/google/protobuf/compiler/ruby/ruby_generated_code_pb.rb
similarity index 100%
rename from src/google/protobuf/compiler/ruby/ruby_generated_code.rb
rename to src/google/protobuf/compiler/ruby/ruby_generated_code_pb.rb
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc
index 9692f1b..bd737c0 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generator.cc
+++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc
@@ -39,8 +39,6 @@
 
 #include <google/protobuf/compiler/ruby/ruby_generator.h>
 
-using google::protobuf::internal::scoped_ptr;
-
 namespace google {
 namespace protobuf {
 namespace compiler {
@@ -48,7 +46,7 @@
 
 // Forward decls.
 std::string IntToString(int32 value);
-std::string StripDotProto(const std::string& proto_file);
+std::string GetRequireName(const std::string& proto_file);
 std::string LabelForField(google::protobuf::FieldDescriptor* field);
 std::string TypeName(google::protobuf::FieldDescriptor* field);
 void GenerateMessage(const google::protobuf::Descriptor* message,
@@ -70,9 +68,13 @@
   return os.str();
 }
 
-std::string StripDotProto(const std::string& proto_file) {
+std::string GetRequireName(const std::string& proto_file) {
   int lastindex = proto_file.find_last_of(".");
-  return proto_file.substr(0, lastindex);
+  return proto_file.substr(0, lastindex) + "_pb";
+}
+
+std::string GetOutputFilename(const std::string& proto_file) {
+  return GetRequireName(proto_file) + ".rb";
 }
 
 std::string LabelForField(const google::protobuf::FieldDescriptor* field) {
@@ -233,15 +235,52 @@
     "end\n");
 }
 
-// Module names, class names, and enum value names need to be Ruby constants,
-// which must start with a capital letter.
+// Locale-agnostic utility functions.
+bool IsLower(char ch) { return ch >= 'a' && ch <= 'z'; }
+
+bool IsUpper(char ch) { return ch >= 'A' && ch <= 'Z'; }
+
+bool IsAlpha(char ch) { return IsLower(ch) || IsUpper(ch); }
+
+char ToUpper(char ch) { return IsLower(ch) ? (ch - 'a' + 'A') : ch; }
+
+
+// Package names in protobuf are snake_case by convention, but Ruby module
+// names must be PascalCased.
+//
+//   foo_bar_baz -> FooBarBaz
+std::string PackageToModule(const std::string& name) {
+  bool next_upper = true;
+  std::string result;
+  result.reserve(name.size());
+
+  for (int i = 0; i < name.size(); i++) {
+    if (name[i] == '_') {
+      next_upper = true;
+    } else {
+      if (next_upper) {
+        result.push_back(ToUpper(name[i]));
+      } else {
+        result.push_back(name[i]);
+      }
+      next_upper = false;
+    }
+  }
+
+  return result;
+}
+
+// Class and enum names in protobuf should be PascalCased by convention, but
+// since there is nothing enforcing this we need to ensure that they are valid
+// Ruby constants.  That mainly means making sure that the first character is
+// an upper-case letter.
 std::string RubifyConstant(const std::string& name) {
   std::string ret = name;
   if (!ret.empty()) {
-    if (ret[0] >= 'a' && ret[0] <= 'z') {
+    if (IsLower(ret[0])) {
       // If it starts with a lowercase letter, capitalize it.
-      ret[0] = ret[0] - 'a' + 'A';
-    } else if (ret[0] < 'A' || ret[0] > 'Z') {
+      ret[0] = ToUpper(ret[0]);
+    } else if (!IsAlpha(ret[0])) {
       // Otherwise (e.g. if it begins with an underscore), we need to come up
       // with some prefix that starts with a capital letter. We could be smarter
       // here, e.g. try to strip leading underscores, but this may cause other
@@ -250,6 +289,7 @@
       ret = "PB_" + ret;
     }
   }
+
   return ret;
 }
 
@@ -297,9 +337,20 @@
 }
 
 int GeneratePackageModules(
-    std::string package_name,
+    const FileDescriptor* file,
     google::protobuf::io::Printer* printer) {
   int levels = 0;
+  bool need_change_to_module;
+  std::string package_name;
+
+  if (file->options().has_ruby_package()) {
+    package_name = file->options().ruby_package();
+    need_change_to_module = false;
+  } else {
+    package_name = file->package();
+    need_change_to_module = true;
+  }
+
   while (!package_name.empty()) {
     size_t dot_index = package_name.find(".");
     string component;
@@ -310,7 +361,9 @@
       component = package_name.substr(0, dot_index);
       package_name = package_name.substr(dot_index + 1);
     }
-    component = RubifyConstant(component);
+    if (need_change_to_module) {
+      component = PackageToModule(component);
+    }
     printer->Print(
       "module $name$\n",
       "name", component);
@@ -331,8 +384,69 @@
   }
 }
 
-void GenerateFile(const google::protobuf::FileDescriptor* file,
-                  google::protobuf::io::Printer* printer) {
+bool UsesTypeFromFile(const Descriptor* message, const FileDescriptor* file,
+                      string* error) {
+  for (int i = 0; i < message->field_count(); i++) {
+    const FieldDescriptor* field = message->field(i);
+    if ((field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+         field->message_type()->file() == file) ||
+        (field->type() == FieldDescriptor::TYPE_ENUM &&
+         field->enum_type()->file() == file)) {
+      *error = "proto3 message field " + field->full_name() + " in file " +
+               file->name() + " has a dependency on a type from proto2 file " +
+               file->name() +
+               ".  Ruby doesn't support proto2 yet, so we must fail.";
+      return true;
+    }
+  }
+
+  for (int i = 0; i < message->nested_type_count(); i++) {
+    if (UsesTypeFromFile(message->nested_type(i), file, error)) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+// Ruby doesn't currently support proto2.  This causes a failure even for proto3
+// files that import proto2.  But in some cases, the proto2 file is only being
+// imported to extend another proto2 message.  The prime example is declaring
+// custom options by extending FileOptions/FieldOptions/etc.
+//
+// If the proto3 messages don't have any proto2 submessages, it is safe to omit
+// the dependency completely.  Users won't be able to use any proto2 extensions,
+// but they already couldn't because proto2 messages aren't supported.
+//
+// If/when we add proto2 support, we should remove this.
+bool MaybeEmitDependency(const FileDescriptor* import,
+                         const FileDescriptor* from,
+                         io::Printer* printer,
+                         string* error) {
+  if (import->syntax() == FileDescriptor::SYNTAX_PROTO2) {
+    for (int i = 0; i < from->message_type_count(); i++) {
+      if (UsesTypeFromFile(from->message_type(i), import, error)) {
+        // Error text was already set by UsesTypeFromFile().
+        return false;
+      }
+    }
+
+    // Ok to omit this proto2 dependency -- so we won't print anything.
+    GOOGLE_LOG(WARNING) << "Omitting proto2 dependency '" << import->name()
+                        << "' from proto3 output file '"
+                        << GetOutputFilename(from->name())
+                        << "' because we don't support proto2 and no proto2 "
+                           "types from that file are being used.";
+    return true;
+  } else {
+    printer->Print(
+      "require '$name$'\n", "name", GetRequireName(import->name()));
+    return true;
+  }
+}
+
+bool GenerateFile(const FileDescriptor* file, io::Printer* printer,
+                  string* error) {
   printer->Print(
     "# Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
     "# source: $filename$\n"
@@ -343,9 +457,9 @@
     "require 'google/protobuf'\n\n");
 
   for (int i = 0; i < file->dependency_count(); i++) {
-    const std::string& name = file->dependency(i)->name();
-    printer->Print(
-      "require '$name$'\n", "name", StripDotProto(name));
+    if (!MaybeEmitDependency(file->dependency(i), file, printer, error)) {
+      return false;
+    }
   }
 
   printer->Print(
@@ -361,7 +475,7 @@
   printer->Print(
     "end\n\n");
 
-  int levels = GeneratePackageModules(file->package(), printer);
+  int levels = GeneratePackageModules(file, printer);
   for (int i = 0; i < file->message_type_count(); i++) {
     GenerateMessageAssignment("", file->message_type(i), printer);
   }
@@ -369,6 +483,7 @@
     GenerateEnumAssignment("", file->enum_type(i), printer);
   }
   EndPackageModules(levels, printer);
+  return true;
 }
 
 bool Generator::Generate(
@@ -384,15 +499,11 @@
     return false;
   }
 
-  std::string filename =
-      StripDotProto(file->name()) + ".rb";
-  scoped_ptr<io::ZeroCopyOutputStream> output(
-      generator_context->Open(filename));
+  std::unique_ptr<io::ZeroCopyOutputStream> output(
+      generator_context->Open(GetOutputFilename(file->name())));
   io::Printer printer(output.get(), '$');
 
-  GenerateFile(file, &printer);
-
-  return true;
+  return GenerateFile(file, &printer, error);
 }
 
 }  // namespace ruby
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.h b/src/google/protobuf/compiler/ruby/ruby_generator.h
index 75555c3..8c1dfa2 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generator.h
+++ b/src/google/protobuf/compiler/ruby/ruby_generator.h
@@ -28,6 +28,8 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+// Generates Ruby code for a given .proto file.
+
 #ifndef GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__
 #define GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__
 
@@ -40,6 +42,10 @@
 namespace compiler {
 namespace ruby {
 
+// CodeGenerator implementation for generated Ruby protocol buffer classes.
+// If you create your own protocol compiler binary and you want it to support
+// Ruby output, you can do so by registering an instance of this
+// CodeGenerator with the CommandLineInterface in your main() function.
 class LIBPROTOC_EXPORT Generator
     : public google::protobuf::compiler::CodeGenerator {
   virtual bool Generate(
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
index 1b04cb3..1aabe8a 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
+++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
@@ -45,22 +45,8 @@
 namespace ruby {
 namespace {
 
-string FindRubyTestDir(const string& file) {
-  // Inspired by TestSourceDir() in src/google/protobuf/testing/googletest.cc.
-#ifndef GOOGLE_THIRD_PARTY_PROTOBUF
-  string prefix = ".";
-  while (!File::Exists(prefix + "/src/google/protobuf/compiler/ruby" + file)) {
-    if (!File::Exists(prefix)) {
-      GOOGLE_LOG(FATAL)
-          << "Could not find Ruby test directory. Please run tests from "
-             "somewhere within the protobuf source package.";
-    }
-    prefix += "/..";
-  }
-  return prefix + "/src/google/protobuf/compiler/ruby";
-#else
-  return "third_party/protobuf/src/google/protobuf/compiler/ruby";
-#endif  // GOOGLE_THIRD_PARTY_PROTOBUF
+string FindRubyTestDir() {
+  return TestSourceDir() + "/google/protobuf/compiler/ruby";
 }
 
 // This test is a simple golden-file test over the output of the Ruby code
@@ -71,7 +57,7 @@
 // extensions to the point where we can do this test in a more automated way.
 
 TEST(RubyGeneratorTest, GeneratorTest) {
-  string ruby_tests = FindRubyTestDir("/ruby_generated_code.proto");
+  string ruby_tests = FindRubyTestDir();
 
   google::protobuf::compiler::CommandLineInterface cli;
   cli.SetInputsAreProtoPathRelative(true);
@@ -105,12 +91,12 @@
   // Load the generated output and compare to the expected result.
   string output;
   GOOGLE_CHECK_OK(File::GetContents(
-      TestTempDir() + "/ruby_generated_code.rb",
+      TestTempDir() + "/ruby_generated_code_pb.rb",
       &output,
       true));
   string expected_output;
   GOOGLE_CHECK_OK(File::GetContents(
-      ruby_tests + "/ruby_generated_code.rb",
+      ruby_tests + "/ruby_generated_code_pb.rb",
       &expected_output,
       true));
   EXPECT_EQ(expected_output, output);
diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc
index a30ac30..2e5a89a 100644
--- a/src/google/protobuf/compiler/subprocess.cc
+++ b/src/google/protobuf/compiler/subprocess.cc
@@ -33,6 +33,7 @@
 #include <google/protobuf/compiler/subprocess.h>
 
 #include <algorithm>
+#include <cstring>
 #include <iostream>
 
 #ifndef _WIN32
@@ -47,11 +48,20 @@
 #include <google/protobuf/message.h>
 #include <google/protobuf/stubs/substitute.h>
 
-
 namespace google {
 namespace protobuf {
 namespace compiler {
 
+namespace {
+char* portable_strdup(const char* s) {
+  char* ns = (char*) malloc(strlen(s) + 1);
+  if (ns != NULL) {
+    strcpy(ns, s);
+  }
+  return ns;
+}
+}  // namespace
+
 #ifdef _WIN32
 
 static void CloseHandleOrDie(HANDLE handle) {
@@ -115,7 +125,7 @@
   }
 
   // CreateProcess() mutates its second parameter.  WTF?
-  char* name_copy = strdup(program.c_str());
+  char* name_copy = portable_strdup(program.c_str());
 
   // Create the process.
   PROCESS_INFORMATION process_info;
@@ -261,12 +271,11 @@
   char* message;
 
   // WTF?
-  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-                FORMAT_MESSAGE_FROM_SYSTEM |
-                FORMAT_MESSAGE_IGNORE_INSERTS,
-                NULL, error_code, 0,
-                (LPTSTR)&message,  // NOT A BUG!
-                0, NULL);
+  FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+                     FORMAT_MESSAGE_IGNORE_INSERTS,
+                 NULL, error_code, 0,
+                 (LPSTR)&message,  // NOT A BUG!
+                 0, NULL);
 
   string result = message;
   LocalFree(message);
@@ -300,7 +309,7 @@
   GOOGLE_CHECK(pipe(stdin_pipe) != -1);
   GOOGLE_CHECK(pipe(stdout_pipe) != -1);
 
-  char* argv[2] = { strdup(program.c_str()), NULL };
+  char* argv[2] = { portable_strdup(program.c_str()), NULL };
 
   child_pid_ = fork();
   if (child_pid_ == -1) {
@@ -348,7 +357,6 @@
 
 bool Subprocess::Communicate(const Message& input, Message* output,
                              string* error) {
-
   GOOGLE_CHECK_NE(child_stdin_, -1) << "Must call Start() first.";
 
   // The "sighandler_t" typedef is GNU-specific, so define our own.
@@ -361,7 +369,7 @@
   string output_data;
 
   int input_pos = 0;
-  int max_fd = max(child_stdin_, child_stdout_);
+  int max_fd = std::max(child_stdin_, child_stdout_);
 
   while (child_stdout_ != -1) {
     fd_set read_fds;
diff --git a/src/google/protobuf/compiler/subprocess.h b/src/google/protobuf/compiler/subprocess.h
index 2513863..9d980b0 100644
--- a/src/google/protobuf/compiler/subprocess.h
+++ b/src/google/protobuf/compiler/subprocess.h
@@ -44,7 +44,6 @@
 
 #include <string>
 
-
 namespace google {
 namespace protobuf {
 
diff --git a/src/google/protobuf/compiler/test_plugin.cc b/src/google/protobuf/compiler/test_plugin.cc
index 4830fd7..c676ce8 100644
--- a/src/google/protobuf/compiler/test_plugin.cc
+++ b/src/google/protobuf/compiler/test_plugin.cc
@@ -37,7 +37,6 @@
 #include <stdlib.h>
 #include <google/protobuf/compiler/plugin.h>
 #include <google/protobuf/compiler/mock_code_generator.h>
-#include <google/protobuf/stubs/strutil.h>
 
 int main(int argc, char* argv[]) {
 #ifdef _MSC_VER
diff --git a/src/google/protobuf/compiler/zip_output_unittest.sh b/src/google/protobuf/compiler/zip_output_unittest.sh
index 6fc7136..f859791 100755
--- a/src/google/protobuf/compiler/zip_output_unittest.sh
+++ b/src/google/protobuf/compiler/zip_output_unittest.sh
@@ -41,6 +41,8 @@
 
 TEST_TMPDIR=.
 PROTOC=./protoc
+JAR=jar
+UNZIP=unzip
 
 echo '
   syntax = "proto2";
@@ -57,8 +59,9 @@
     || fail 'protoc failed.'
 
 echo "Testing output to zip..."
-if unzip -h > /dev/null; then
-  unzip -t $TEST_TMPDIR/testzip.zip > $TEST_TMPDIR/testzip.list || fail 'unzip failed.'
+if $UNZIP -h > /dev/null; then
+  $UNZIP -t $TEST_TMPDIR/testzip.zip > $TEST_TMPDIR/testzip.list \
+    || fail 'unzip failed.'
 
   grep 'testing: testzip\.pb\.cc *OK$' $TEST_TMPDIR/testzip.list > /dev/null \
     || fail 'testzip.pb.cc not found in output zip.'
@@ -73,8 +76,14 @@
 fi
 
 echo "Testing output to jar..."
-if jar c $TEST_TMPDIR/testzip.proto > /dev/null; then
-  jar tf $TEST_TMPDIR/testzip.jar > $TEST_TMPDIR/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.'
+
+  # Check that -interface.jar timestamps are normalized:
+  if [[ "$(TZ=UTC $JAR tvf $TEST_TMPDIR/testzip.jar)" != *'Tue Jan 01 00:00:00 UTC 1980'* ]]; then
+    fail 'Zip did not contain normalized timestamps'
+  fi
 
   grep '^test/jar/Foo\.java$' $TEST_TMPDIR/testzip.list > /dev/null \
     || fail 'Foo.java not found in output jar.'
diff --git a/src/google/protobuf/compiler/zip_writer.cc b/src/google/protobuf/compiler/zip_writer.cc
index 458cced..1799af6 100644
--- a/src/google/protobuf/compiler/zip_writer.cc
+++ b/src/google/protobuf/compiler/zip_writer.cc
@@ -70,6 +70,10 @@
 namespace protobuf {
 namespace compiler {
 
+// January 1, 1980 as a DOS date.
+// see https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
+static const uint16 kDosEpoch = 1 << 5 | 1;
+
 static const uint32 kCRC32Table[256] = {
   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
   0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
@@ -154,7 +158,7 @@
   WriteShort(&output, 0);  // flags
   WriteShort(&output, 0);  // compression method: stored
   WriteShort(&output, 0);  // last modified time
-  WriteShort(&output, 0);  // last modified date
+  WriteShort(&output, kDosEpoch);  // last modified date
   output.WriteLittleEndian32(info.crc32);  // crc-32
   output.WriteLittleEndian32(info.size);  // compressed size
   output.WriteLittleEndian32(info.size);  // uncompressed size
@@ -185,7 +189,7 @@
     WriteShort(&output, 0);  // flags
     WriteShort(&output, 0);  // compression method: stored
     WriteShort(&output, 0);  // last modified time
-    WriteShort(&output, 0);  // last modified date
+    WriteShort(&output, kDosEpoch);  // last modified date
     output.WriteLittleEndian32(crc32);  // crc-32
     output.WriteLittleEndian32(size);  // compressed size
     output.WriteLittleEndian32(size);  // uncompressed size
diff --git a/src/google/protobuf/compiler/zip_writer.h b/src/google/protobuf/compiler/zip_writer.h
index 602e508..03db4d5 100644
--- a/src/google/protobuf/compiler/zip_writer.h
+++ b/src/google/protobuf/compiler/zip_writer.h
@@ -85,7 +85,7 @@
   };
 
   io::ZeroCopyOutputStream* raw_output_;
-  vector<FileInfo> files_;
+  std::vector<FileInfo> files_;
 };
 
 }  // namespace compiler