for the middle-end nodes like COMPLEX_EXPR, VEC_PERM_EXPR and
    others.  The name of the builtin is passed using BNAME parameter.
    Function returns true if there were no errors while parsing and
-   stores the arguments in CEXPR_LIST.  */
+   stores the arguments in CEXPR_LIST.  If it returns true,
+   *OUT_CLOSE_PAREN_LOC is written to with the location of the closing
+   parenthesis.  */
 static bool
 c_parser_get_builtin_args (c_parser *parser, const char *bname,
                           vec<c_expr_t, va_gc> **ret_cexpr_list,
-                          bool choose_expr_p)
+                          bool choose_expr_p,
+                          location_t *out_close_paren_loc)
 {
   location_t loc = c_parser_peek_token (parser)->location;
   vec<c_expr_t, va_gc> *cexpr_list;
 
   if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
     {
+      *out_close_paren_loc = c_parser_peek_token (parser)->location;
       c_parser_consume_token (parser);
       return true;
     }
       vec_safe_push (cexpr_list, expr);
     }
 
+  *out_close_paren_loc = c_parser_peek_token (parser)->location;
   if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
     return false;
 
            vec<c_expr_t, va_gc> *cexpr_list;
            c_expr_t *e1_p, *e2_p, *e3_p;
            tree c;
+           location_t close_paren_loc;
 
            c_parser_consume_token (parser);
            if (!c_parser_get_builtin_args (parser,
                                            "__builtin_choose_expr",
-                                           &cexpr_list, true))
+                                           &cexpr_list, true,
+                                           &close_paren_loc))
              {
                expr.value = error_mark_node;
                break;
                        " a constant");
            constant_expression_warning (c);
            expr = integer_zerop (c) ? *e3_p : *e2_p;
+           set_c_expr_source_range (&expr, loc, close_paren_loc);
            break;
          }
        case RID_TYPES_COMPATIBLE_P:
            vec<c_expr_t, va_gc> *cexpr_list;
            c_expr_t *e2_p;
            tree chain_value;
+           location_t close_paren_loc;
 
            c_parser_consume_token (parser);
            if (!c_parser_get_builtin_args (parser,
                                            "__builtin_call_with_static_chain",
-                                           &cexpr_list, false))
+                                           &cexpr_list, false,
+                                           &close_paren_loc))
              {
                expr.value = error_mark_node;
                break;
                        "must be a pointer type");
            else
              CALL_EXPR_STATIC_CHAIN (expr.value) = chain_value;
+           set_c_expr_source_range (&expr, loc, close_paren_loc);
            break;
          }
        case RID_BUILTIN_COMPLEX:
          {
            vec<c_expr_t, va_gc> *cexpr_list;
            c_expr_t *e1_p, *e2_p;
+           location_t close_paren_loc;
 
            c_parser_consume_token (parser);
            if (!c_parser_get_builtin_args (parser,
                                            "__builtin_complex",
-                                           &cexpr_list, false))
+                                           &cexpr_list, false,
+                                           &close_paren_loc))
              {
                expr.value = error_mark_node;
                break;
              }
            pedwarn_c90 (loc, OPT_Wpedantic,
                         "ISO C90 does not support complex types");
-           expr.value = build2 (COMPLEX_EXPR,
-                                build_complex_type
-                                  (TYPE_MAIN_VARIANT
-                                    (TREE_TYPE (e1_p->value))),
-                                e1_p->value, e2_p->value);
+           expr.value = build2_loc (loc, COMPLEX_EXPR,
+                                    build_complex_type
+                                    (TYPE_MAIN_VARIANT
+                                     (TREE_TYPE (e1_p->value))),
+                                    e1_p->value, e2_p->value);
+           set_c_expr_source_range (&expr, loc, close_paren_loc);
            break;
          }
        case RID_BUILTIN_SHUFFLE:
            vec<c_expr_t, va_gc> *cexpr_list;
            unsigned int i;
            c_expr_t *p;
+           location_t close_paren_loc;
 
            c_parser_consume_token (parser);
            if (!c_parser_get_builtin_args (parser,
                                            "__builtin_shuffle",
-                                           &cexpr_list, false))
+                                           &cexpr_list, false,
+                                           &close_paren_loc))
              {
                expr.value = error_mark_node;
                break;
                               "%<__builtin_shuffle%>");
                expr.value = error_mark_node;
              }
+           set_c_expr_source_range (&expr, loc, close_paren_loc);
            break;
          }
        case RID_AT_SELECTOR:
 
    { dg-end-multiline-output "" } */
 }
 
+void test_builtin_choose_expr (int i)
+{
+  __emit_expression_range (0,  __builtin_choose_expr (1, i, i) + i);  /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0,  __builtin_choose_expr (1, i, i) + i);
+                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0,  i + __builtin_choose_expr (1, i, i));  /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0,  i + __builtin_choose_expr (1, i, i));
+                                ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
+extern int f (int);
+void test_builtin_call_with_static_chain (int i, void *ptr)
+{
+  __emit_expression_range (0, __builtin_call_with_static_chain (f (i), ptr));  /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, __builtin_call_with_static_chain (f (i), ptr));
+                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
+void test_builtin_complex (float i, float j)
+{
+  __emit_expression_range (0,  __builtin_complex (i, j) );  /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0,  __builtin_complex (i, j) );
+                                ^~~~~~~~~~~~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
+typedef int v4si __attribute__ ((vector_size (16)));
+void test_builtin_shuffle (v4si a, v4si b, v4si mask)
+{
+  __emit_expression_range (0,  __builtin_shuffle (a, mask) );  /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0,  __builtin_shuffle (a, mask) );
+                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0,  __builtin_shuffle (a, b, mask) );  /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0,  __builtin_shuffle (a, b, mask) );
+                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
 /* Examples of non-trivial expressions.  ****************************/
 
 extern double sqrt (double x);