diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index f69121b..63385fc 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -453,7 +453,7 @@ c_parser_peek_2nd_token (c_parser *parser)
 /* Return a pointer to the Nth token from PARSER, reading it
    in if necessary.  The N-1th token is already read in.  */
 
-static c_token *
+c_token *
 c_parser_peek_nth_token (c_parser *parser, unsigned int n)
 {
   /* N is 1-based, not zero-based.  */
diff --git a/gcc/c/c-parser.h b/gcc/c/c-parser.h
index f36e738..04fa681 100644
--- a/gcc/c/c-parser.h
+++ b/gcc/c/c-parser.h
@@ -133,6 +133,8 @@ enum c_lookahead_kind {
 
 
 extern c_token * c_parser_peek_token (c_parser *parser);
+extern c_token * c_parser_peek_2nd_token (c_parser *parser);
+extern c_token * c_parser_peek_nth_token (c_parser *parser, unsigned int n);
 extern bool c_parser_require (c_parser *parser, enum cpp_ttype type,
 			      const char *msgid);
 extern void c_parser_error (c_parser *parser, const char *gmsgid);
@@ -140,7 +142,6 @@ extern void c_parser_consume_token (c_parser *parser);
 extern void c_parser_skip_until_found (c_parser *parser, enum cpp_ttype type,
 				       const char *msgid);
 extern bool c_parser_next_token_starts_declspecs (c_parser *parser);
-extern c_token * c_parser_peek_2nd_token (c_parser *parser);
 bool c_parser_next_tokens_start_declaration (c_parser *parser);
 bool c_token_starts_typename (c_token *token);
 
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index 931a61f..7040071 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -72,7 +72,6 @@ static void c_parser_gimple_if_stmt (c_parser *, gimple_seq *);
 static void c_parser_gimple_switch_stmt (c_parser *, gimple_seq *);
 static void c_parser_gimple_return_stmt (c_parser *, gimple_seq *);
 static void c_finish_gimple_return (location_t, tree);
-static c_expr c_parser_parse_ssa_names (c_parser *);
 static tree c_parser_gimple_paren_condition (c_parser *);
 static vec<tree, va_gc> *c_parser_gimple_expr_list (c_parser *,
 		    vec<tree, va_gc> **, vec<location_t> *);
@@ -343,7 +342,7 @@ c_parser_gimple_expression (c_parser *parser, gimple_seq *seq)
 	    c_parser_consume_token (parser);
 	  else
 	    {
-	      arg = c_parser_parse_ssa_names (parser).value;
+	      arg = c_parser_gimple_unary_expression (parser).value;
 	      vargs.safe_push (arg);
 	    }
 	}
@@ -633,69 +632,76 @@ c_parser_gimple_unary_expression (c_parser *parser)
     }
 }
 
-/* Parse gimple ssa names.  */
+/* Decompose ID into base name (ID until ver_offset) and VERSION.  Return
+   true if ID matches a SSA name.  */
 
-static c_expr
-c_parser_parse_ssa_names (c_parser *parser)
+static bool
+c_parser_parse_ssa_name_id (tree id, unsigned *version, unsigned *ver_offset)
 {
-  tree id = NULL_TREE;
-  c_expr ret;
-  char *var_name = NULL, *var_version = NULL, *token = NULL;
-  ret.original_code = ERROR_MARK;
-  ret.original_type = NULL;
+  const char *token = IDENTIFIER_POINTER (id);
+  const char *var_version = strrchr (token, '_');
+  if (! var_version)
+    return false;
 
-  /* SSA token string.  */
-  const char *ssa_token
-    = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-  token = new char [strlen (ssa_token) + 1];
-  strcpy (token, ssa_token);
+  *ver_offset = var_version - token;
+  for (const char *p = var_version + 1; *p; ++p)
+    if (! ISDIGIT (*p))
+      return false;
+  *version = atoi (var_version + 1);
+  return *version > 0;
+}
 
-  /* Separate var name and version.  */
-  var_version = strrchr (token, '_');
-  if (var_version)
-    {
-      var_name = new char[var_version - token + 1];
-      memcpy (var_name, token, var_version - token);
-      var_name[var_version - token] = '\0';
-      id = get_identifier (var_name);
+/* Get at the actual SSA name ID with VERSION starting at VER_OFFSET.
+   TYPE is the type if the SSA name is being declared.  */
 
-      /* lookup for parent decl.  */
-      if (lookup_name (id))
+static tree 
+c_parser_parse_ssa_name (c_parser *parser,
+			 tree id, tree type, unsigned version,
+			 unsigned ver_offset)
+{
+  tree name = NULL_TREE;
+  const char *token = IDENTIFIER_POINTER (id);
+
+  if (ver_offset == 0)
+    {
+      /* Anonymous unnamed SSA name.  */
+      if (version < num_ssa_names)
+	name = ssa_name (version);
+      if (! name)
 	{
-	  var_version++;
-	  unsigned int version;
-	  version = atoi (var_version);
-	  if (var_version && version)
+	  if (! type)
 	    {
-	      ret.value = NULL_TREE;
-	      if (version < num_ssa_names)
-		ret.value = ssa_name (version);
-	      if (! ret.value)
-		ret.value = make_ssa_name_fn (cfun, lookup_name (id),
-					      gimple_build_nop (), version);
-	      c_parser_consume_token (parser);
+	      c_parser_error (parser, "SSA name not declared"); 
+	      return error_mark_node;
 	    }
+	  name = make_ssa_name_fn (cfun, type, NULL, version);
 	}
     }
-
-  /* For default definition SSA names.  */
-  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+  else
     {
-      c_parser_consume_token (parser);
-      ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-      if (! strcmp ("D", ssa_token))
+      if (version < num_ssa_names)
+	name = ssa_name (version);
+      if (! name)
 	{
-	  set_ssa_default_def (cfun, lookup_name (id), ret.value);
-	  c_parser_consume_token (parser);
+	  /* Separate var name from version.  */
+	  char *var_name = XNEWVEC (char, ver_offset + 1);
+	  memcpy (var_name, token, ver_offset);
+	  var_name[ver_offset] = '\0';
+	  /* lookup for parent decl.  */
+	  id = get_identifier (var_name);
+	  tree parent = lookup_name (id);
+	  XDELETEVEC (var_name);
+	  if (! parent)
+	    {
+	      c_parser_error (parser, "base variable or SSA name not declared"); 
+	      return error_mark_node;
+	    }
+	  name = make_ssa_name_fn (cfun, parent,
+				   gimple_build_nop (), version);
 	}
-      if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
-	goto out;
     }
 
-  out:
-  free (var_name);
-  free (token);
-  return ret;
+  return name;
 }
 
 /* Parse gimple postfix expression.
@@ -756,8 +762,32 @@ c_parser_gimple_postfix_expression (c_parser *parser)
       if (c_parser_peek_token (parser)->id_kind == C_ID_ID)
 	{
 	  tree id = c_parser_peek_token (parser)->value;
-	  if (! lookup_name (id))
-	    expr = c_parser_parse_ssa_names (parser);
+	  unsigned version, ver_offset;
+	  if (! lookup_name (id)
+	      && c_parser_parse_ssa_name_id (id, &version, &ver_offset))
+	    {
+	      c_parser_consume_token (parser);
+	      expr.value = c_parser_parse_ssa_name (parser, id, NULL_TREE,
+						    version, ver_offset);
+	      /* For default definition SSA names.  */
+	      if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+		  && c_parser_peek_2nd_token (parser)->type == CPP_NAME
+		  && strcmp ("D",
+			     IDENTIFIER_POINTER
+			       (c_parser_peek_2nd_token (parser)->value)) == 0
+		  && c_parser_peek_nth_token (parser, 3)->type == CPP_CLOSE_PAREN)
+		{
+		  c_parser_consume_token (parser);
+		  c_parser_consume_token (parser);
+		  c_parser_consume_token (parser);
+		  if (! SSA_NAME_IS_DEFAULT_DEF (expr.value))
+		    {
+		      set_ssa_default_def (cfun, SSA_NAME_VAR (expr.value),
+					   expr.value);
+		      SSA_NAME_DEF_STMT (expr.value) = gimple_build_nop ();
+		    }
+		}
+	    }
 	  else
 	    {
 	      c_parser_consume_token (parser);
@@ -1125,13 +1155,30 @@ c_parser_gimple_declaration (c_parser *parser)
 
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
     {
-      tree postfix_attrs = NULL_TREE;
-      tree all_prefix_attrs = specs->attrs;
-      specs->attrs = NULL;
-      tree decl = start_decl (declarator, specs, false,
-			 chainon (postfix_attrs, all_prefix_attrs));
-      if (decl)
-	finish_decl (decl, UNKNOWN_LOCATION, NULL_TREE, NULL_TREE, NULL_TREE);
+      /* Handle SSA name decls specially, they do not go into the identifier
+         table but we simply build the SSA name for later lookup.  */
+      unsigned version, ver_offset;
+      if (declarator->kind == cdk_id
+	  && is_gimple_reg_type (specs->type)
+	  && c_parser_parse_ssa_name_id (declarator->u.id,
+					 &version, &ver_offset)
+	  /* The following restricts it to unnamed anonymous SSA names
+	     which fails parsing of named ones in dumps (we could
+	     decide to not dump their name for -gimple).  */
+	  && ver_offset == 0)
+	c_parser_parse_ssa_name (parser, declarator->u.id, specs->type,
+				 version, ver_offset);
+      else
+	{
+	  tree postfix_attrs = NULL_TREE;
+	  tree all_prefix_attrs = specs->attrs;
+	  specs->attrs = NULL;
+	  tree decl = start_decl (declarator, specs, false,
+				  chainon (postfix_attrs, all_prefix_attrs));
+	  if (decl)
+	    finish_decl (decl, UNKNOWN_LOCATION, NULL_TREE, NULL_TREE,
+			 NULL_TREE);
+	}
     }
   else
     {
diff --git a/gcc/testsuite/gcc.dg/gimplefe-17.c b/gcc/testsuite/gcc.dg/gimplefe-17.c
new file mode 100644
index 0000000..c5633ee
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-17.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple -fdump-tree-ssa" } */
+
+int 
+__GIMPLE () *
+foo ()
+{
+  int _1;
+  int j;
+  int *b;
+  _1 = 1;
+bb1:
+  if (_1)
+    goto bb3;
+  else
+    goto bb2;
+
+bb2:
+  b_2 = (int *)0;
+
+bb3:
+  b_4 = __PHI (bb1: b_3(D), bb2: b_2);
+  return b_4;
+}
+
+/* { dg-final { scan-tree-dump-not "_1_" "ssa" } } */
