Index: /trunk/src/wp-includes/taxonomy.php
===================================================================
--- /trunk/src/wp-includes/taxonomy.php	(revision 36613)
+++ /trunk/src/wp-includes/taxonomy.php	(revision 36614)
@@ -1073,4 +1073,17 @@
  * along with the $args array.
  *
+ * Prior to 4.5.0, the first parameter of `get_terms()` was a taxonomy or list of taxonomies:
+ *
+ *     $terms = get_terms( 'post_tag', array(
+ *         'hide_empty' => false,
+ *     ) );
+ *
+ * Since 4.5.0, taxonomies should be passed via the 'taxonomy' argument in the `$args` array:
+ *
+ *     $terms = get_terms( array(
+ *         'taxonomy' => 'post_tag',
+ *         'hide_empty' => false,
+ *     ) );
+ *
  * @since 2.3.0
  * @since 4.2.0 Introduced 'name' and 'childless' parameters.
@@ -1078,13 +1091,17 @@
  *              Introduced the 'meta_query' and 'update_term_meta_cache' parameters. Converted to return
  *              a list of WP_Term objects.
- * @since 4.5.0 Introduced 'meta_key' and 'meta_value' parameters. Introduced the ability to order results by metadata.
+ * @since 4.5.0 Changed the function signature so that the `$args` array can be provided as the first parameter.
+ *              Introduced 'meta_key' and 'meta_value' parameters. Introduced the ability to order results by metadata.
+ *
+ * @internal The `$deprecated` parameter is parsed for backward compatibility only.
  *
  * @global wpdb  $wpdb WordPress database abstraction object.
  * @global array $wp_filter
  *
- * @param string|array $taxonomies Taxonomy name or list of Taxonomy names.
  * @param array|string $args {
  *     Optional. Array or string of arguments to get terms.
  *
+ *     @type string|array $taxonomy               Taxonomy name, or array of taxonomies, to which results should
+ *                                                be limited.
  *     @type string       $orderby                Field(s) to order terms by. Accepts term fields ('name', 'slug',
  *                                                'term_group', 'term_id', 'id', 'description'), 'count' for term
@@ -1145,22 +1162,15 @@
  *                                                in conjunction with `$meta_key`.
  * }
+ * @param array $deprecated Argument array, when using the legacy function parameter format. If present, this
+ *                          parameter will be interpreted as `$args`, and the first function parameter will
+ *                          be parsed as a taxonomy or array of taxonomies.
  * @return array|int|WP_Error List of WP_Term instances and their children. Will return WP_Error, if any of $taxonomies
  *                            do not exist.
  */
-function get_terms( $taxonomies, $args = '' ) {
+function get_terms( $args = array(), $deprecated = '' ) {
 	global $wpdb;
-	$empty_array = array();
-
-	if ( ! is_array( $taxonomies ) ) {
-		$taxonomies = array( $taxonomies );
-	}
-
-	foreach ( $taxonomies as $taxonomy ) {
-		if ( ! taxonomy_exists($taxonomy) ) {
-			return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy' ) );
-		}
-	}
 
 	$defaults = array(
+		'taxonomy'               => null,
 		'orderby'                => 'name',
 		'order'                  => 'ASC',
@@ -1188,4 +1198,33 @@
 	);
 
+	/*
+	 * Legacy argument format ($taxonomy, $args) takes precedence.
+	 *
+	 * We detect legacy argument format by checking if
+	 * (a) a second non-empty parameter is passed, or
+	 * (b) the first parameter shares no keys with the default array (ie, it's a list of taxonomies)
+	 */
+	$key_intersect  = array_intersect_key( $defaults, (array) $args );
+	$do_legacy_args = $deprecated || empty( $key_intersect );
+
+	$taxonomies = null;
+	if ( $do_legacy_args ) {
+		$taxonomies = (array) $args;
+		$args = $deprecated;
+	} elseif ( isset( $args['taxonomy'] ) && null !== $args['taxonomy'] ) {
+		$taxonomies = (array) $args['taxonomy'];
+		unset( $args['taxonomy'] );
+	}
+
+	$empty_array = array();
+
+	if ( $taxonomies ) {
+		foreach ( $taxonomies as $taxonomy ) {
+			if ( ! taxonomy_exists($taxonomy) ) {
+				return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy' ) );
+			}
+		}
+	}
+
 	/**
 	 * Filter the terms query default arguments.
@@ -1205,7 +1244,9 @@
 	// Save queries by not crawling the tree in the case of multiple taxes or a flat tax.
 	$has_hierarchical_tax = false;
-	foreach ( $taxonomies as $_tax ) {
-		if ( is_taxonomy_hierarchical( $_tax ) ) {
-			$has_hierarchical_tax = true;
+	if ( $taxonomies ) {
+		foreach ( $taxonomies as $_tax ) {
+			if ( is_taxonomy_hierarchical( $_tax ) ) {
+				$has_hierarchical_tax = true;
+			}
 		}
 	}
@@ -1312,5 +1353,7 @@
 	$where_conditions = array();
 
-	$where_conditions[] = "tt.taxonomy IN ('" . implode("', '", $taxonomies) . "')";
+	if ( $taxonomies ) {
+		$where_conditions[] = "tt.taxonomy IN ('" . implode("', '", $taxonomies) . "')";
+	}
 
 	$exclude = $args['exclude'];
Index: /trunk/tests/phpunit/tests/term/getTerms.php
===================================================================
--- /trunk/tests/phpunit/tests/term/getTerms.php	(revision 36613)
+++ /trunk/tests/phpunit/tests/term/getTerms.php	(revision 36614)
@@ -10,4 +10,41 @@
 		_clean_term_filters();
 		wp_cache_delete( 'last_changed', 'terms' );
+	}
+
+	/**
+	 * @ticket 35495
+	 */
+	public function test_should_accept_an_args_array_containing_taxonomy_for_first_parameter() {
+		register_taxonomy( 'wptests_tax', 'post' );
+		$term = self::factory()->term->create( array( 'taxonomy' => 'wptests_tax' ) );
+
+		$found = get_terms( array(
+			'taxonomy' => 'wptests_tax',
+			'hide_empty' => false,
+			'fields' => 'ids',
+			'update_term_meta_cache' => false,
+		) );
+
+		$this->assertEqualSets( array( $term ), $found );
+	}
+
+	/**
+	 * @ticket 35495
+	 */
+	public function test_excluding_taxonomy_arg_should_return_terms_from_all_taxonomies() {
+		register_taxonomy( 'wptests_tax1', 'post' );
+		register_taxonomy( 'wptests_tax2', 'post' );
+		$t1 = self::factory()->term->create( array( 'taxonomy' => 'wptests_tax1' ) );
+		$t2 = self::factory()->term->create( array( 'taxonomy' => 'wptests_tax2' ) );
+
+		$found = get_terms( array(
+			'hide_empty' => false,
+			'fields' => 'ids',
+			'update_term_meta_cache' => false,
+		) );
+
+		// There may be other terms lying around, so don't do an exact match.
+		$this->assertContains( $t1, $found );
+		$this->assertContains( $t2, $found );
 	}
 
