Index: src/wp-includes/formatting.php
===================================================================
--- src/wp-includes/formatting.php	(revision 37258)
+++ src/wp-includes/formatting.php	(working copy)
@@ -216,7 +216,7 @@
 
 	// Look for shortcodes and HTML elements.
 
-	preg_match_all( '@\[/?([^<>&/\[\]\x00-\x20=]++)@', $text, $matches );
+	preg_match_all( '@\[/?(' . WP_SHORTCODE_NAME_NON_TERMINATORS . '++)@', $text, $matches );
 	$tagnames = array_intersect( array_keys( $shortcode_tags ), $matches[1] );
 	$found_shortcodes = ! empty( $tagnames );
 	$shortcode_regex = $found_shortcodes ? _get_wptexturize_shortcode_regex( $tagnames ) : '';
Index: src/wp-includes/shortcodes.php
===================================================================
--- src/wp-includes/shortcodes.php	(revision 37258)
+++ src/wp-includes/shortcodes.php	(working copy)
@@ -41,6 +41,14 @@
  */
 $shortcode_tags = array();
 
+if ( in_array( get_option( 'blog_charset' ), array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ) ) {
+	define( 'WP_SHORTCODE_NAME_TERMINATORS',	 '(?:[<>&\/\[\]\x00-\x20=]|\xC2\xA0)' );
+	define( 'WP_SHORTCODE_NAME_NON_TERMINATORS', '(?:[^<>&\/\[\]\x00-\x20=\xC2]|\xC2[^\xA0])' );
+} else {
+	define( 'WP_SHORTCODE_NAME_TERMINATORS',	 '[<>&\/\[\]\x00-\x20=]' );
+	define( 'WP_SHORTCODE_NAME_NON_TERMINATORS', '[^<>&\/\[\]\x00-\x20=]' );
+}
+
 /**
  * Add hook for shortcode tag.
  *
@@ -95,7 +103,7 @@
 		return;
 	}
 
-	if ( 0 !== preg_match( '@[<>&/\[\]\x00-\x20=]@', $tag ) ) {
+	if ( 0 !== preg_match( '@' . WP_SHORTCODE_NAME_TERMINATORS . '@', $tag ) ) {
 		/* translators: 1: shortcode name, 2: space separated list of reserved characters */
 		$message = sprintf( __( 'Invalid shortcode name: %1$s. Do not use spaces or reserved characters: %2$s' ), $tag, '& / < > [ ] =' );
 		_doing_it_wrong( __FUNCTION__, $message, '4.4.0' );
@@ -210,7 +218,7 @@
 		return $content;
 
 	// Find all registered tag names in $content.
-	preg_match_all( '@\[([^<>&/\[\]\x00-\x20=]++)@', $content, $matches );
+	preg_match_all( '@\[(' . WP_SHORTCODE_NAME_NON_TERMINATORS . '++)@', $content, $matches );
 	$tagnames = array_intersect( array_keys( $shortcode_tags ), $matches[1] );
 
 	if ( empty( $tagnames ) ) {
@@ -481,6 +489,7 @@
 function shortcode_parse_atts($text) {
 	$atts = array();
 	$pattern = get_shortcode_atts_regex();
+
 	$text = preg_replace("/[\x{00a0}\x{200b}]+/u", " ", $text);
 	if ( preg_match_all($pattern, $text, $match, PREG_SET_ORDER) ) {
 		foreach ($match as $m) {
@@ -578,7 +587,7 @@
 		return $content;
 
 	// Find all registered tag names in $content.
-	preg_match_all( '@\[([^<>&/\[\]\x00-\x20=]++)@', $content, $matches );
+	preg_match_all( '@\[(' . WP_SHORTCODE_NAME_NON_TERMINATORS . '++)@', $content, $matches );
 	$tagnames = array_intersect( array_keys( $shortcode_tags ), $matches[1] );
 
 	if ( empty( $tagnames ) ) {
Index: tests/phpunit/tests/shortcode.php
===================================================================
--- tests/phpunit/tests/shortcode.php	(revision 37258)
+++ tests/phpunit/tests/shortcode.php	(working copy)
@@ -312,6 +312,24 @@
 	}
 
 	/**
+	 * @ticket 35022
+	 */
+	public function test_non_breaking_space_following_shortcode_tag() {
+		do_shortcode( "[test-shortcode-tag\xC2\xA0foo=\"bar\"]" );
+		$this->assertSame( 'test-shortcode-tag', $this->tagname );
+		$this->assertSame( array( 'foo' => 'bar' ), $this->atts );
+	}
+
+	/**
+	 * @ticket 35022
+	 */
+	public function test_non_non_breaking_space_following_shortcode_tag() {
+		do_shortcode( "[test-shortcode-tag\xC2\xA1foo=\"bar\"]" );
+		$this->assertNull( $this->tagname );
+		$this->assertNull( $this->atts );
+	}
+
+	/**
 	 * @ticket 6562
 	 */
 	function test_utf8_whitespace_2() {
