Don't break the RE2 object when compiling the reverse Prog fails.

Change-Id: I3d34d0e971563991b64e60ba38c6311fa2fc03f7
Reviewed-on: https://code-review.googlesource.com/c/re2/+/52631
Reviewed-by: Paul Wankadia <junyer@google.com>
diff --git a/re2/re2.cc b/re2/re2.cc
index 1395751..8c9ed4d 100644
--- a/re2/re2.cc
+++ b/re2/re2.cc
@@ -173,15 +173,20 @@
     empty_group_names = new std::map<int, std::string>;
   });
 
-  pattern_ = std::string(pattern);
+  pattern_.assign(pattern.data(), pattern.size());
   options_.Copy(options);
   entire_regexp_ = NULL;
+  error_ = empty_string;
+  error_code_ = NoError;
+  error_arg_.clear();
+  prefix_.clear();
+  prefix_foldcase_ = false;
   suffix_regexp_ = NULL;
   prog_ = NULL;
   num_captures_ = -1;
+  is_one_pass_ = false;
+
   rprog_ = NULL;
-  error_ = empty_string;
-  error_code_ = NoError;
   named_groups_ = NULL;
   group_names_ = NULL;
 
@@ -240,9 +245,11 @@
     if (re->rprog_ == NULL) {
       if (re->options_.log_errors())
         LOG(ERROR) << "Error reverse compiling '" << trunc(re->pattern_) << "'";
-      re->error_ =
-          new std::string("pattern too large - reverse compile failed");
-      re->error_code_ = RE2::ErrorPatternTooLarge;
+      // We no longer touch error_ and error_code_ because failing to compile
+      // the reverse Prog is not a showstopper: falling back to NFA execution
+      // is fine. More importantly, an RE2 object is supposed to be logically
+      // immutable: whatever ok() would have returned after Init() completed,
+      // it should continue to return that no matter what ReverseProg() does.
     }
   }, this);
   return rprog_;
diff --git a/re2/re2.h b/re2/re2.h
index 46409cb..44fb5af 100644
--- a/re2/re2.h
+++ b/re2/re2.h
@@ -741,29 +741,26 @@
 
   re2::Prog* ReverseProg() const;
 
-  std::string   pattern_;          // string regular expression
-  Options       options_;          // option flags
-  std::string   prefix_;           // required prefix (before regexp_)
-  bool          prefix_foldcase_;  // prefix is ASCII case-insensitive
-  re2::Regexp*  entire_regexp_;    // parsed regular expression
-  re2::Regexp*  suffix_regexp_;    // parsed regular expression, prefix removed
-  re2::Prog*    prog_;             // compiled program for regexp
-  int           num_captures_;     // Number of capturing groups
-  bool          is_one_pass_;      // can use prog_->SearchOnePass?
+  std::string pattern_;         // string regular expression
+  Options options_;             // option flags
+  re2::Regexp* entire_regexp_;  // parsed regular expression
+  const std::string* error_;    // error indicator (or points to empty string)
+  ErrorCode error_code_;        // error code
+  std::string error_arg_;       // fragment of regexp showing error
+  std::string prefix_;          // required prefix (before suffix_regexp_)
+  bool prefix_foldcase_;        // prefix_ is ASCII case-insensitive
+  re2::Regexp* suffix_regexp_;  // parsed regular expression, prefix_ removed
+  re2::Prog* prog_;             // compiled program for regexp
+  int num_captures_;            // number of capturing groups
+  bool is_one_pass_;            // can use prog_->SearchOnePass?
 
-  mutable re2::Prog*          rprog_;    // reverse program for regexp
-  mutable const std::string*  error_;    // Error indicator
-                                         // (or points to empty string)
-  mutable ErrorCode      error_code_;    // Error code
-  mutable std::string    error_arg_;     // Fragment of regexp showing error
-
+  // Reverse Prog for DFA execution only
+  mutable re2::Prog* rprog_;
   // Map from capture names to indices
   mutable const std::map<std::string, int>* named_groups_;
-
   // Map from capture indices to names
   mutable const std::map<int, std::string>* group_names_;
 
-  // Onces for lazy computations.
   mutable std::once_flag rprog_once_;
   mutable std::once_flag named_groups_once_;
   mutable std::once_flag group_names_once_;