FreeBSD/contrib/gcc/cp/call.c
/* There are three conditions of builtin candidates:

   1) bool-taking candidates.  These are the same regardless of the input.
   2) pointer-pair taking candidates.  These are generated for each type
      one of the input types converts to.
   3) arithmetic candidates.  According to the standard, we should generate
      all of these, but I'm trying not to...

   Here we generate a superset of the possible candidates for this particular
   case.  That is a subset of the full set the standard defines, plus some
   other cases which the standard disallows. add_builtin_candidate will
   filter out the invalid set.  */
There are three conditions of builtin candidates:
1) bool-taking candidates.  These are the same regardless of the input.
2) pointer-pair taking candidates.  These are generated for each type
one of the input types converts to.
3) arithmetic candidates.  According to the standard, we should generate
all of these, but I'm trying not to

Here we generate a superset of the possible candidates for this particular
case.  That is a subset of the full set the standard defines, plus some
other cases which the standard disallows. add_builtin_candidate will
filter out the invalid set.
There are three conditions of builtin candidates : 1 ) bool - taking candidates . These are the same regardless of the input . 2 ) pointer - pair taking candidates . These are generated for each type one of the input types converts to . 3 ) arithmetic candidates . According to the standard we should generate all of these but I ' m trying not to Here we generate a superset of the possible candidates for this particular case . That is a subset of the full set the standard defines plus some other cases which the standard disallows . add_builtin_candidate will filter out the invalid set .
static void
add_builtin_candidates (struct z_candidate **candidates, enum tree_code code,
			enum tree_code code2, tree fnname, tree *args,
			int flags)
{
  int ref1, i;
  int enum_p = 0;
  tree type, argtypes[3];
  tree types[2];
  for (i = 0; i < 3; ++i)
    {
      if (args[i])
	argtypes[i]  = lvalue_type (args[i]);
      else
	argtypes[i] = NULL_TREE;
    }
  switch (code)
    {
    case POSTINCREMENT_EXPR:
    case PREINCREMENT_EXPR:
    case POSTDECREMENT_EXPR:
    case PREDECREMENT_EXPR:
    case MODIFY_EXPR:
      ref1 = 1;
      break;
    case TRUTH_NOT_EXPR:
      build_builtin_candidate
	(candidates, fnname, boolean_type_node,
	 NULL_TREE, args, argtypes, flags);
      return;
    case TRUTH_ORIF_EXPR:
    case TRUTH_ANDIF_EXPR:
      build_builtin_candidate
	(candidates, fnname, boolean_type_node,
	 boolean_type_node, args, argtypes, flags);
      return;
    case ADDR_EXPR:
    case COMPOUND_EXPR:
    case COMPONENT_REF:
      return;
    case COND_EXPR:
    case EQ_EXPR:
    case NE_EXPR:
    case LT_EXPR:
    case LE_EXPR:
    case GT_EXPR:
    case GE_EXPR:
      enum_p = 1;
    default:
      ref1 = 0;
    }
  types[0] = types[1] = NULL_TREE;
  for (i = 0; i < 2; ++i)
    {
      if (! args[i])
	;
      else if (IS_AGGR_TYPE (argtypes[i]))
	{
	  tree convs;
	  if (i == 0 && code == MODIFY_EXPR && code2 == NOP_EXPR)
	    return;
	  convs = lookup_conversions (argtypes[i]);
	  if (code == COND_EXPR)
	    {
	      if (real_lvalue_p (args[i]))
		types[i] = tree_cons
		  (NULL_TREE, build_reference_type (argtypes[i]), types[i]);
	      types[i] = tree_cons
		(NULL_TREE, TYPE_MAIN_VARIANT (argtypes[i]), types[i]);
	    }
	  else if (! convs)
	    return;
	  for (; convs; convs = TREE_CHAIN (convs))
	    {
	      type = TREE_TYPE (TREE_TYPE (OVL_CURRENT (TREE_VALUE (convs))));
	      if (i == 0 && ref1
		  && (TREE_CODE (type) != REFERENCE_TYPE
		      || CP_TYPE_CONST_P (TREE_TYPE (type))))
		continue;
	      if (code == COND_EXPR && TREE_CODE (type) == REFERENCE_TYPE)
		types[i] = tree_cons (NULL_TREE, type, types[i]);
	      type = non_reference (type);
	      if (i != 0 || ! ref1)
		{
		  type = TYPE_MAIN_VARIANT (type_decays_to (type));
		  if (enum_p && TREE_CODE (type) == ENUMERAL_TYPE)
		    types[i] = tree_cons (NULL_TREE, type, types[i]);
		  if (INTEGRAL_TYPE_P (type))
		    type = type_promotes_to (type);
		}
	      if (! value_member (type, types[i]))
		types[i] = tree_cons (NULL_TREE, type, types[i]);
	    }
	}
      else
	{
	  if (code == COND_EXPR && real_lvalue_p (args[i]))
	    types[i] = tree_cons
	      (NULL_TREE, build_reference_type (argtypes[i]), types[i]);
	  type = non_reference (argtypes[i]);
	  if (i != 0 || ! ref1)
	    {
	      type = TYPE_MAIN_VARIANT (type_decays_to (type));
	      if (enum_p && TREE_CODE (type) == ENUMERAL_TYPE)
		types[i] = tree_cons (NULL_TREE, type, types[i]);
	      if (INTEGRAL_TYPE_P (type))
		type = type_promotes_to (type);
	    }
	  types[i] = tree_cons (NULL_TREE, type, types[i]);
	}
    }
  for (; types[0]; types[0] = TREE_CHAIN (types[0]))
    {
      if (types[1])
	for (type = types[1]; type; type = TREE_CHAIN (type))
	  add_builtin_candidate
	    (candidates, code, code2, fnname, TREE_VALUE (types[0]),
	     TREE_VALUE (type), args, argtypes, flags);
      else
	add_builtin_candidate
	  (candidates, code, code2, fnname, TREE_VALUE (types[0]),
	   NULL_TREE, args, argtypes, flags);
    }
}
static void add_builtin_candidates ( struct z_candidate * * candidates , enum tree_code code , enum tree_code code2 , tree fnname , tree * args , int flags ) { int ref1 , i ; int enum_p = 0 ; tree type , argtypes [ 3 ] ; tree types [ 2 ] ; for ( i = 0 ; i < 3 ; ++ i ) { if ( args [ i ] ) argtypes [ i ] = lvalue_type ( args [ i ] ) ; else argtypes [ i ] = NULL_TREE ; } switch ( code ) { case POSTINCREMENT_EXPR : case PREINCREMENT_EXPR : case POSTDECREMENT_EXPR : case PREDECREMENT_EXPR : case MODIFY_EXPR : ref1 = 1 ; break ; case TRUTH_NOT_EXPR : build_builtin_candidate ( candidates , fnname , boolean_type_node , NULL_TREE , args , argtypes , flags ) ; return ; case TRUTH_ORIF_EXPR : case TRUTH_ANDIF_EXPR : build_builtin_candidate ( candidates , fnname , boolean_type_node , boolean_type_node , args , argtypes , flags ) ; return ; case ADDR_EXPR : case COMPOUND_EXPR : case COMPONENT_REF : return ; case COND_EXPR : case EQ_EXPR : case NE_EXPR : case LT_EXPR : case LE_EXPR : case GT_EXPR : case GE_EXPR : enum_p = 1 ; default : ref1 = 0 ; } types [ 0 ] = types [ 1 ] = NULL_TREE ; for ( i = 0 ; i < 2 ; ++ i ) { if ( ! args [ i ] ) ; else if ( IS_AGGR_TYPE ( argtypes [ i ] ) ) { tree convs ; if ( i == 0 && code == MODIFY_EXPR && code2 == NOP_EXPR ) return ; convs = lookup_conversions ( argtypes [ i ] ) ; if ( code == COND_EXPR ) { if ( real_lvalue_p ( args [ i ] ) ) types [ i ] = tree_cons ( NULL_TREE , build_reference_type ( argtypes [ i ] ) , types [ i ] ) ; types [ i ] = tree_cons ( NULL_TREE , TYPE_MAIN_VARIANT ( argtypes [ i ] ) , types [ i ] ) ; } else if ( ! convs ) return ; for ( ; convs ; convs = TREE_CHAIN ( convs ) ) { type = TREE_TYPE ( TREE_TYPE ( OVL_CURRENT ( TREE_VALUE ( convs ) ) ) ) ; if ( i == 0 && ref1 && ( TREE_CODE ( type ) != REFERENCE_TYPE || CP_TYPE_CONST_P ( TREE_TYPE ( type ) ) ) ) continue ; if ( code == COND_EXPR && TREE_CODE ( type ) == REFERENCE_TYPE ) types [ i ] = tree_cons ( NULL_TREE , type , types [ i ] ) ; type = non_reference ( type ) ; if ( i != 0 || ! ref1 ) { type = TYPE_MAIN_VARIANT ( type_decays_to ( type ) ) ; if ( enum_p && TREE_CODE ( type ) == ENUMERAL_TYPE ) types [ i ] = tree_cons ( NULL_TREE , type , types [ i ] ) ; if ( INTEGRAL_TYPE_P ( type ) ) type = type_promotes_to ( type ) ; } if ( ! value_member ( type , types [ i ] ) ) types [ i ] = tree_cons ( NULL_TREE , type , types [ i ] ) ; } } else { if ( code == COND_EXPR && real_lvalue_p ( args [ i ] ) ) types [ i ] = tree_cons ( NULL_TREE , build_reference_type ( argtypes [ i ] ) , types [ i ] ) ; type = non_reference ( argtypes [ i ] ) ; if ( i != 0 || ! ref1 ) { type = TYPE_MAIN_VARIANT ( type_decays_to ( type ) ) ; if ( enum_p && TREE_CODE ( type ) == ENUMERAL_TYPE ) types [ i ] = tree_cons ( NULL_TREE , type , types [ i ] ) ; if ( INTEGRAL_TYPE_P ( type ) ) type = type_promotes_to ( type ) ; } types [ i ] = tree_cons ( NULL_TREE , type , types [ i ] ) ; } } for ( ; types [ 0 ] ; types [ 0 ] = TREE_CHAIN ( types [ 0 ] ) ) { if ( types [ 1 ] ) for ( type = types [ 1 ] ; type ; type = TREE_CHAIN ( type ) ) add_builtin_candidate ( candidates , code , code2 , fnname , TREE_VALUE ( types [ 0 ] ) , TREE_VALUE ( type ) , args , argtypes , flags ) ; else add_builtin_candidate ( candidates , code , code2 , fnname , TREE_VALUE ( types [ 0 ] ) , NULL_TREE , args , argtypes , flags ) ; } }
There are three conditions of builtin candidates:
1) bool-taking candidates.
There are three conditions of builtin candidates : 1 ) bool - taking candidates .
/* TYPES[i] is the set of possible builtin-operator parameter types
     we will consider for the Ith argument.  These are represented as
     a TREE_LIST; the TREE_VALUE of each node is the potential
     parameter type.  */ /* 4 For every pair T, VQ), where T is an arithmetic or  enumeration  type,
     and  VQ  is  either  volatile or empty, there exist candidate operator
     functions of the form
		 VQ T&   operator++(VQ T&);  */ /* 24There also exist candidate operator functions of the form
	     bool    operator!(bool);
	     bool    operator&&(bool, bool);
	     bool    operator||(bool, bool);  */ /* Fall through.  */ /* Run through the possible parameter types of both arguments,
     creating candidates with those parameter types.  */