Provide hooks::context iff thread_local is supported.

Change-Id: I984b825fc4831142a520db10a1f5ab9c47ced348
Reviewed-on: https://code-review.googlesource.com/c/re2/+/51979
Reviewed-by: Paul Wankadia <junyer@google.com>
diff --git a/re2/re2.cc b/re2/re2.cc
index 2ac84a9..56dfcfc 100644
--- a/re2/re2.cc
+++ b/re2/re2.cc
@@ -657,7 +657,9 @@
   bool can_bit_state = prog_->CanBitState();
   size_t bit_state_text_max = kMaxBitStateBitmapSize / prog_->list_count();
 
+#ifdef RE2_HAVE_THREAD_LOCAL
   hooks::context = this;
+#endif
   bool dfa_failed = false;
   bool skipped_test = false;
   switch (re_anchor) {
@@ -1267,7 +1269,9 @@
 
 namespace hooks {
 
+#ifdef RE2_HAVE_THREAD_LOCAL
 thread_local const RE2* context = NULL;
+#endif
 
 template <typename T>
 union Hook {
diff --git a/re2/re2.h b/re2/re2.h
index 6d172ca..9bd1d13 100644
--- a/re2/re2.h
+++ b/re2/re2.h
@@ -196,6 +196,10 @@
 #include <mutex>
 #include <string>
 
+#ifdef __APPLE__
+#include <TargetConditionals.h>
+#endif
+
 #include "re2/stringpiece.h"
 
 namespace re2 {
@@ -950,6 +954,15 @@
 
 namespace hooks {
 
+// Most platforms support thread_local. Older versions of iOS don't support
+// thread_local, but for the sake of brevity, we lump together all versions
+// of Apple platforms that aren't macOS. If an iOS application really needs
+// the context pointee someday, we can get more specific then...
+#define RE2_HAVE_THREAD_LOCAL
+#if defined(__APPLE__) && defined(TARGET_OS_MAC) && !defined(TARGET_OS_OSX)
+#undef RE2_HAVE_THREAD_LOCAL
+#endif
+
 // A hook must not make any assumptions regarding the lifetime of the context
 // pointee beyond the current invocation of the hook. Pointers and references
 // obtained via the context pointee should be considered invalidated when the
@@ -959,7 +972,9 @@
 // A hook must not use RE2 for matching. Control flow reentering RE2::Match()
 // could result in infinite mutual recursion. To discourage that possibility,
 // RE2 will not maintain the context pointer correctly when used in that way.
+#ifdef RE2_HAVE_THREAD_LOCAL
 extern thread_local const RE2* context;
+#endif
 
 struct DFAStateCacheReset {
   int64_t state_budget;