diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 4eba2999727..3aaf24d0f32 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -1950,6 +1950,7 @@ static tree c_parser_objc_selector_arg (c_parser *);
 static tree c_parser_objc_receiver (c_parser *);
 static tree c_parser_objc_message_args (c_parser *);
 static tree c_parser_objc_keywordexpr (c_parser *);
+static tree c_parser_objc_array_literal (c_parser *);
 static void c_parser_objc_at_property_declaration (c_parser *);
 static void c_parser_objc_at_synthesize_declaration (c_parser *);
 static void c_parser_objc_at_dynamic_declaration (c_parser *);
@@ -11851,6 +11852,19 @@ c_parser_postfix_expression (c_parser *parser)
       set_c_expr_source_range (&expr, tok_range);
       c_parser_consume_token (parser);
       break;
+    case CPP_ATSIGN:
+      if (c_dialect_objc ()
+	  && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_SQUARE)
+	{
+	  c_parser_consume_token (parser);
+	  expr.value = c_parser_objc_array_literal (parser);
+	  set_c_expr_source_range (&expr, loc,
+				   c_parser_peek_token (parser)->location);
+	  break;
+	}
+      c_parser_error (parser, "expected expression");
+      expr.set_error ();
+      break;
     case CPP_NAME:
       switch (c_parser_peek_token (parser)->id_kind)
 	{
@@ -15650,6 +15664,45 @@ c_parser_objc_keywordexpr (c_parser *parser)
   return ret;
 }
 
+/* Parse an Objective-C array literal.
+
+   objc-array-literal:
+     @ [ assignment-expression-list[opt] ]
+
+   Lower '@[a, b]' to '[NSArray arrayWithObjects:a, b, nil]'.  */
+
+static tree
+c_parser_objc_array_literal (c_parser *parser)
+{
+  tree args = NULL_TREE;
+  tree elements = NULL_TREE;
+
+  gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_SQUARE));
+  c_parser_consume_token (parser);
+
+  if (c_parser_next_token_is_not (parser, CPP_CLOSE_SQUARE))
+    {
+      vec<tree, va_gc> *element_vec
+	= c_parser_expr_list (parser, true, true, NULL, NULL, NULL, NULL);
+      unsigned int ix;
+      tree element;
+
+      FOR_EACH_VEC_SAFE_ELT (element_vec, ix, element)
+	args = chainon (args, build_tree_list (NULL_TREE, element));
+      release_tree_vector (element_vec);
+    }
+
+  args = chainon (args, build_tree_list (NULL_TREE, null_pointer_node));
+  elements = TREE_CHAIN (args) ? args : TREE_VALUE (args);
+  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
+
+  return objc_build_message_expr (objc_get_class_reference
+				  (get_identifier ("NSArray")),
+				  build_tree_list
+				  (get_identifier ("arrayWithObjects"),
+				   elements));
+}
+
 /* A check, needed in several places, that ObjC interface, implementation or
    method definitions are not prefixed by incorrect items.  */
 static bool
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index b57acc6cba5..7ce50abf409 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -3033,6 +3033,8 @@ static tree cp_parser_objc_message_args
   (cp_parser *);
 static tree cp_parser_objc_message_expression
   (cp_parser *);
+static tree cp_parser_objc_array_literal
+  (cp_parser *);
 static cp_expr cp_parser_objc_encode_expression
   (cp_parser *);
 static tree cp_parser_objc_defs_expression
@@ -6825,6 +6827,12 @@ cp_parser_primary_expression (cp_parser *parser,
       cp_parser_error (parser, "expected primary-expression");
       return error_mark_node;
 
+    case CPP_ATSIGN:
+      if (c_dialect_objc ())
+	return cp_parser_objc_expression (parser);
+      cp_parser_error (parser, "expected primary-expression");
+      return error_mark_node;
+
     case CPP_KEYWORD:
       switch (token->keyword)
 	{
@@ -39290,6 +39298,7 @@ cp_parser_allow_gnu_extensions_p (cp_parser* parser)
 
    objc-expression:
      objc-message-expression
+     objc-array-literal
      objc-string-literal
      objc-encode-expression
      objc-protocol-expression
@@ -39308,6 +39317,14 @@ cp_parser_objc_expression (cp_parser* parser)
     case CPP_OPEN_SQUARE:
       return cp_parser_objc_message_expression (parser);
 
+    case CPP_ATSIGN:
+      if (cp_lexer_peek_nth_token (parser->lexer, 2)->type
+	  == CPP_OPEN_SQUARE)
+	return cp_parser_objc_array_literal (parser);
+      error_at (kwd->location, "misplaced %<@%> Objective-C++ construct");
+      cp_parser_skip_to_end_of_block_or_statement (parser);
+      return error_mark_node;
+
     case CPP_OBJC_STRING:
       kwd = cp_lexer_consume_token (parser->lexer);
       return objc_build_string_object (kwd->u.value);
@@ -39338,6 +39355,56 @@ cp_parser_objc_expression (cp_parser* parser)
   return error_mark_node;
 }
 
+/* Parse an Objective-C array literal.
+
+   objc-array-literal:
+     @ [ assignment-expression-list[opt] ]
+
+   Lower '@[a, b]' to '[NSArray arrayWithObjects:a, b, nil]'.  */
+
+static tree
+cp_parser_objc_array_literal (cp_parser *parser)
+{
+  tree sel_args = NULL_TREE;
+  tree addl_args = NULL_TREE;
+  location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@'.  */
+  cp_parser_require (parser, CPP_OPEN_SQUARE, RT_OPEN_SQUARE);
+
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_SQUARE))
+    {
+      tree element = cp_parser_assignment_expression (parser);
+      sel_args = tree_cons (get_identifier ("arrayWithObjects"), element,
+			    sel_args);
+
+      while (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+	{
+	  cp_lexer_consume_token (parser->lexer);
+	  element = cp_parser_assignment_expression (parser);
+	  addl_args = tree_cons (NULL_TREE, element, addl_args);
+	}
+    }
+
+  if (sel_args)
+    addl_args = tree_cons (NULL_TREE, null_pointer_node, addl_args);
+  else
+    sel_args = tree_cons (get_identifier ("arrayWithObjects"),
+			  null_pointer_node, sel_args);
+
+  location_t end_loc = cp_lexer_peek_token (parser->lexer)->location;
+  cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
+
+  tree result = objc_build_message_expr
+    (objc_get_class_reference (get_identifier ("NSArray")),
+     build_tree_list (nreverse (sel_args), nreverse (addl_args)));
+
+  location_t combined_loc = make_location (start_loc, start_loc, end_loc);
+  protected_set_expr_location (result, combined_loc);
+
+  return result;
+}
+
 /* Parse an Objective-C message expression.
 
    objc-message-expression:
