Index: src/wp-includes/template.php
===================================================================
--- src/wp-includes/template.php	(revision 41149)
+++ src/wp-includes/template.php	(working copy)
@@ -85,6 +85,7 @@
  * and {@see '$type_template'} dynamic hooks, where `$type` is '404'.
  *
  * @since 1.5.0
+ * @since 4.9.0 The hierachy was extended to include specific templates dependent on the query.
  *
  * @see get_query_template()
  *
@@ -91,7 +92,37 @@
  * @return string Full path to 404 template file.
  */
 function get_404_template() {
-	return get_query_template('404');
+	$checks = array(
+		'taxonomy'      => 'taxonomy-%s',
+		'attachment_id' => 'attachment',
+		'page_id'       => 'page',
+		'pagename'      => 'page',
+		'post_type'     => 'single-%s',
+		'p'             => 'single',
+		'name'          => 'single',
+		'cat'           => 'category',
+		'category_name' => 'category',
+		'tag'           => 'tag',
+		'author'        => 'author',
+		'm'             => 'date',
+		'year'          => 'date',
+		'monthnum'      => 'date',
+		'day'           => 'date',
+	);
+
+	$templates = array();
+
+	foreach ( $checks as $query_var => $template ) {
+		$query_val = get_query_var( $query_var );
+		if ( ! empty( $query_val ) ) {
+			$templates[] = '404-' . sprintf( $template, $query_val ) . '.php';
+			break;
+		}
+	}
+
+	$templates[] = '404.php';
+
+	return get_query_template( '404', $templates );
 }
 
 /**
Index: tests/phpunit/tests/template.php
===================================================================
--- tests/phpunit/tests/template.php	(revision 41149)
+++ tests/phpunit/tests/template.php	(working copy)
@@ -41,6 +41,7 @@
 
 	public function setUp() {
 		parent::setUp();
+		$this->set_permalink_structure( '/%year%/%monthnum%/%day%/%postname%/' );
 		register_post_type( 'cpt', array(
 			'public' => true,
 		) );
@@ -58,17 +59,92 @@
 		parent::tearDown();
 	}
 
+	/**
+	 * @ticket 23049
+	 */
+	public function test_404_template_hierarchy_for_term() {
+		$url = home_url( 'taxo/not-found' );
 
-	public function test_404_template_hierarchy() {
+		$this->assertTemplateHierarchy( $url, array(
+			'404-taxonomy-taxo.php',
+			'404.php',
+		) );
+	}
+
+	/**
+	 * @ticket 23049
+	 */
+	public function test_404_template_hierarchy_for_attachment() {
 		$url = add_query_arg( array(
-			'p' => '-1',
+			'attachment_id' => '99999999',
 		), home_url() );
 
 		$this->assertTemplateHierarchy( $url, array(
+			'404-attachment.php',
 			'404.php',
 		) );
 	}
 
+	/**
+	 * @ticket 23049
+	 */
+	public function test_404_template_hierarchy_for_page() {
+		$url = home_url( 'not-found' );
+
+		$this->assertTemplateHierarchy( $url, array(
+			'404-page.php',
+			'404.php',
+		) );
+	}
+
+	/**
+	 * @ticket 23049
+	 */
+	public function test_404_template_hierarchy_for_single_post() {
+		$url = home_url( '1984/02/25/not-found' );
+
+		$this->assertTemplateHierarchy( $url, array(
+			'404-single.php',
+			'404.php',
+		) );
+	}
+
+	/**
+	 * @ticket 23049
+	 */
+	public function test_404_template_hierarchy_for_single_post_type() {
+		$url = home_url( 'cpt/not-found' );
+
+		$this->assertTemplateHierarchy( $url, array(
+			'404-single-cpt.php',
+			'404.php',
+		) );
+	}
+
+	/**
+	 * @ticket 23049
+	 */
+	public function test_404_template_hierarchy_for_category() {
+		$url = home_url( 'category/not-found' );
+
+		$this->assertTemplateHierarchy( $url, array(
+			'404-category.php',
+			'404.php',
+		) );
+	}
+
+	/**
+	 * @ticket 23049
+	 */
+	public function test_404_template_hierarchy_for_tag() {
+		$url = home_url( 'tag/not-found' );
+
+		$this->assertTemplateHierarchy( $url, array(
+			'404-tag.php',
+			'404.php',
+		) );
+	}
+
 	public function test_author_template_hierarchy() {
 		$author = self::factory()->user->create_and_get( array(
 			'user_nicename' => 'foo',
