Down-integrate from google3.
diff --git a/src/google/protobuf/util/field_mask_util.cc b/src/google/protobuf/util/field_mask_util.cc
index a2e2a38..cf65ef2 100644
--- a/src/google/protobuf/util/field_mask_util.cc
+++ b/src/google/protobuf/util/field_mask_util.cc
@@ -53,7 +53,8 @@
   }
 }
 
-bool FieldMaskUtil::SnakeCaseToCamelCase(StringPiece input, string* output) {
+bool FieldMaskUtil::SnakeCaseToCamelCase(StringPiece input,
+                                         string* output) {
   output->clear();
   bool after_underscore = false;
   for (int i = 0; i < input.size(); ++i) {
@@ -82,7 +83,8 @@
   return true;
 }
 
-bool FieldMaskUtil::CamelCaseToSnakeCase(StringPiece input, string* output) {
+bool FieldMaskUtil::CamelCaseToSnakeCase(StringPiece input,
+                                         string* output) {
   output->clear();
   for (int i = 0; i < input.size(); ++i) {
     if (input[i] == '_') {
@@ -228,12 +230,13 @@
   }
 
   // Trims all fields not specified by this tree from the given message.
-  void TrimMessage(Message* message) {
+  // Returns true if the message is modified.
+  bool TrimMessage(Message* message) {
     // Do nothing if the tree is empty.
     if (root_.children.empty()) {
-      return;
+      return false;
     }
-    TrimMessage(&root_, message);
+    return TrimMessage(&root_, message);
   }
 
  private:
@@ -276,7 +279,8 @@
   void AddRequiredFieldPath(Node* node, const Descriptor* descriptor);
 
   // Trims all fields not specified by this sub-tree from the given message.
-  void TrimMessage(const Node* node, Message* message);
+  // Returns true if the message is actually modified
+  bool TrimMessage(const Node* node, Message* message);
 
   Node root_;
 
@@ -576,26 +580,39 @@
   }
 }
 
-void FieldMaskTree::TrimMessage(const Node* node, Message* message) {
+bool FieldMaskTree::TrimMessage(const Node* node, Message* message) {
   GOOGLE_DCHECK(!node->children.empty());
   const Reflection* reflection = message->GetReflection();
   const Descriptor* descriptor = message->GetDescriptor();
   const int32 field_count = descriptor->field_count();
+  bool modified = false;
   for (int index = 0; index < field_count; ++index) {
     const FieldDescriptor* field = descriptor->field(index);
     std::map<string, Node*>::const_iterator it =
         node->children.find(field->name());
     if (it == node->children.end()) {
+      if (field->is_repeated()) {
+        if (reflection->FieldSize(*message, field) != 0) {
+          modified = true;
+        }
+      } else {
+        if (reflection->HasField(*message, field)) {
+          modified = true;
+        }
+      }
       reflection->ClearField(message, field);
     } else {
       if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
         Node* child = it->second;
         if (!child->children.empty() && reflection->HasField(*message, field)) {
-          TrimMessage(child, reflection->MutableMessage(message, field));
+          bool nestedMessageChanged =
+              TrimMessage(child, reflection->MutableMessage(message, field));
+          modified = nestedMessageChanged || modified;
         }
       }
     }
   }
+  return modified;
 }
 
 }  // namespace
@@ -643,7 +660,8 @@
   tree.MergeToFieldMask(out);
 }
 
-bool FieldMaskUtil::IsPathInFieldMask(StringPiece path, const FieldMask& mask) {
+bool FieldMaskUtil::IsPathInFieldMask(StringPiece path,
+                                      const FieldMask& mask) {
   for (int i = 0; i < mask.paths_size(); ++i) {
     const string& mask_path = mask.paths(i);
     if (path == mask_path) {
@@ -670,15 +688,15 @@
   tree.MergeMessage(source, options, destination);
 }
 
-void FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* destination) {
+bool FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* message) {
   // Build a FieldMaskTree and walk through the tree to merge all specified
   // fields.
   FieldMaskTree tree;
   tree.MergeFromFieldMask(mask);
-  tree.TrimMessage(GOOGLE_CHECK_NOTNULL(destination));
+  return tree.TrimMessage(GOOGLE_CHECK_NOTNULL(message));
 }
 
-void FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* destination,
+bool FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* message,
                                 const TrimOptions& options) {
   // Build a FieldMaskTree and walk through the tree to merge all specified
   // fields.
@@ -687,9 +705,9 @@
   // If keep_required_fields is true, implicitely add required fields of
   // a message present in the tree to prevent from trimming.
   if (options.keep_required_fields()) {
-    tree.AddRequiredFieldPath(GOOGLE_CHECK_NOTNULL(destination->GetDescriptor()));
+    tree.AddRequiredFieldPath(GOOGLE_CHECK_NOTNULL(message->GetDescriptor()));
   }
-  tree.TrimMessage(GOOGLE_CHECK_NOTNULL(destination));
+  return tree.TrimMessage(GOOGLE_CHECK_NOTNULL(message));
 }
 
 }  // namespace util