Fix gcc 4.1 build (#1035) (#1913)

* Fix gcc 4.1.2 compilation of map_field_inl.h

Fixes "error: object missing in reference to '...'" errors from #1035

* Disable 64-bit map keys on gcc <= 4.1

* Add missing case statements
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index adb4a33..61a2389 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -1726,12 +1726,19 @@
         break;
       case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
         return hash<string>()(map_key.GetStringValue());
+#if defined(GOOGLE_PROTOBUF_HAVE_64BIT_HASH)
       case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
         return hash< ::google::protobuf::int64>()(map_key.GetInt64Value());
-      case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
-        return hash< ::google::protobuf::int32>()(map_key.GetInt32Value());
       case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
         return hash< ::google::protobuf::uint64>()(map_key.GetUInt64Value());
+#else
+      case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
+      case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
+        GOOGLE_LOG(FATAL) << "Unsupported on this platform.";
+        break;
+#endif
+      case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
+        return hash< ::google::protobuf::int32>()(map_key.GetInt32Value());
       case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
         return hash< ::google::protobuf::uint32>()(map_key.GetUInt32Value());
       case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h
index 01c9b89..2d84b0a 100644
--- a/src/google/protobuf/map_field_inl.h
+++ b/src/google/protobuf/map_field_inl.h
@@ -339,9 +339,9 @@
          default_enum_value>::Swap(
     MapFieldLiteType* other) {
   MapField* down_other = down_cast<MapField*>(other);
-  std::swap(MapFieldBase::repeated_field_, down_other->repeated_field_);
+  std::swap(this->MapFieldBase::repeated_field_, down_other->repeated_field_);
   MapFieldLiteType::Swap(other);
-  std::swap(MapFieldBase::state_, down_other->state_);
+  std::swap(this->MapFieldBase::state_, down_other->state_);
 }
 
 template <typename Key, typename T,
@@ -352,7 +352,7 @@
 MapField<Key, T, kKeyFieldType, kValueFieldType,
          default_enum_value>::SetEntryDescriptor(
     const Descriptor** descriptor) {
-  MapFieldBase::entry_descriptor_ = descriptor;
+  this->MapFieldBase::entry_descriptor_ = descriptor;
 }
 
 template <typename Key, typename T,
@@ -362,7 +362,7 @@
 void
 MapField<Key, T, kKeyFieldType, kValueFieldType,
          default_enum_value>::SetAssignDescriptorCallback(void (*callback)()) {
-  MapFieldBase::assign_descriptor_callback_ = callback;
+  this->MapFieldBase::assign_descriptor_callback_ = callback;
 }
 
 template <typename Key, typename T,
@@ -392,19 +392,19 @@
 void
 MapField<Key, T, kKeyFieldType, kValueFieldType,
          default_enum_value>::SyncRepeatedFieldWithMapNoLock() const {
-  if (MapFieldBase::repeated_field_ == NULL) {
-    if (MapFieldBase::arena_ == NULL) {
-      MapFieldBase::repeated_field_ = new RepeatedPtrField<Message>();
+  if (this->MapFieldBase::repeated_field_ == NULL) {
+    if (this->MapFieldBase::arena_ == NULL) {
+      this->MapFieldBase::repeated_field_ = new RepeatedPtrField<Message>();
     } else {
-      MapFieldBase::repeated_field_ =
+      this->MapFieldBase::repeated_field_ =
           Arena::CreateMessage<RepeatedPtrField<Message> >(
-              MapFieldBase::arena_);
+              this->MapFieldBase::arena_);
     }
   }
   const Map<Key, T>& map = GetInternalMap();
   RepeatedPtrField<EntryType>* repeated_field =
       reinterpret_cast<RepeatedPtrField<EntryType>*>(
-          MapFieldBase::repeated_field_);
+          this->MapFieldBase::repeated_field_);
 
   repeated_field->Clear();
 
@@ -413,7 +413,7 @@
     InitDefaultEntryOnce();
     GOOGLE_CHECK(default_entry_ != NULL);
     EntryType* new_entry =
-        down_cast<EntryType*>(default_entry_->New(MapFieldBase::arena_));
+        down_cast<EntryType*>(default_entry_->New(this->MapFieldBase::arena_));
     repeated_field->AddAllocated(new_entry);
     (*new_entry->mutable_key()) = it->first;
     (*new_entry->mutable_value()) = it->second;
@@ -430,8 +430,8 @@
   Map<Key, T>* map = const_cast<MapField*>(this)->MutableInternalMap();
   RepeatedPtrField<EntryType>* repeated_field =
       reinterpret_cast<RepeatedPtrField<EntryType>*>(
-          MapFieldBase::repeated_field_);
-  GOOGLE_CHECK(MapFieldBase::repeated_field_ != NULL);
+          this->MapFieldBase::repeated_field_);
+  GOOGLE_CHECK(this->MapFieldBase::repeated_field_ != NULL);
   map->clear();
   for (typename RepeatedPtrField<EntryType>::iterator it =
            repeated_field->begin(); it != repeated_field->end(); ++it) {
@@ -452,8 +452,8 @@
 MapField<Key, T, kKeyFieldType, kValueFieldType,
          default_enum_value>::SpaceUsedExcludingSelfNoLock() const {
   int size = 0;
-  if (MapFieldBase::repeated_field_ != NULL) {
-    size += MapFieldBase::repeated_field_->SpaceUsedExcludingSelf();
+  if (this->MapFieldBase::repeated_field_ != NULL) {
+    size += this->MapFieldBase::repeated_field_->SpaceUsedExcludingSelf();
   }
   Map<Key, T>* map = const_cast<MapField*>(this)->MutableInternalMap();
   size += sizeof(*map);
@@ -475,10 +475,10 @@
     const {
   if (default_entry_ == NULL) {
     MapFieldBase::InitMetadataOnce();
-    GOOGLE_CHECK(*MapFieldBase::entry_descriptor_ != NULL);
+    GOOGLE_CHECK(*this->MapFieldBase::entry_descriptor_ != NULL);
     default_entry_ = down_cast<const EntryType*>(
         MessageFactory::generated_factory()->GetPrototype(
-            *MapFieldBase::entry_descriptor_));
+            *this->MapFieldBase::entry_descriptor_));
   }
 }
 
diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h
index bf0b88b..be998b2 100644
--- a/src/google/protobuf/stubs/hash.h
+++ b/src/google/protobuf/stubs/hash.h
@@ -40,6 +40,7 @@
 
 #define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1
 #define GOOGLE_PROTOBUF_HAVE_HASH_SET 1
+#define GOOGLE_PROTOBUF_HAVE_64BIT_HASH 1
 
 // Use C++11 unordered_{map|set} if available.
 #if ((_LIBCPP_STD_VER >= 11) || \
@@ -92,6 +93,10 @@
 #  define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
 # endif
 
+# if __GNUC__ == 4 && __GNUC__MINOR__ <= 1
+#  undef GOOGLE_PROTOBUF_HAVE_64BIT_HASH
+# endif
+
 // Version checks for MSC.
 // Apparently Microsoft decided to move hash_map *back* to the std namespace in
 // MSVC 2010: