[libc++] Validate the entire regex is consumed

This change would have warned about the bug found in D62451.
No unit tests since the exception should never throw.

Differential Revision: https://reviews.llvm.org/D62452
diff --git a/libcxx/include/regex b/libcxx/include/regex
index d13f9ad..d6f5585 100644
--- a/libcxx/include/regex
+++ b/libcxx/include/regex
@@ -965,7 +965,8 @@
     error_stack,
     __re_err_grammar,
     __re_err_empty,
-    __re_err_unknown
+    __re_err_unknown,
+    __re_err_parse
 };
 
 }  // regex_constants
@@ -2539,8 +2540,7 @@
         : __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0),
           __end_(0)
         {
-        if (__get_grammar(__flags_) == 0) __flags_ |= regex_constants::ECMAScript;
-        __parse(__p, __p + __traits_.length(__p));
+        __init(__p, __p + __traits_.length(__p));
         }
 
     _LIBCPP_INLINE_VISIBILITY
@@ -2548,8 +2548,7 @@
         : __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0),
           __end_(0)
         {
-        if (__get_grammar(__flags_) == 0) __flags_ |= regex_constants::ECMAScript;
-        __parse(__p, __p + __len);
+        __init(__p, __p + __len);
         }
 
 //     basic_regex(const basic_regex&) = default;
@@ -2561,8 +2560,7 @@
         : __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0),
           __end_(0)
         {
-        if (__get_grammar(__flags_) == 0) __flags_ |= regex_constants::ECMAScript;
-        __parse(__p.begin(), __p.end());
+        __init(__p.begin(), __p.end());
         }
 
     template <class _ForwardIterator>
@@ -2572,8 +2570,7 @@
         : __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0),
           __end_(0)
         {
-        if (__get_grammar(__flags_) == 0) __flags_ |= regex_constants::ECMAScript;
-        __parse(__first, __last);
+        __init(__first, __last);
         }
 #ifndef _LIBCPP_CXX03_LANG
     _LIBCPP_INLINE_VISIBILITY
@@ -2582,8 +2579,7 @@
         : __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0),
           __end_(0)
         {
-        if (__get_grammar(__flags_) == 0) __flags_ |= regex_constants::ECMAScript;
-        __parse(__il.begin(), __il.end());
+        __init(__il.begin(), __il.end());
         }
 #endif  // _LIBCPP_CXX03_LANG
 
@@ -2699,6 +2695,9 @@
     unsigned __loop_count() const {return __loop_count_;}
 
     template <class _ForwardIterator>
+        void
+        __init(_ForwardIterator __first, _ForwardIterator __last);
+    template <class _ForwardIterator>
         _ForwardIterator
         __parse(_ForwardIterator __first, _ForwardIterator __last);
     template <class _ForwardIterator>
@@ -3056,6 +3055,17 @@
 
 template <class _CharT, class _Traits>
 template <class _ForwardIterator>
+void
+basic_regex<_CharT, _Traits>::__init(_ForwardIterator __first, _ForwardIterator __last)
+{
+    if (__get_grammar(__flags_) == 0) __flags_ |= regex_constants::ECMAScript;
+    _ForwardIterator __temp = __parse(__first, __last);
+    if ( __temp != __last)
+        __throw_regex_error<regex_constants::__re_err_parse>();
+}
+
+template <class _CharT, class _Traits>
+template <class _ForwardIterator>
 _ForwardIterator
 basic_regex<_CharT, _Traits>::__parse(_ForwardIterator __first,
                                       _ForwardIterator __last)
diff --git a/libcxx/src/regex.cpp b/libcxx/src/regex.cpp
index a971f64..d31e494 100644
--- a/libcxx/src/regex.cpp
+++ b/libcxx/src/regex.cpp
@@ -53,6 +53,8 @@
         return "An invalid regex grammar has been requested.";
     case regex_constants::__re_err_empty:
         return "An empty regex is not allowed in the POSIX grammar.";
+    case regex_constants::__re_err_parse:
+        return "The parser did not consume the entire regular expression.";
     default:
         break;
     }