cpp_generator: Add support for --cpp_out=speed:...

Previously --cpp_out:lite was available to force the optimization mode
to the lite runtime. This adds --cpp_out=speed:...
which is needed to override the file specific options in cases where
libprotobuf-mutator is used for fuzzing since it depends on reflection.

Signed-off-by: Allen Webb <allenwebb@google.com>
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc
index e4fecd3..ba631d3 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -92,9 +92,12 @@
       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 == "speed") {
+      file_options.enforce_mode = EnforceOptimizeMode::kSpeed;
     } else if (options[i].first == "lite") {
-      file_options.enforce_lite = true;
+      file_options.enforce_mode = EnforceOptimizeMode::kLiteRuntime;
     } else if (options[i].first == "lite_implicit_weak_fields") {
+      file_options.enforce_mode = EnforceOptimizeMode::kLiteRuntime;
       file_options.lite_implicit_weak_fields = true;
       if (!options[i].second.empty()) {
         file_options.num_cc_files = strto32(options[i].second.c_str(),
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index bde2230..0701017 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -353,7 +353,7 @@
 inline bool IsProto2MessageSet(const Descriptor* descriptor,
                                const Options& options) {
   return !options.opensource_runtime &&
-         !options.enforce_lite &&
+         options.enforce_mode != EnforceOptimizeMode::kLiteRuntime &&
          !options.lite_implicit_weak_fields &&
          descriptor->options().message_set_wire_format() &&
          descriptor->full_name() == "google.protobuf.bridge.MessageSet";
@@ -362,7 +362,7 @@
 inline bool IsProto2MessageSetFile(const FileDescriptor* file,
                                    const Options& options) {
   return !options.opensource_runtime &&
-         !options.enforce_lite &&
+         options.enforce_mode != EnforceOptimizeMode::kLiteRuntime &&
          !options.lite_implicit_weak_fields &&
          file->name() == "net/proto2/bridge/proto/message_set.proto";
 }
@@ -419,9 +419,15 @@
 
 inline FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file,
                                                const Options& options) {
-  return options.enforce_lite
-      ? FileOptions::LITE_RUNTIME
-      : file->options().optimize_for();
+  switch (options.enforce_mode) {
+    case EnforceOptimizeMode::kSpeed:
+      return FileOptions::SPEED;
+    case EnforceOptimizeMode::kLiteRuntime:
+      return FileOptions::LITE_RUNTIME;
+    case EnforceOptimizeMode::kNoEnforcement:
+    default:
+      return file->options().optimize_for();
+  }
 }
 
 // This orders the messages in a .pb.cc as it's outputted by file.cc
diff --git a/src/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h
index fc90bd7..181a562 100644
--- a/src/google/protobuf/compiler/cpp/cpp_options.h
+++ b/src/google/protobuf/compiler/cpp/cpp_options.h
@@ -42,6 +42,12 @@
 
 namespace cpp {
 
+enum class EnforceOptimizeMode {
+  kNoEnforcement, // Use the runtime specified by the file specific options.
+  kSpeed, // This is the full runtime.
+  kLiteRuntime,
+};
+
 // Generator options (see generator.cc for a description of each):
 struct Options {
   std::string dllexport_decl;
@@ -49,7 +55,7 @@
   bool proto_h = false;
   bool transitive_pb_h = true;
   bool annotate_headers = false;
-  bool enforce_lite = false;
+  EnforceOptimizeMode enforce_mode = EnforceOptimizeMode::kNoEnforcement;
   bool table_driven_parsing = false;
   bool table_driven_serialization = false;
   bool lite_implicit_weak_fields = false;