Index: c-parser.c
===================================================================
--- c-parser.c	(revision 179464)
+++ c-parser.c	(working copy)
@@ -297,7 +297,7 @@ c_lex_one_token (c_parser *parser, c_tok
 		/* Else they are not special keywords.
 		*/
 	      }
-	    else if (c_dialect_objc () 
+	    else if (c_dialect_objc ()
 		     && (OBJC_IS_AT_KEYWORD (rid_code)
 			 || OBJC_IS_CXX_KEYWORD (rid_code)))
 	      {
@@ -689,9 +689,9 @@ c_parser_next_token_starts_declspecs (c_
      setter/getter on the class.  c_token_starts_declspecs() can't
      differentiate between the two cases because it only checks the
      current token, so we have a special check here.  */
-  if (c_dialect_objc () 
+  if (c_dialect_objc ()
       && token->type == CPP_NAME
-      && token->id_kind == C_ID_CLASSNAME 
+      && token->id_kind == C_ID_CLASSNAME
       && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
     return false;
 
@@ -706,9 +706,9 @@ c_parser_next_tokens_start_declaration (
   c_token *token = c_parser_peek_token (parser);
 
   /* Same as above.  */
-  if (c_dialect_objc () 
+  if (c_dialect_objc ()
       && token->type == CPP_NAME
-      && token->id_kind == C_ID_CLASSNAME 
+      && token->id_kind == C_ID_CLASSNAME
       && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
     return false;
 
@@ -1516,7 +1516,7 @@ c_parser_declaration_or_fndef (c_parser
 	      return;
 	    if (specs->attrs)
 	      {
-		warning_at (c_parser_peek_token (parser)->location, 
+		warning_at (c_parser_peek_token (parser)->location,
 			    OPT_Wattributes,
 	       		    "prefix attributes are ignored for methods");
 		specs->attrs = NULL_TREE;
@@ -1551,12 +1551,12 @@ c_parser_declaration_or_fndef (c_parser
 	      return;
 	    if (specs->attrs)
 	      {
-		warning_at (c_parser_peek_token (parser)->location, 
+		warning_at (c_parser_peek_token (parser)->location,
 			OPT_Wattributes,
 			"prefix attributes are ignored for implementations");
 		specs->attrs = NULL_TREE;
 	      }
-	    c_parser_objc_class_definition (parser, NULL_TREE);	    
+	    c_parser_objc_class_definition (parser, NULL_TREE);
 	    return;
 	  }
 	  break;
@@ -1582,7 +1582,7 @@ c_parser_declaration_or_fndef (c_parser
 	  break;
 	}
     }
-  
+
   pending_xref_error ();
   prefix_attrs = specs->attrs;
   all_prefix_attrs = prefix_attrs;
@@ -1597,7 +1597,7 @@ c_parser_declaration_or_fndef (c_parser
 	 should diagnose if there were no declaration specifiers) or a
 	 function definition (in which case the diagnostic for
 	 implicit int suffices).  */
-      declarator = c_parser_declarator (parser, 
+      declarator = c_parser_declarator (parser,
 					specs->typespec_kind != ctsk_none,
 					C_DTR_NORMAL, &dummy);
       if (declarator == NULL)
@@ -1657,13 +1657,13 @@ c_parser_declaration_or_fndef (c_parser
 	      if (d)
 		finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
 			     NULL_TREE, asm_name);
-	      
+
 	      if (c_parser_next_token_is_keyword (parser, RID_IN))
 		{
 		  if (d)
 		    *objc_foreach_object_declaration = d;
 		  else
-		    *objc_foreach_object_declaration = error_mark_node;		    
+		    *objc_foreach_object_declaration = error_mark_node;
 		}
 	    }
 	  if (c_parser_next_token_is (parser, CPP_COMMA))
@@ -3084,7 +3084,7 @@ c_parser_parms_declarator (c_parser *par
       && !attrs
       && c_parser_next_token_is (parser, CPP_NAME)
       && c_parser_peek_token (parser)->id_kind == C_ID_ID
-      
+
       /* Look ahead to detect typos in type names.  */
       && c_parser_peek_2nd_token (parser)->type != CPP_NAME
       && c_parser_peek_2nd_token (parser)->type != CPP_MULT
@@ -3478,11 +3478,11 @@ c_parser_attributes (c_parser *parser)
 	  /* Parse the attribute contents.  If they start with an
 	     identifier which is followed by a comma or close
 	     parenthesis, then the arguments start with that
-	     identifier; otherwise they are an expression list.  
+	     identifier; otherwise they are an expression list.
 	     In objective-c the identifier may be a classname.  */
 	  if (c_parser_next_token_is (parser, CPP_NAME)
 	      && (c_parser_peek_token (parser)->id_kind == C_ID_ID
-		  || (c_dialect_objc () 
+		  || (c_dialect_objc ()
 		      && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
 	      && ((c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
 		  || (c_parser_peek_2nd_token (parser)->type
@@ -4771,7 +4771,7 @@ c_parser_do_statement (c_parser *parser)
 
    Here is the canonical example of the first variant:
     for (object in array)    { do something with object }
-   we call the first expression ("object") the "object_expression" and 
+   we call the first expression ("object") the "object_expression" and
    the second expression ("array") the "collection_expression".
    object_expression must be an lvalue of type "id" (a generic Objective-C
    object) because the loop works by assigning to object_expression the
@@ -4829,10 +4829,10 @@ c_parser_for_statement (c_parser *parser
 	}
       else if (c_parser_next_tokens_start_declaration (parser))
 	{
-	  c_parser_declaration_or_fndef (parser, true, true, true, true, true, 
+	  c_parser_declaration_or_fndef (parser, true, true, true, true, true,
 					 &object_expression);
 	  parser->objc_could_be_foreach_context = false;
-	  
+
 	  if (c_parser_next_token_is_keyword (parser, RID_IN))
 	    {
 	      c_parser_consume_token (parser);
@@ -4861,7 +4861,7 @@ c_parser_for_statement (c_parser *parser
 	      c_parser_declaration_or_fndef (parser, true, true, true, true,
 					     true, &object_expression);
 	      parser->objc_could_be_foreach_context = false;
-	      
+
 	      restore_extension_diagnostics (ext);
 	      if (c_parser_next_token_is_keyword (parser, RID_IN))
 		{
@@ -5345,7 +5345,7 @@ c_parser_conditional_expression (c_parse
       tree eptype = NULL_TREE;
 
       middle_loc = c_parser_peek_token (parser)->location;
-      pedwarn (middle_loc, OPT_pedantic, 
+      pedwarn (middle_loc, OPT_pedantic,
 	       "ISO C forbids omitting the middle term of a ?: expression");
       warn_for_omitted_condop (middle_loc, cond.value);
       if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
@@ -5993,16 +5993,16 @@ c_parser_alignof_expression (c_parser *p
    for the middle-end nodes like COMPLEX_EXPR, VEC_SHUFFLE_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 EXPR_LIST.  List of original types can be
-   obtained by passing non NULL value to ORIG_TYPES.  */
+   stores the arguments in CEXPR_LIST.  */
 static bool
 c_parser_get_builtin_args (c_parser *parser, const char *bname,
-			   VEC(tree,gc) **expr_list,
-			   VEC(tree,gc) **orig_types)
+			   VEC(c_expr_t,gc) **ret_cexpr_list)
 {
   location_t loc = c_parser_peek_token (parser)->location;
-  *expr_list = NULL;
+  VEC (c_expr_t,gc) *cexpr_list;
+  c_expr_t expr;
 
+  *ret_cexpr_list = NULL;
   if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
     {
       error_at (loc, "cannot take address of %qs", bname);
@@ -6016,15 +6016,21 @@ c_parser_get_builtin_args (c_parser *par
       c_parser_consume_token (parser);
       return true;
     }
-    
-  if (orig_types)
-    *expr_list = c_parser_expr_list (parser, false, false, orig_types);
-  else
-    *expr_list = c_parser_expr_list (parser, false, false, NULL);
+
+  expr = c_parser_expr_no_commas (parser, NULL);
+  cexpr_list = VEC_alloc (c_expr_t, gc, 1);
+  C_EXPR_APPEND (cexpr_list, expr);
+  while (c_parser_next_token_is (parser, CPP_COMMA))
+    {
+      c_parser_consume_token (parser);
+      expr = c_parser_expr_no_commas (parser, NULL);
+      C_EXPR_APPEND (cexpr_list, expr);
+    }
 
   if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
     return false;
 
+  *ret_cexpr_list = cexpr_list;
   return true;
 }
 
@@ -6068,7 +6074,7 @@ c_parser_get_builtin_args (c_parser *par
      __builtin_types_compatible_p ( type-name , type-name )
      __builtin_complex ( assignment-expression , assignment-expression )
      __builtin_shuffle ( assignment-expression , assignment-expression )
-     __builtin_shuffle ( assignment-expression , 
+     __builtin_shuffle ( assignment-expression ,
 			 assignment-expression ,
 			 assignment-expression, )
 
@@ -6165,7 +6171,7 @@ c_parser_postfix_expression (c_parser *p
 	      }
 	    component = c_parser_peek_token (parser)->value;
 	    c_parser_consume_token (parser);
-	    expr.value = objc_build_class_component_ref (class_name, 
+	    expr.value = objc_build_class_component_ref (class_name,
 							 component);
 	    break;
 	  }
@@ -6378,52 +6384,41 @@ c_parser_postfix_expression (c_parser *p
 	  break;
 	case RID_CHOOSE_EXPR:
 	  {
-	    VEC(tree,gc) *expr_list;
-	    VEC(tree,gc) *orig_types;
-	    tree e1value, e2value, e3value, c;
+	    VEC (c_expr_t, gc) *cexpr_list;
+	    c_expr_t *e1_p, *e2_p, *e3_p;
+	    tree c;
 
 	    c_parser_consume_token (parser);
 	    if (!c_parser_get_builtin_args (parser,
 					    "__builtin_choose_expr",
-					    &expr_list, &orig_types))
+					    &cexpr_list))
 	      {
 		expr.value = error_mark_node;
 		break;
 	      }
 
-	    if (VEC_length (tree, expr_list) != 3)
+	    if (VEC_length (c_expr_t, cexpr_list) != 3)
 	      {
 		error_at (loc, "wrong number of arguments to "
 			       "%<__builtin_choose_expr%>");
 		expr.value = error_mark_node;
 		break;
 	      }
-	    
-	    e1value = VEC_index (tree, expr_list, 0);
-	    e2value = VEC_index (tree, expr_list, 1);
-	    e3value = VEC_index (tree, expr_list, 2);
-
-	    c = e1value;
-	    mark_exp_read (e2value);
-	    mark_exp_read (e3value);
+
+	    e1_p = VEC_index (c_expr_t, cexpr_list, 0);
+	    e2_p = VEC_index (c_expr_t, cexpr_list, 1);
+	    e3_p = VEC_index (c_expr_t, cexpr_list, 2);
+
+	    c = e1_p->value;
+	    mark_exp_read (e2_p->value);
+	    mark_exp_read (e3_p->value);
 	    if (TREE_CODE (c) != INTEGER_CST
 		|| !INTEGRAL_TYPE_P (TREE_TYPE (c)))
 	      error_at (loc,
 			"first argument to %<__builtin_choose_expr%> not"
 			" a constant");
 	    constant_expression_warning (c);
-	    
-	    if (integer_zerop (c))
-	      {
-		expr.value = e3value;
-		expr.original_type = VEC_index (tree, orig_types, 2);
-	      }
-	    else
-	      {
-		expr.value = e2value;
-		expr.original_type = VEC_index (tree, orig_types, 1);
-	      }
-
+	    expr = integer_zerop (c) ? *e3_p : *e2_p;
 	    break;
 	  }
 	case RID_TYPES_COMPATIBLE_P:
@@ -6464,50 +6459,50 @@ c_parser_postfix_expression (c_parser *p
 	  }
 	  break;
 	case RID_BUILTIN_COMPLEX:
-	  { 
-	    VEC(tree,gc) *expr_list;
-	    tree e1value, e2value;
-	    
+	  {
+	    VEC(c_expr_t, gc) *cexpr_list;
+	    c_expr_t *e1_p, *e2_p;
+
 	    c_parser_consume_token (parser);
 	    if (!c_parser_get_builtin_args (parser,
 					    "__builtin_complex",
-					    &expr_list, NULL))
+					    &cexpr_list))
 	      {
 		expr.value = error_mark_node;
 		break;
 	      }
 
-	    if (VEC_length (tree, expr_list) != 2)
+	    if (VEC_length (c_expr_t, cexpr_list) != 2)
 	      {
 		error_at (loc, "wrong number of arguments to "
 			       "%<__builtin_complex%>");
 		expr.value = error_mark_node;
 		break;
 	      }
-	    
-	    e1value = VEC_index (tree, expr_list, 0);
-	    e2value = VEC_index (tree, expr_list, 1);
-
-	    mark_exp_read (e1value);
-	    if (TREE_CODE (e1value) == EXCESS_PRECISION_EXPR)
-	      e1value = convert (TREE_TYPE (e1value),
-				 TREE_OPERAND (e1value, 0));
-	    mark_exp_read (e2value);
-	    if (TREE_CODE (e2value) == EXCESS_PRECISION_EXPR)
-	      e2value = convert (TREE_TYPE (e2value),
-				 TREE_OPERAND (e2value, 0));
-	    if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1value))
-		|| DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e1value))
-		|| !SCALAR_FLOAT_TYPE_P (TREE_TYPE (e2value))
-		|| DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2value)))
+
+	    e1_p = VEC_index (c_expr_t, cexpr_list, 0);
+	    e2_p = VEC_index (c_expr_t, cexpr_list, 1);
+
+	    mark_exp_read (e1_p->value);
+	    if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR)
+	      e1_p->value = convert (TREE_TYPE (e1_p->value),
+				     TREE_OPERAND (e1_p->value, 0));
+	    mark_exp_read (e2_p->value);
+	    if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR)
+	      e2_p->value = convert (TREE_TYPE (e2_p->value),
+				     TREE_OPERAND (e2_p->value, 0));
+	    if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
+		|| DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
+		|| !SCALAR_FLOAT_TYPE_P (TREE_TYPE (e2_p->value))
+		|| DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2_p->value)))
 	      {
 		error_at (loc, "%<__builtin_complex%> operand "
 			  "not of real binary floating-point type");
 		expr.value = error_mark_node;
 		break;
 	      }
-	    if (TYPE_MAIN_VARIANT (TREE_TYPE (e1value))
-		!= TYPE_MAIN_VARIANT (TREE_TYPE (e2value)))
+	    if (TYPE_MAIN_VARIANT (TREE_TYPE (e1_p->value))
+		!= TYPE_MAIN_VARIANT (TREE_TYPE (e2_p->value)))
 	      {
 		error_at (loc,
 			  "%<__builtin_complex%> operands of different types");
@@ -6518,34 +6513,37 @@ c_parser_postfix_expression (c_parser *p
 	      pedwarn (loc, OPT_pedantic,
 		       "ISO C90 does not support complex types");
 	    expr.value = build2 (COMPLEX_EXPR,
-				 build_complex_type (TYPE_MAIN_VARIANT
-						     (TREE_TYPE (e1value))),
-				 e1value, e2value);
+				 build_complex_type
+				   (TYPE_MAIN_VARIANT
+				     (TREE_TYPE (e1_p->value))),
+				 e1_p->value, e2_p->value);
 	    break;
 	  }
 	case RID_BUILTIN_SHUFFLE:
 	  {
-	    VEC(tree,gc) *expr_list;
-	    
+	    VEC(c_expr_t,gc) *cexpr_list;
+
 	    c_parser_consume_token (parser);
 	    if (!c_parser_get_builtin_args (parser,
 					    "__builtin_shuffle",
-					    &expr_list, NULL))
+					    &cexpr_list))
 	      {
 		expr.value = error_mark_node;
 		break;
 	      }
 
-	    if (VEC_length (tree, expr_list) == 2)
-	      expr.value = c_build_vec_shuffle_expr
-				(loc, VEC_index (tree, expr_list, 0),
-				 NULL_TREE,
-				 VEC_index (tree, expr_list, 1));
-	    else if (VEC_length (tree, expr_list) == 3)
-	      expr.value = c_build_vec_shuffle_expr
-				(loc, VEC_index (tree, expr_list, 0),
-				 VEC_index (tree, expr_list, 1),
-				 VEC_index (tree, expr_list, 2));
+	    if (VEC_length (c_expr_t, cexpr_list) == 2)
+	      expr.value =
+		c_build_vec_shuffle_expr
+		  (loc, VEC_index (c_expr_t, cexpr_list, 0)->value,
+		   NULL_TREE, VEC_index (c_expr_t, cexpr_list, 1)->value);
+
+	    else if (VEC_length (c_expr_t, cexpr_list) == 3)
+	      expr.value =
+		c_build_vec_shuffle_expr
+		  (loc, VEC_index (c_expr_t, cexpr_list, 0)->value,
+		   VEC_index (c_expr_t, cexpr_list, 1)->value,
+		   VEC_index (c_expr_t, cexpr_list, 2)->value);
 	    else
 	      {
 		error_at (loc, "wrong number of arguments to "
@@ -7154,7 +7152,7 @@ c_parser_objc_class_instance_variables (
 	  /* There is a syntax error.  We want to skip the offending
 	     tokens up to the next ';' (included) or '}'
 	     (excluded).  */
-	  
+
 	  /* First, skip manually a ')' or ']'.  This is because they
 	     reduce the nesting level, so c_parser_skip_until_found()
 	     wouldn't be able to skip past them.  */
@@ -7460,32 +7458,32 @@ c_parser_objc_methodproto (c_parser *par
   /* Forget protocol qualifiers now.  */
   parser->objc_pq_context = false;
 
-  /* Do not allow the presence of attributes to hide an erroneous 
+  /* Do not allow the presence of attributes to hide an erroneous
      method implementation in the interface section.  */
   if (!c_parser_next_token_is (parser, CPP_SEMICOLON))
     {
       c_parser_error (parser, "expected %<;%>");
       return;
     }
-  
+
   if (decl != error_mark_node)
     objc_add_method_declaration (is_class_method, decl, attributes);
 
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
 }
 
-/* If we are at a position that method attributes may be present, check that 
-   there are not any parsed already (a syntax error) and then collect any 
+/* If we are at a position that method attributes may be present, check that
+   there are not any parsed already (a syntax error) and then collect any
    specified at the current location.  Finally, if new attributes were present,
    check that the next token is legal ( ';' for decls and '{' for defs).  */
-   
-static bool 
+
+static bool
 c_parser_objc_maybe_method_attributes (c_parser* parser, tree* attributes)
 {
   bool bad = false;
   if (*attributes)
     {
-      c_parser_error (parser, 
+      c_parser_error (parser,
 		    "method attributes must be specified at the end only");
       *attributes = NULL_TREE;
       bad = true;
@@ -7505,7 +7503,7 @@ c_parser_objc_maybe_method_attributes (c
     return bad;
 
   /* We've got attributes, but not at the end.  */
-  c_parser_error (parser, 
+  c_parser_error (parser,
 		  "expected %<;%> or %<{%> after method attribute definition");
   return true;
 }
@@ -7610,7 +7608,7 @@ c_parser_objc_method_decl (c_parser *par
 	    {
 	      ellipsis = true;
 	      c_parser_consume_token (parser);
-	      attr_err |= c_parser_objc_maybe_method_attributes 
+	      attr_err |= c_parser_objc_maybe_method_attributes
 						(parser, attributes) ;
 	      break;
 	    }
@@ -7740,7 +7738,7 @@ c_parser_objc_protocol_refs (c_parser *p
    where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
 
    PS: This function is identical to cp_parser_objc_try_catch_finally_statement
-   for C++.  Keep them in sync.  */   
+   for C++.  Keep them in sync.  */
 
 static void
 c_parser_objc_try_catch_finally_statement (c_parser *parser)
@@ -7798,7 +7796,7 @@ c_parser_objc_try_catch_finally_statemen
 	     going.  */
 	  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
 	    c_parser_consume_token (parser);
-	  
+
 	  /* If these is no immediate closing parenthesis, the user
 	     probably doesn't know that parenthesis are required at
 	     all (ie, they typed "@catch NSException *e").  So, just
@@ -8042,13 +8040,13 @@ c_parser_objc_keywordexpr (c_parser *par
 /* A check, needed in several places, that ObjC interface, implementation or
    method definitions are not prefixed by incorrect items.  */
 static bool
-c_parser_objc_diagnose_bad_element_prefix (c_parser *parser, 
+c_parser_objc_diagnose_bad_element_prefix (c_parser *parser,
 					   struct c_declspecs *specs)
 {
   if (!specs->declspecs_seen_p || specs->non_sc_seen_p
       || specs->typespec_kind != ctsk_none)
     {
-      c_parser_error (parser, 
+      c_parser_error (parser,
       		      "no type or storage class may be specified here,");
       c_parser_skip_to_end_of_block_or_statement (parser);
       return true;
@@ -8122,7 +8120,7 @@ c_parser_objc_at_property_declaration (c
     {
       /* Eat the '(' */
       c_parser_consume_token (parser);
-      
+
       /* Property attribute keywords are valid now.  */
       parser->objc_property_attr_context = true;
 
@@ -8203,7 +8201,7 @@ c_parser_objc_at_property_declaration (c
 
 	  if (syntax_error)
 	    break;
-	  
+
 	  if (c_parser_next_token_is (parser, CPP_COMMA))
 	    c_parser_consume_token (parser);
 	  else
@@ -8229,7 +8227,7 @@ c_parser_objc_at_property_declaration (c
       /* Comma-separated properties are chained together in
 	 reverse order; add them one by one.  */
       properties = nreverse (properties);
-      
+
       for (; properties; properties = TREE_CHAIN (properties))
 	objc_add_property_declaration (loc, copy_node (properties),
 				       property_readonly, property_readwrite,
@@ -8952,9 +8950,9 @@ c_parser_omp_clause_private (c_parser *p
 
    reduction-operator:
      One of: + * - & ^ | && ||
-     
+
    OpenMP 3.1:
-   
+
    reduction-operator:
      One of: + * - & ^ | && || max min  */
 
@@ -9602,7 +9600,7 @@ restart:
 								 rhs_expr);
 	      rhs = rhs_expr.value;
 	      rhs = c_fully_fold (rhs, false, NULL);
-	      goto stmt_done; 
+	      goto stmt_done;
 	    }
 	  /* FALLTHROUGH */
 	default:
Index: c-tree.h
===================================================================
--- c-tree.h	(revision 179464)
+++ c-tree.h	(working copy)
@@ -130,6 +130,22 @@ struct c_expr
   tree original_type;
 };
 
+/* Type alias for struct c_expr. This allows to use the structure
+   inside the VEC types.  */
+typedef struct c_expr c_expr_t;
+
+/* A varray of c_expr_t.  */
+DEF_VEC_O (c_expr_t);
+DEF_VEC_ALLOC_O (c_expr_t, gc);
+DEF_VEC_ALLOC_O (c_expr_t, heap);
+
+/* Append a new c_expr_t element to V.  */
+#define C_EXPR_APPEND(V, ELEM) \
+  do { \
+    c_expr_t *__elem_p = VEC_safe_push (c_expr_t, gc, V, NULL); \
+    *__elem_p = (ELEM); \
+  } while (0)
+
 /* A kind of type specifier.  Note that this information is currently
    only used to distinguish tag definitions, tag references and typeof
    uses.  */
