Index: src/wp-includes/class-wp-comment-query.php
===================================================================
--- src/wp-includes/class-wp-comment-query.php	(revision 42373)
+++ src/wp-includes/class-wp-comment-query.php	(working copy)
@@ -248,6 +248,8 @@
 	 *                                                   Default true.
 	 *     @type bool         $update_comment_post_cache Whether to prime the cache for comment posts.
 	 *                                                   Default false.
+	 *     @type bool         $do_comment_feed_filters   Whether do comment feed filters. Default false.
+	 *     @type bool         $do_comment_feed           Whether do comment feed join. Default false.
 	 * }
 	 */
 	public function __construct( $query = '' ) {
@@ -297,6 +299,8 @@
 			'cache_domain'              => 'core',
 			'update_comment_meta_cache' => true,
 			'update_comment_post_cache' => false,
+			'do_comment_feed_filters'   => false,
+			'do_comment_feed'           => false,
 		);
 
 		if ( ! empty( $query ) ) {
@@ -385,6 +389,7 @@
 		 */
 		$_args = wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) );
 		unset( $_args['fields'] );
+		unset( $_args['do_comment_feed_filters'] );
 
 		$key          = md5( serialize( $_args ) );
 		$last_changed = wp_cache_get_last_changed( 'comment' );
@@ -473,7 +478,7 @@
 	 * @global wpdb $wpdb WordPress database abstraction object.
 	 */
 	protected function get_comment_ids() {
-		global $wpdb;
+		global $wp_query, $wpdb;
 
 		// Assemble clauses related to 'comment_approved'.
 		$approved_clauses = array();
@@ -642,6 +647,18 @@
 			}
 		}
 
+		if ( $this->query_vars['do_comment_feed_filters'] ) {
+			/**
+			 * Filters the LIMIT clause of the comments feed query before sending.
+			 *
+			 * @since 2.8.0
+			 *
+			 * @param string $climits The JOIN clause of the query.
+			 * @param WP_Query $wp_query The WP_Query global.
+			 */
+			$limits = apply_filters( 'comment_feed_limits', $limits, $wp_query );
+		}
+
 		if ( $this->query_vars['count'] ) {
 			$fields = 'COUNT(*)';
 		} else {
@@ -818,6 +835,10 @@
 		}
 
 		$join = '';
+		if ( $this->query_vars['do_comment_feed'] ) {
+			$join_posts_table                              = true;
+			$this->sql_clauses['where']['do_comment_feed'] = "( post_status = 'publish' OR ( post_status = 'inherit' AND post_type = 'attachment' ) )";
+		}
 
 		if ( $join_posts_table ) {
 			$join .= "JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID";
@@ -834,6 +855,20 @@
 			}
 		}
 
+
+
+		if ( $this->query_vars['do_comment_feed_filters'] ) {
+			/**
+			 * Filters the LIMIT clause of the comments feed query before sending.
+			 *
+			 * @since 2.8.0
+			 *
+			 * @param string $climits The JOIN clause of the query.
+			 * @param WP_Query $wp_query The WP_Query global.
+			 */
+			$join = apply_filters( 'comment_feed_join', $join, $wp_query );
+		}
+
 		if ( ! empty( $this->query_vars['date_query'] ) && is_array( $this->query_vars['date_query'] ) ) {
 			$this->date_query                         = new WP_Date_Query( $this->query_vars['date_query'], 'comment_date' );
 			$this->sql_clauses['where']['date_query'] = preg_replace( '/^\s*AND\s*/', '', $this->date_query->get_sql() );
@@ -861,14 +896,50 @@
 
 		$this->filtered_where_clause = $where;
 
+		if ( $this->query_vars['do_comment_feed_filters'] ) {
+			/**
+			 * Filters the WHERE clause of the comments feed query before sending.
+			 *
+			 * @since 2.2.0
+			 *
+			 * @param string $cwhere The WHERE clause of the query.
+			 * @param WP_Query $wp_query The WP_Query global.
+			 */
+			$where = apply_filters( 'comment_feed_where', $where, $wp_query );
+		}
+
 		if ( $where ) {
 			$where = 'WHERE ' . $where;
 		}
 
+		if ( $this->query_vars['do_comment_feed_filters'] ) {
+			/**
+			 * Filters the GROUP BY clause of the comments feed query before sending.
+			 *
+			 * @since 2.2.0
+			 *
+			 * @param string $cgroupby The GROUP BY clause of the query.
+			 * @param WP_Query $wp_query The WP_Query global.
+			 */
+			$groupby = apply_filters( 'comment_feed_groupby', $groupby, $wp_query );
+		}
+
 		if ( $groupby ) {
 			$groupby = 'GROUP BY ' . $groupby;
 		}
 
+		if ( $this->query_vars['do_comment_feed_filters'] ) {
+			/**
+			 * Filters the ORDER BY clause of the comments feed query before sending.
+			 *
+			 * @since 2.8.0
+			 *
+			 * @param string $corderby The ORDER BY clause of the query.
+			 * @param WP_Query $wp_query The WP_Query global.
+			 */
+			$orderby = apply_filters( 'comment_feed_orderby', $orderby, $wp_query );
+		}
+
 		if ( $orderby ) {
 			$orderby = "ORDER BY $orderby";
 		}
Index: src/wp-includes/class-wp-query.php
===================================================================
--- src/wp-includes/class-wp-query.php	(revision 42373)
+++ src/wp-includes/class-wp-query.php	(working copy)
@@ -2517,92 +2517,6 @@
 			$limits = 'LIMIT ' . $pgstrt . $q['posts_per_page'];
 		}
 
