Mark ab/6881855 as merged

Bug: 172690556
Change-Id: I0f9dd622bced9e740ca9c68de091d9f5b044dc91
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 9e8f89f..0a27b5e 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
 {
   "git": {
-    "sha1": "95047166acfbf49446a3b9e3633e353cf95c678c"
+    "sha1": "d03ae186b5d9f4d92cb1312ca77e8d9b05efc84d"
   }
 }
diff --git a/Cargo.toml b/Cargo.toml
index a0e2849..f4b1476 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,7 +12,7 @@
 
 [package]
 name = "regex-syntax"
-version = "0.6.18"
+version = "0.6.21"
 authors = ["The Rust Project Developers"]
 description = "A regular expression parser."
 homepage = "https://github.com/rust-lang/regex"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index a3d4187..7b56f32 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "regex-syntax"
-version = "0.6.18"  #:version
+version = "0.6.21"  #:version
 authors = ["The Rust Project Developers"]
 license = "MIT/Apache-2.0"
 repository = "https://github.com/rust-lang/regex"
diff --git a/METADATA b/METADATA
index 3aa3b91..dda6e41 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/regex-syntax/regex-syntax-0.6.18.crate"
+    value: "https://static.crates.io/crates/regex-syntax/regex-syntax-0.6.21.crate"
   }
-  version: "0.6.18"
+  version: "0.6.21"
   license_type: NOTICE
   last_upgrade_date {
     year: 2020
-    month: 5
-    day: 28
+    month: 11
+    day: 2
   }
 }
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 2506375..fff6ba4 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -2,8 +2,15 @@
 {
   "presubmit": [
     {
-      "name": "regex-syntax_host_test_src_lib",
-      "host": true
+      "host": true,
+      "name": "regex-syntax_host_test_src_lib"
+    },
+    {
+      "host": true,
+      "name": "libsqlite3-sys_host_test_src_lib"
+    },
+    {
+      "name": "libsqlite3-sys_device_test_src_lib"
     }
   ]
 }
diff --git a/src/ast/parse.rs b/src/ast/parse.rs
index f5b4548..55c5f79 100644
--- a/src/ast/parse.rs
+++ b/src/ast/parse.rs
@@ -98,12 +98,13 @@
 /// Returns true if the given character is a valid in a capture group name.
 ///
 /// If `first` is true, then `c` is treated as the first character in the
-/// group name (which is not allowed to be a digit).
+/// group name (which must be alphabetic or underscore).
 fn is_capture_char(c: char, first: bool) -> bool {
     c == '_'
-        || (!first && c >= '0' && c <= '9')
-        || (c >= 'a' && c <= 'z')
-        || (c >= 'A' && c <= 'Z')
+        || (!first
+            && (('0' <= c && c <= '9') || c == '.' || c == '[' || c == ']'))
+        || ('A' <= c && c <= 'Z')
+        || ('a' <= c && c <= 'z')
 }
 
 /// A builder for a regular expression parser.
@@ -3852,6 +3853,45 @@
         );
 
         assert_eq!(
+            parser("(?P<a_1>z)").parse(),
+            Ok(Ast::Group(ast::Group {
+                span: span(0..10),
+                kind: ast::GroupKind::CaptureName(ast::CaptureName {
+                    span: span(4..7),
+                    name: s("a_1"),
+                    index: 1,
+                }),
+                ast: Box::new(lit('z', 8)),
+            }))
+        );
+
+        assert_eq!(
+            parser("(?P<a.1>z)").parse(),
+            Ok(Ast::Group(ast::Group {
+                span: span(0..10),
+                kind: ast::GroupKind::CaptureName(ast::CaptureName {
+                    span: span(4..7),
+                    name: s("a.1"),
+                    index: 1,
+                }),
+                ast: Box::new(lit('z', 8)),
+            }))
+        );
+
+        assert_eq!(
+            parser("(?P<a[1]>z)").parse(),
+            Ok(Ast::Group(ast::Group {
+                span: span(0..11),
+                kind: ast::GroupKind::CaptureName(ast::CaptureName {
+                    span: span(4..8),
+                    name: s("a[1]"),
+                    index: 1,
+                }),
+                ast: Box::new(lit('z', 9)),
+            }))
+        );
+
+        assert_eq!(
             parser("(?P<").parse().unwrap_err(),
             TestError {
                 span: span(4..4),
diff --git a/src/hir/translate.rs b/src/hir/translate.rs
index 72f3f9a..44d2813 100644
--- a/src/hir/translate.rs
+++ b/src/hir/translate.rs
@@ -322,7 +322,7 @@
                         ast.negated,
                         &mut cls,
                     )?;
-                    if cls.iter().next().is_none() {
+                    if cls.ranges().is_empty() {
                         return Err(self.error(
                             ast.span,
                             ErrorKind::EmptyClassNotAllowed,
@@ -337,7 +337,7 @@
                         ast.negated,
                         &mut cls,
                     )?;
-                    if cls.iter().next().is_none() {
+                    if cls.ranges().is_empty() {
                         return Err(self.error(
                             ast.span,
                             ErrorKind::EmptyClassNotAllowed,
@@ -844,6 +844,11 @@
                 ast_class.negated,
                 class,
             )?;
+            if class.ranges().is_empty() {
+                let err = self
+                    .error(ast_class.span, ErrorKind::EmptyClassNotAllowed);
+                return Err(err);
+            }
         }
         result
     }
@@ -2318,6 +2323,21 @@
     }
 
     #[test]
+    #[cfg(feature = "unicode-gencat")]
+    fn class_unicode_any_empty() {
+        assert_eq!(
+            t_err(r"\P{any}"),
+            TestError {
+                kind: hir::ErrorKind::EmptyClassNotAllowed,
+                span: Span::new(
+                    Position::new(0, 1, 1),
+                    Position::new(7, 1, 8)
+                ),
+            }
+        );
+    }
+
+    #[test]
     #[cfg(not(feature = "unicode-age"))]
     fn class_unicode_age_disabled() {
         assert_eq!(
diff --git a/src/lib.rs b/src/lib.rs
index 7892668..f35c913 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -198,7 +198,7 @@
 ///
 /// These are the only characters that are allowed to be escaped, with one
 /// exception: an ASCII space character may be escaped when extended mode (with
-/// the `x` flag) is enabld. In particular, `is_meta_character(' ')` returns
+/// the `x` flag) is enabled. In particular, `is_meta_character(' ')` returns
 /// `false`.
 ///
 /// Note that the set of characters for which this function returns `true` or
diff --git a/src/unicode.rs b/src/unicode.rs
index 7e41439..a78362b 100644
--- a/src/unicode.rs
+++ b/src/unicode.rs
@@ -237,8 +237,16 @@
     fn canonical_binary(&self, name: &str) -> Result<CanonicalClassQuery> {
         let norm = symbolic_name_normalize(name);
 
-        if let Some(canon) = canonical_prop(&norm)? {
-            return Ok(CanonicalClassQuery::Binary(canon));
+        // This is a special case where 'cf' refers to the 'Format' general
+        // category, but where the 'cf' abbreviation is also an abbreviation
+        // for the 'Case_Folding' property. But we want to treat it as
+        // a general category. (Currently, we don't even support the
+        // 'Case_Folding' property. But if we do in the future, users will be
+        // required to spell it out.)
+        if norm != "cf" {
+            if let Some(canon) = canonical_prop(&norm)? {
+                return Ok(CanonicalClassQuery::Binary(canon));
+            }
         }
         if let Some(canon) = canonical_gencat(&norm)? {
             return Ok(CanonicalClassQuery::GeneralCategory(canon));