FreeBSD/contrib/gcc/c-common.c
/* Generic argument checking recursion routine.  PARAM is the argument to
   be checked.  PARAM_NUM is the number of the argument.  CALLBACK is invoked
   once the argument is resolved.  CTX is context for the callback.  */
Generic argument checking recursion routine.  PARAM is the argument to
be checked.  PARAM_NUM is the number of the argument.  CALLBACK is invoked
once the argument is resolved.  CTX is context for the callback.
Generic argument checking recursion routine . PARAM is the argument to be checked . PARAM_NUM is the number of the argument . CALLBACK is invoked once the argument is resolved . CTX is context for the callback .
void
check_function_arguments_recurse (void (*callback)
				  (void *, tree, unsigned HOST_WIDE_INT),
				  void *ctx, tree param,
				  unsigned HOST_WIDE_INT param_num)
{
  if ((TREE_CODE (param) == NOP_EXPR || TREE_CODE (param) == CONVERT_EXPR)
      && (TYPE_PRECISION (TREE_TYPE (param))
	  == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (param, 0)))))
    {
      check_function_arguments_recurse (callback, ctx,
					TREE_OPERAND (param, 0), param_num);
      return;
    }
  if (TREE_CODE (param) == CALL_EXPR)
    {
      tree type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (param, 0)));
      tree attrs;
      bool found_format_arg = false;
      for (attrs = TYPE_ATTRIBUTES (type);
	   attrs;
	   attrs = TREE_CHAIN (attrs))
	if (is_attribute_p ("format_arg", TREE_PURPOSE (attrs)))
	  {
	    tree inner_args;
	    tree format_num_expr;
	    int format_num;
	    int i;
	    format_num_expr = TREE_VALUE (TREE_VALUE (attrs));
	    gcc_assert (TREE_CODE (format_num_expr) == INTEGER_CST
			&& !TREE_INT_CST_HIGH (format_num_expr));
	    format_num = TREE_INT_CST_LOW (format_num_expr);
	    for (inner_args = TREE_OPERAND (param, 1), i = 1;
		 inner_args != 0;
		 inner_args = TREE_CHAIN (inner_args), i++)
	      if (i == format_num)
		{
		  check_function_arguments_recurse (callback, ctx,
						    TREE_VALUE (inner_args),
						    param_num);
		  found_format_arg = true;
		  break;
		}
	  }
      if (found_format_arg)
	return;
    }
  if (TREE_CODE (param) == COND_EXPR)
    {
      check_function_arguments_recurse (callback, ctx,
					TREE_OPERAND (param, 1), param_num);
      check_function_arguments_recurse (callback, ctx,
					TREE_OPERAND (param, 2), param_num);
      return;
    }
  (*callback) (ctx, param, param_num);
}
void check_function_arguments_recurse ( void ( * callback ) ( void * , tree , unsigned HOST_WIDE_INT ) , void * ctx , tree param , unsigned HOST_WIDE_INT param_num ) { if ( ( TREE_CODE ( param ) == NOP_EXPR || TREE_CODE ( param ) == CONVERT_EXPR ) && ( TYPE_PRECISION ( TREE_TYPE ( param ) ) == TYPE_PRECISION ( TREE_TYPE ( TREE_OPERAND ( param , 0 ) ) ) ) ) { check_function_arguments_recurse ( callback , ctx , TREE_OPERAND ( param , 0 ) , param_num ) ; return ; } if ( TREE_CODE ( param ) == CALL_EXPR ) { tree type = TREE_TYPE ( TREE_TYPE ( TREE_OPERAND ( param , 0 ) ) ) ; tree attrs ; bool found_format_arg = false ; for ( attrs = TYPE_ATTRIBUTES ( type ) ; attrs ; attrs = TREE_CHAIN ( attrs ) ) if ( is_attribute_p ( " " , TREE_PURPOSE ( attrs ) ) ) { tree inner_args ; tree format_num_expr ; int format_num ; int i ; format_num_expr = TREE_VALUE ( TREE_VALUE ( attrs ) ) ; gcc_assert ( TREE_CODE ( format_num_expr ) == INTEGER_CST && ! TREE_INT_CST_HIGH ( format_num_expr ) ) ; format_num = TREE_INT_CST_LOW ( format_num_expr ) ; for ( inner_args = TREE_OPERAND ( param , 1 ) , i = 1 ; inner_args != 0 ; inner_args = TREE_CHAIN ( inner_args ) , i ++ ) if ( i == format_num ) { check_function_arguments_recurse ( callback , ctx , TREE_VALUE ( inner_args ) , param_num ) ; found_format_arg = true ; break ; } } if ( found_format_arg ) return ; } if ( TREE_CODE ( param ) == COND_EXPR ) { check_function_arguments_recurse ( callback , ctx , TREE_OPERAND ( param , 1 ) , param_num ) ; check_function_arguments_recurse ( callback , ctx , TREE_OPERAND ( param , 2 ) , param_num ) ; return ; } ( * callback ) ( ctx , param , param_num ) ; }
Generic argument checking recursion routine.
Generic argument checking recursion routine .
/* Strip coercion.  */ /* See if this is a call to a known internationalization function
	 that modifies a format arg.  Such a function may have multiple
	 format_arg attributes (for example, ngettext).  */ /* Extract the argument number, which was previously checked
	       to be valid.  */ /* If we found a format_arg attribute and did a recursive check,
	 we are done with checking this argument.  Otherwise, we continue
	 and this will be considered a non-literal.  */ /* Check both halves of the conditional expression.  */