-		// Comments feeds
-		if ( $this->is_comment_feed && ! $this->is_singular ) {
-			if ( $this->is_archive || $this->is_search ) {
-				$cjoin    = "JOIN {$wpdb->posts} ON ({$wpdb->comments}.comment_post_ID = {$wpdb->posts}.ID) $join ";
-				$cwhere   = "WHERE comment_approved = '1' $where";
-				$cgroupby = "{$wpdb->comments}.comment_id";
-			} else { // Other non singular e.g. front
-				$cjoin    = "JOIN {$wpdb->posts} ON ( {$wpdb->comments}.comment_post_ID = {$wpdb->posts}.ID )";
-				$cwhere   = "WHERE ( post_status = 'publish' OR ( post_status = 'inherit' AND post_type = 'attachment' ) ) AND comment_approved = '1'";
-				$cgroupby = '';
-			}
-
-			if ( ! $q['suppress_filters'] ) {
-				/**
-				 * Filters the JOIN clause of the comments feed query before sending.
-				 *
-				 * @since 2.2.0
-				 *
-				 * @param string   $cjoin The JOIN clause of the query.
-				 * @param WP_Query $this The WP_Query instance (passed by reference).
-				 */
-				$cjoin = apply_filters_ref_array( 'comment_feed_join', array( $cjoin, &$this ) );
-
-				/**
-				 * Filters the WHERE clause of the comments feed query before sending.
-				 *
-				 * @since 2.2.0
-				 *
-				 * @param string   $cwhere The WHERE clause of the query.
-				 * @param WP_Query $this   The WP_Query instance (passed by reference).
-				 */
-				$cwhere = apply_filters_ref_array( 'comment_feed_where', array( $cwhere, &$this ) );
-
-				/**
-				 * Filters the GROUP BY clause of the comments feed query before sending.
-				 *
-				 * @since 2.2.0
-				 *
-				 * @param string   $cgroupby The GROUP BY clause of the query.
-				 * @param WP_Query $this     The WP_Query instance (passed by reference).
-				 */
-				$cgroupby = apply_filters_ref_array( 'comment_feed_groupby', array( $cgroupby, &$this ) );
-
-				/**
-				 * Filters the ORDER BY clause of the comments feed query before sending.
-				 *
-				 * @since 2.8.0
-				 *
-				 * @param string   $corderby The ORDER BY clause of the query.
-				 * @param WP_Query $this     The WP_Query instance (passed by reference).
-				 */
-				$corderby = apply_filters_ref_array( 'comment_feed_orderby', array( 'comment_date_gmt DESC', &$this ) );
-
-				/**
-				 * Filters the LIMIT clause of the comments feed query before sending.
-				 *
-				 * @since 2.8.0
-				 *
-				 * @param string   $climits The JOIN clause of the query.
-				 * @param WP_Query $this    The WP_Query instance (passed by reference).
-				 */
-				$climits = apply_filters_ref_array( 'comment_feed_limits', array( 'LIMIT ' . get_option( 'posts_per_rss' ), &$this ) );
-			}
-			$cgroupby = ( ! empty( $cgroupby ) ) ? 'GROUP BY ' . $cgroupby : '';
-			$corderby = ( ! empty( $corderby ) ) ? 'ORDER BY ' . $corderby : '';
-
-			$comments = (array) $wpdb->get_results( "SELECT $distinct {$wpdb->comments}.* FROM {$wpdb->comments} $cjoin $cwhere $cgroupby $corderby $climits" );
-			// Convert to WP_Comment
-			$this->comments      = array_map( 'get_comment', $comments );
-			$this->comment_count = count( $this->comments );
-
-			$post_ids = array();
-
-			foreach ( $this->comments as $comment ) {
-				$post_ids[] = (int) $comment->comment_post_ID;
-			}
-
-			$post_ids = join( ',', $post_ids );
-			$join     = '';
-			if ( $post_ids ) {
-				$where = "AND {$wpdb->posts}.ID IN ($post_ids) ";
-			} else {
-				$where = 'AND 0';
-			}
-		}
-
 		$pieces = array( 'where', 'groupby', 'join', 'orderby', 'distinct', 'fields', 'limits' );
 
 		/*
@@ -2969,28 +2883,26 @@
 			$this->posts = apply_filters_ref_array( 'posts_results', array( $this->posts, &$this ) );
 		}
 
-		if ( ! empty( $this->posts ) && $this->is_comment_feed && $this->is_singular ) {
-			/** This filter is documented in wp-includes/query.php */
-			$cjoin = apply_filters_ref_array( 'comment_feed_join', array( '', &$this ) );
+		if ( ! empty( $this->posts ) && $this->is_comment_feed ) {
+			$comment_args = array(
+				'orderby'                   => 'comment_date_gmt',
+				'order'                     => 'DESC',
+				'status'                    => 'approve',
+				'no_found_rows'             => true,
+				'number'                    => get_option( 'posts_per_rss' ),
+				'update_comment_meta_cache' => false,
+				'do_comment_feed_filters'   => ! $q['suppress_filters'],
+			);
 
-			/** This filter is documented in wp-includes/query.php */
-			$cwhere = apply_filters_ref_array( 'comment_feed_where', array( "WHERE comment_post_ID = '{$this->posts[0]->ID}' AND comment_approved = '1'", &$this ) );
+			if ( $this->is_singular ) {
+				$comment_args['post_id'] = $this->posts[0]->ID;
+			} else {
+				$comment_args['do_comment_feed'] = true;
+			}
 
-			/** This filter is documented in wp-includes/query.php */
-			$cgroupby = apply_filters_ref_array( 'comment_feed_groupby', array( '', &$this ) );
-			$cgroupby = ( ! empty( $cgroupby ) ) ? 'GROUP BY ' . $cgroupby : '';
-
-			/** This filter is documented in wp-includes/query.php */
-			$corderby = apply_filters_ref_array( 'comment_feed_orderby', array( 'comment_date_gmt DESC', &$this ) );
-			$corderby = ( ! empty( $corderby ) ) ? 'ORDER BY ' . $corderby : '';
-
-			/** This filter is documented in wp-includes/query.php */
-			$climits = apply_filters_ref_array( 'comment_feed_limits', array( 'LIMIT ' . get_option( 'posts_per_rss' ), &$this ) );
-
-			$comments_request = "SELECT {$wpdb->comments}.* FROM {$wpdb->comments} $cjoin $cwhere $cgroupby $corderby $climits";
-			$comments         = $wpdb->get_results( $comments_request );
-			// Convert to WP_Comment
-			$this->comments      = array_map( 'get_comment', $comments );
+			$comment_args        = apply_filters( 'comments_feed_query_args', $comment_args );
+			$comment_query       = new WP_Comment_Query( $comment_args );
+			$this->comments      = $comment_query->comments;
 			$this->comment_count = count( $this->comments );
 		}
 
Index: tests/phpunit/tests/feed/rss2.php
===================================================================
--- tests/phpunit/tests/feed/rss2.php	(revision 42373)
+++ tests/phpunit/tests/feed/rss2.php	(working copy)
@@ -368,7 +368,7 @@
 		$this->assertTrue( have_comments() );
 
 		// Check to see if we have the expected XML output from the feed template.
-		$feed = $this->do_rss2();
+		$feed = $this->do_rss2( 'comments' );
 
 		$xml = xml_to_array( $feed );
 
@@ -377,6 +377,11 @@
 
 		// There should only be one <rss> child element.
 		$this->assertEquals( 1, count( $rss ) );
+
+		// Comment limits obey 'posts_per_rss' count.
+		$comments = xml_find( $xml, 'rss', 'channel', 'item' );
+		$posts_per_rss = (int) get_option( 'posts_per_rss' );
+		$this->assertCount( $posts_per_rss, $comments );
 	}
 
 	/*
@@ -414,6 +419,11 @@
 	 * @ticket 30210
 	 */
 	function test_valid_single_post_comment_feed_endpoint() {
+		$comment_ids = self::factory()->comment->create_many( 3, array(
+			'comment_post_ID' => self::$posts[0],
+			'comment_approved' => '1',
+		) );
+
 		// An example of an valid date archive feed endpoint.
 		$this->go_to( get_post_comments_feed_link( self::$posts[0] ) );
 
@@ -424,7 +434,7 @@
 		$this->assertTrue( have_posts() );
 
 		// Check to see if we have the expected XML output from the feed template.
-		$feed = $this->do_rss2();
+		$feed = $this->do_rss2( 'comments' );
 
 		$xml = xml_to_array( $feed );
 
@@ -433,6 +443,10 @@
 
 		// There should only be one <rss> child element.
 		$this->assertEquals( 1, count( $rss ) );
+
+		// There should be three comments.
+		$comments = xml_find( $xml, 'rss', 'channel', 'item' );
+		$this->assertCount( 3, $comments );
 	}
 
 	/*
