Exemple #1
0
enum omp_clause_default_kind
cxx_omp_predetermined_sharing (tree decl)
{
  tree type;

  /* Static data members are predetermined as shared.  */
  if (TREE_STATIC (decl))
    {
      tree ctx = CP_DECL_CONTEXT (decl);
      if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
	return OMP_CLAUSE_DEFAULT_SHARED;
    }

  type = TREE_TYPE (decl);
  if (TREE_CODE (type) == REFERENCE_TYPE)
    {
      if (!is_invisiref_parm (decl))
	return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
      type = TREE_TYPE (type);

      if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl))
	{
	  /* NVR doesn't preserve const qualification of the
	     variable's type.  */
	  tree outer = outer_curly_brace_block (current_function_decl);
	  tree var;

	  if (outer)
	    for (var = BLOCK_VARS (outer); var; var = TREE_CHAIN (var))
	      if (DECL_NAME (decl) == DECL_NAME (var)
		  && (TYPE_MAIN_VARIANT (type)
		      == TYPE_MAIN_VARIANT (TREE_TYPE (var))))
		{
		  if (TYPE_READONLY (TREE_TYPE (var)))
		    type = TREE_TYPE (var);
		  break;
		}
	}
    }

  if (type == error_mark_node)
    return OMP_CLAUSE_DEFAULT_UNSPECIFIED;

  /* Variables with const-qualified type having no mutable member
     are predetermined shared.  */
  if (TYPE_READONLY (type) && !cp_has_mutable_p (type))
    return OMP_CLAUSE_DEFAULT_SHARED;

  return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
}
Exemple #2
0
static void
unpack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
{
  machine_mode mode;

  mode = bp_unpack_machine_mode (bp);
  SET_TYPE_MODE (expr, mode);
  TYPE_STRING_FLAG (expr) = (unsigned) bp_unpack_value (bp, 1);
  /* TYPE_NO_FORCE_BLK is private to stor-layout and need
     no streaming.  */
  TYPE_NEEDS_CONSTRUCTING (expr) = (unsigned) bp_unpack_value (bp, 1);
  TYPE_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1);
  TYPE_RESTRICT (expr) = (unsigned) bp_unpack_value (bp, 1);
  TYPE_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1);
  TYPE_READONLY (expr) = (unsigned) bp_unpack_value (bp, 1);
  if (RECORD_OR_UNION_TYPE_P (expr))
    {
      TYPE_TRANSPARENT_AGGR (expr) = (unsigned) bp_unpack_value (bp, 1);
      TYPE_FINAL_P (expr) = (unsigned) bp_unpack_value (bp, 1);
    }
  else if (TREE_CODE (expr) == ARRAY_TYPE)
    TYPE_NONALIASED_COMPONENT (expr) = (unsigned) bp_unpack_value (bp, 1);
  TYPE_PRECISION (expr) = bp_unpack_var_len_unsigned (bp);
  TYPE_ALIGN (expr) = bp_unpack_var_len_unsigned (bp);
#ifdef ACCEL_COMPILER
  if (TYPE_ALIGN (expr) > targetm.absolute_biggest_alignment)
    TYPE_ALIGN (expr) = targetm.absolute_biggest_alignment;
#endif
}
Exemple #3
0
static void
pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
{
  /* for VECTOR_TYPE, TYPE_MODE reevaluates the mode using target_flags
     not necessary valid in a global context.
     Use the raw value previously set by layout_type.  */
  bp_pack_machine_mode (bp, TYPE_MODE_RAW (expr));
  bp_pack_value (bp, TYPE_STRING_FLAG (expr), 1);
  /* TYPE_NO_FORCE_BLK is private to stor-layout and need
     no streaming.  */
  bp_pack_value (bp, TYPE_NEEDS_CONSTRUCTING (expr), 1);
  bp_pack_value (bp, TYPE_PACKED (expr), 1);
  bp_pack_value (bp, TYPE_RESTRICT (expr), 1);
  bp_pack_value (bp, TYPE_USER_ALIGN (expr), 1);
  bp_pack_value (bp, TYPE_READONLY (expr), 1);
  /* We used to stream TYPE_ALIAS_SET == 0 information to let frontends mark
     types that are opaque for TBAA.  This however did not work as intended,
     becuase TYPE_ALIAS_SET == 0 was regularly lost in type merging.  */
  if (RECORD_OR_UNION_TYPE_P (expr))
    {
      bp_pack_value (bp, TYPE_TRANSPARENT_AGGR (expr), 1);
      bp_pack_value (bp, TYPE_FINAL_P (expr), 1);
    }
  else if (TREE_CODE (expr) == ARRAY_TYPE)
    bp_pack_value (bp, TYPE_NONALIASED_COMPONENT (expr), 1);
  bp_pack_var_len_unsigned (bp, TYPE_PRECISION (expr));
  bp_pack_var_len_unsigned (bp, TYPE_ALIGN (expr));
}
Exemple #4
0
static void
pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
{
  bp_pack_enum (bp, machine_mode, MAX_MACHINE_MODE, TYPE_MODE (expr));
  bp_pack_value (bp, TYPE_STRING_FLAG (expr), 1);
  bp_pack_value (bp, TYPE_NO_FORCE_BLK (expr), 1);
  bp_pack_value (bp, TYPE_NEEDS_CONSTRUCTING (expr), 1);
  if (RECORD_OR_UNION_TYPE_P (expr))
    {
      bp_pack_value (bp, TYPE_TRANSPARENT_AGGR (expr), 1);
      bp_pack_value (bp, TYPE_FINAL_P (expr), 1);
    }
  else if (TREE_CODE (expr) == ARRAY_TYPE)
    bp_pack_value (bp, TYPE_NONALIASED_COMPONENT (expr), 1);
  bp_pack_value (bp, TYPE_PACKED (expr), 1);
  bp_pack_value (bp, TYPE_RESTRICT (expr), 1);
  bp_pack_value (bp, TYPE_USER_ALIGN (expr), 1);
  bp_pack_value (bp, TYPE_READONLY (expr), 1);
  bp_pack_var_len_unsigned (bp, TYPE_PRECISION (expr));
  bp_pack_var_len_unsigned (bp, TYPE_ALIGN (expr));
  /* Make sure to preserve the fact whether the frontend would assign
     alias-set zero to this type.  */
  bp_pack_var_len_int (bp, (TYPE_ALIAS_SET (expr) == 0
			    || (!in_lto_p
				&& get_alias_set (expr) == 0)) ? 0 : -1);
}
Exemple #5
0
static void
unpack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
{
  machine_mode mode;

  mode = bp_unpack_enum (bp, machine_mode, MAX_MACHINE_MODE);
  SET_TYPE_MODE (expr, mode);
  TYPE_STRING_FLAG (expr) = (unsigned) bp_unpack_value (bp, 1);
  TYPE_NO_FORCE_BLK (expr) = (unsigned) bp_unpack_value (bp, 1);
  TYPE_NEEDS_CONSTRUCTING (expr) = (unsigned) bp_unpack_value (bp, 1);
  if (RECORD_OR_UNION_TYPE_P (expr))
    {
      TYPE_TRANSPARENT_AGGR (expr) = (unsigned) bp_unpack_value (bp, 1);
      TYPE_FINAL_P (expr) = (unsigned) bp_unpack_value (bp, 1);
    }
  else if (TREE_CODE (expr) == ARRAY_TYPE)
    TYPE_NONALIASED_COMPONENT (expr) = (unsigned) bp_unpack_value (bp, 1);
  TYPE_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1);
  TYPE_RESTRICT (expr) = (unsigned) bp_unpack_value (bp, 1);
  TYPE_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1);
  TYPE_READONLY (expr) = (unsigned) bp_unpack_value (bp, 1);
  TYPE_PRECISION (expr) = bp_unpack_var_len_unsigned (bp);
  TYPE_ALIGN (expr) = bp_unpack_var_len_unsigned (bp);
  TYPE_ALIAS_SET (expr) = bp_unpack_var_len_int (bp);
}
Exemple #6
0
/* Return true if DECL is const qualified var having no mutable member.  */
bool
cxx_omp_const_qual_no_mutable (tree decl)
{
  tree type = TREE_TYPE (decl);
  if (TREE_CODE (type) == REFERENCE_TYPE)
    {
      if (!is_invisiref_parm (decl))
	return false;
      type = TREE_TYPE (type);

      if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl))
	{
	  /* NVR doesn't preserve const qualification of the
	     variable's type.  */
	  tree outer = outer_curly_brace_block (current_function_decl);
	  tree var;

	  if (outer)
	    for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
	      if (DECL_NAME (decl) == DECL_NAME (var)
		  && (TYPE_MAIN_VARIANT (type)
		      == TYPE_MAIN_VARIANT (TREE_TYPE (var))))
		{
		  if (TYPE_READONLY (TREE_TYPE (var)))
		    type = TREE_TYPE (var);
		  break;
		}
	}
    }

  if (type == error_mark_node)
    return false;

  /* Variables with const-qualified type having no mutable member
     are predetermined shared.  */
  if (TYPE_READONLY (type) && !cp_has_mutable_p (type))
    return true;

  return false;
}
Exemple #7
0
static void
pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
{
  bp_pack_enum (bp, machine_mode, MAX_MACHINE_MODE, TYPE_MODE (expr));
  bp_pack_value (bp, TYPE_STRING_FLAG (expr), 1);
  bp_pack_value (bp, TYPE_NO_FORCE_BLK (expr), 1);
  bp_pack_value (bp, TYPE_NEEDS_CONSTRUCTING (expr), 1);
  if (RECORD_OR_UNION_TYPE_P (expr))
    bp_pack_value (bp, TYPE_TRANSPARENT_AGGR (expr), 1);
  bp_pack_value (bp, TYPE_PACKED (expr), 1);
  bp_pack_value (bp, TYPE_RESTRICT (expr), 1);
  bp_pack_value (bp, TYPE_CONTAINS_PLACEHOLDER_INTERNAL (expr), 2);
  bp_pack_value (bp, TYPE_USER_ALIGN (expr), 1);
  bp_pack_value (bp, TYPE_READONLY (expr), 1);
  bp_pack_var_len_unsigned (bp, TYPE_PRECISION (expr));
  bp_pack_var_len_unsigned (bp, TYPE_ALIGN (expr));
  bp_pack_var_len_int (bp, TYPE_ALIAS_SET (expr) == 0 ? 0 : -1);
}
Exemple #8
0
void
readonly_error (tree arg, const char* string, int soft)
{
  const char *fmt;
  void (*fn) (const char *, ...) ATTRIBUTE_GCC_CXXDIAG(1,2);

  if (soft)
    fn = pedwarn;
  else
    fn = error;

  if (TREE_CODE (arg) == COMPONENT_REF)
    {
      if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
	fmt = "%s of data-member %qD in read-only structure";
      else
	fmt = "%s of read-only data-member %qD";
      (*fn) (fmt, string, TREE_OPERAND (arg, 1));
    }
  else if (TREE_CODE (arg) == VAR_DECL)
    {
      if (DECL_LANG_SPECIFIC (arg)
	  && DECL_IN_AGGR_P (arg)
	  && !TREE_STATIC (arg))
	fmt = "%s of constant field %qD";
      else
	fmt = "%s of read-only variable %qD";
      (*fn) (fmt, string, arg);
    }
  else if (TREE_CODE (arg) == PARM_DECL)
    (*fn) ("%s of read-only parameter %qD", string, arg);
  else if (TREE_CODE (arg) == INDIRECT_REF
	   && TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))) == REFERENCE_TYPE
	   && (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL
	       || TREE_CODE (TREE_OPERAND (arg, 0)) == PARM_DECL))
    (*fn) ("%s of read-only reference %qD", string, TREE_OPERAND (arg, 0));
  else if (TREE_CODE (arg) == RESULT_DECL)
    (*fn) ("%s of read-only named return value %qD", string, arg);
  else if (TREE_CODE (arg) == FUNCTION_DECL)
    (*fn) ("%s of function %qD", string, arg);
  else
    (*fn) ("%s of read-only location", string);
}
Exemple #9
0
static tree
handle_noreturn_attribute (tree *node, tree ARG_UNUSED (name),
			   tree ARG_UNUSED (args), int ARG_UNUSED (flags),
			   bool * ARG_UNUSED (no_add_attrs))
{
  tree type = TREE_TYPE (*node);

  if (TREE_CODE (*node) == FUNCTION_DECL)
    TREE_THIS_VOLATILE (*node) = 1;
  else if (TREE_CODE (type) == POINTER_TYPE
	   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
    TREE_TYPE (*node)
      = build_pointer_type
	(build_type_variant (TREE_TYPE (type),
			     TYPE_READONLY (TREE_TYPE (type)), 1));
  else
    gcc_unreachable ();

  return NULL_TREE;
}
Exemple #10
0
void
readonly_error (tree arg, const char* string)
{
  const char *fmt;

  if (TREE_CODE (arg) == COMPONENT_REF)
    {
      if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
	fmt = "%s of data-member %qD in read-only structure";
      else
	fmt = "%s of read-only data-member %qD";
      error (fmt, string, TREE_OPERAND (arg, 1));
    }
  else if (TREE_CODE (arg) == VAR_DECL)
    {
      if (DECL_LANG_SPECIFIC (arg)
	  && DECL_IN_AGGR_P (arg)
	  && !TREE_STATIC (arg))
	fmt = "%s of constant field %qD";
      else
	fmt = "%s of read-only variable %qD";
      error (fmt, string, arg);
    }
  else if (TREE_CODE (arg) == PARM_DECL)
    error ("%s of read-only parameter %qD", string, arg);
  else if (TREE_CODE (arg) == INDIRECT_REF
	   && TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))) == REFERENCE_TYPE
	   && (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL
	       || TREE_CODE (TREE_OPERAND (arg, 0)) == PARM_DECL))
    error ("%s of read-only reference %qD", string, TREE_OPERAND (arg, 0));
  else if (TREE_CODE (arg) == RESULT_DECL)
    error ("%s of read-only named return value %qD", string, arg);
  else if (TREE_CODE (arg) == FUNCTION_DECL)
    error ("%s of function %qD", string, arg);
  else
    error ("%s of read-only location %qE", string, arg);
}
Exemple #11
0
void
print_node (FILE *file, const char *prefix, tree node, int indent)
{
    int hash;
    struct bucket *b;
    machine_mode mode;
    enum tree_code_class tclass;
    int len;
    int i;
    expanded_location xloc;
    enum tree_code code;

    if (node == 0)
        return;

    code = TREE_CODE (node);
    tclass = TREE_CODE_CLASS (code);

    /* Don't get too deep in nesting.  If the user wants to see deeper,
       it is easy to use the address of a lowest-level node
       as an argument in another call to debug_tree.  */

    if (indent > 24)
    {
        print_node_brief (file, prefix, node, indent);
        return;
    }

    if (indent > 8 && (tclass == tcc_type || tclass == tcc_declaration))
    {
        print_node_brief (file, prefix, node, indent);
        return;
    }

    /* It is unsafe to look at any other fields of an ERROR_MARK node.  */
    if (code == ERROR_MARK)
    {
        print_node_brief (file, prefix, node, indent);
        return;
    }

    /* Allow this function to be called if the table is not there.  */
    if (table)
    {
        hash = ((uintptr_t) node) % HASH_SIZE;

        /* If node is in the table, just mention its address.  */
        for (b = table[hash]; b; b = b->next)
            if (b->node == node)
            {
                print_node_brief (file, prefix, node, indent);
                return;
            }

        /* Add this node to the table.  */
        b = XNEW (struct bucket);
        b->node = node;
        b->next = table[hash];
        table[hash] = b;
    }

    /* Indent to the specified column, since this is the long form.  */
    indent_to (file, indent);

    /* Print the slot this node is in, and its code, and address.  */
    fprintf (file, "%s <%s", prefix, get_tree_code_name (code));
    dump_addr (file, " ", node);

    /* Print the name, if any.  */
    if (tclass == tcc_declaration)
    {
        if (DECL_NAME (node))
            fprintf (file, " %s", IDENTIFIER_POINTER (DECL_NAME (node)));
        else if (code == LABEL_DECL
                 && LABEL_DECL_UID (node) != -1)
        {
            if (dump_flags & TDF_NOUID)
                fprintf (file, " L.xxxx");
            else
                fprintf (file, " L.%d", (int) LABEL_DECL_UID (node));
        }
        else
        {
            if (dump_flags & TDF_NOUID)
                fprintf (file, " %c.xxxx", code == CONST_DECL ? 'C' : 'D');
            else
                fprintf (file, " %c.%u", code == CONST_DECL ? 'C' : 'D',
                         DECL_UID (node));
        }
    }
    else if (tclass == tcc_type)
    {
        if (TYPE_NAME (node))
        {
            if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
                fprintf (file, " %s", IDENTIFIER_POINTER (TYPE_NAME (node)));
            else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
                     && DECL_NAME (TYPE_NAME (node)))
                fprintf (file, " %s",
                         IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node))));
        }
    }
    if (code == IDENTIFIER_NODE)
        fprintf (file, " %s", IDENTIFIER_POINTER (node));

    if (code == INTEGER_CST)
    {
        if (indent <= 4)
            print_node_brief (file, "type", TREE_TYPE (node), indent + 4);
    }
    else if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
    {
        print_node (file, "type", TREE_TYPE (node), indent + 4);
        if (TREE_TYPE (node))
            indent_to (file, indent + 3);
    }

    if (!TYPE_P (node) && TREE_SIDE_EFFECTS (node))
        fputs (" side-effects", file);

    if (TYPE_P (node) ? TYPE_READONLY (node) : TREE_READONLY (node))
        fputs (" readonly", file);
    if (TYPE_P (node) && TYPE_ATOMIC (node))
        fputs (" atomic", file);
    if (!TYPE_P (node) && TREE_CONSTANT (node))
        fputs (" constant", file);
    else if (TYPE_P (node) && TYPE_SIZES_GIMPLIFIED (node))
        fputs (" sizes-gimplified", file);

    if (TYPE_P (node) && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (node)))
        fprintf (file, " address-space-%d", TYPE_ADDR_SPACE (node));

    if (TREE_ADDRESSABLE (node))
        fputs (" addressable", file);
    if (TREE_THIS_VOLATILE (node))
        fputs (" volatile", file);
    if (TREE_ASM_WRITTEN (node))
        fputs (" asm_written", file);
    if (TREE_USED (node))
        fputs (" used", file);
    if (TREE_NOTHROW (node))
        fputs (" nothrow", file);
    if (TREE_PUBLIC (node))
        fputs (" public", file);
    if (TREE_PRIVATE (node))
        fputs (" private", file);
    if (TREE_PROTECTED (node))
        fputs (" protected", file);
    if (TREE_STATIC (node))
        fputs (code == CALL_EXPR ? " must-tail-call" : " static", file);
    if (TREE_DEPRECATED (node))
        fputs (" deprecated", file);
    if (TREE_VISITED (node))
        fputs (" visited", file);

    if (code != TREE_VEC && code != INTEGER_CST && code != SSA_NAME)
    {
        if (TREE_LANG_FLAG_0 (node))
            fputs (" tree_0", file);
        if (TREE_LANG_FLAG_1 (node))
            fputs (" tree_1", file);
        if (TREE_LANG_FLAG_2 (node))
            fputs (" tree_2", file);
        if (TREE_LANG_FLAG_3 (node))
            fputs (" tree_3", file);
        if (TREE_LANG_FLAG_4 (node))
            fputs (" tree_4", file);
        if (TREE_LANG_FLAG_5 (node))
            fputs (" tree_5", file);
        if (TREE_LANG_FLAG_6 (node))
            fputs (" tree_6", file);
    }

    /* DECL_ nodes have additional attributes.  */

    switch (TREE_CODE_CLASS (code))
    {
    case tcc_declaration:
        if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
        {
            if (DECL_UNSIGNED (node))
                fputs (" unsigned", file);
            if (DECL_IGNORED_P (node))
                fputs (" ignored", file);
            if (DECL_ABSTRACT_P (node))
                fputs (" abstract", file);
            if (DECL_EXTERNAL (node))
                fputs (" external", file);
            if (DECL_NONLOCAL (node))
                fputs (" nonlocal", file);
        }
        if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
        {
            if (DECL_WEAK (node))
                fputs (" weak", file);
            if (DECL_IN_SYSTEM_HEADER (node))
                fputs (" in_system_header", file);
        }
        if (CODE_CONTAINS_STRUCT (code, TS_DECL_WRTL)
                && code != LABEL_DECL
                && code != FUNCTION_DECL
                && DECL_REGISTER (node))
            fputs (" regdecl", file);

        if (code == TYPE_DECL && TYPE_DECL_SUPPRESS_DEBUG (node))
            fputs (" suppress-debug", file);

        if (code == FUNCTION_DECL
                && DECL_FUNCTION_SPECIFIC_TARGET (node))
            fputs (" function-specific-target", file);
        if (code == FUNCTION_DECL
                && DECL_FUNCTION_SPECIFIC_OPTIMIZATION (node))
            fputs (" function-specific-opt", file);
        if (code == FUNCTION_DECL && DECL_DECLARED_INLINE_P (node))
            fputs (" autoinline", file);
        if (code == FUNCTION_DECL && DECL_BUILT_IN (node))
            fputs (" built-in", file);
        if (code == FUNCTION_DECL && DECL_STATIC_CHAIN (node))
            fputs (" static-chain", file);
        if (TREE_CODE (node) == FUNCTION_DECL && decl_is_tm_clone (node))
            fputs (" tm-clone", file);

        if (code == FIELD_DECL && DECL_PACKED (node))
            fputs (" packed", file);
        if (code == FIELD_DECL && DECL_BIT_FIELD (node))
            fputs (" bit-field", file);
        if (code == FIELD_DECL && DECL_NONADDRESSABLE_P (node))
            fputs (" nonaddressable", file);

        if (code == LABEL_DECL && EH_LANDING_PAD_NR (node))
            fprintf (file, " landing-pad:%d", EH_LANDING_PAD_NR (node));

        if (code == VAR_DECL && DECL_IN_TEXT_SECTION (node))
            fputs (" in-text-section", file);
        if (code == VAR_DECL && DECL_IN_CONSTANT_POOL (node))
            fputs (" in-constant-pool", file);
        if (code == VAR_DECL && DECL_COMMON (node))
            fputs (" common", file);
        if (code == VAR_DECL && DECL_THREAD_LOCAL_P (node))
        {
            fputs (" ", file);
            fputs (tls_model_names[DECL_TLS_MODEL (node)], file);
        }

        if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
        {
            if (DECL_VIRTUAL_P (node))
                fputs (" virtual", file);
            if (DECL_PRESERVE_P (node))
                fputs (" preserve", file);
            if (DECL_LANG_FLAG_0 (node))
                fputs (" decl_0", file);
            if (DECL_LANG_FLAG_1 (node))
                fputs (" decl_1", file);
            if (DECL_LANG_FLAG_2 (node))
                fputs (" decl_2", file);
            if (DECL_LANG_FLAG_3 (node))
                fputs (" decl_3", file);
            if (DECL_LANG_FLAG_4 (node))
                fputs (" decl_4", file);
            if (DECL_LANG_FLAG_5 (node))
                fputs (" decl_5", file);
            if (DECL_LANG_FLAG_6 (node))
                fputs (" decl_6", file);
            if (DECL_LANG_FLAG_7 (node))
                fputs (" decl_7", file);

            mode = DECL_MODE (node);
            fprintf (file, " %s", GET_MODE_NAME (mode));
        }

        if ((code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL)
                && DECL_BY_REFERENCE (node))
            fputs (" passed-by-reference", file);

        if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)  && DECL_DEFER_OUTPUT (node))
            fputs (" defer-output", file);


        xloc = expand_location (DECL_SOURCE_LOCATION (node));
        fprintf (file, " file %s line %d col %d", xloc.file, xloc.line,
                 xloc.column);

        if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
        {
            print_node (file, "size", DECL_SIZE (node), indent + 4);
            print_node (file, "unit size", DECL_SIZE_UNIT (node), indent + 4);

            if (code != FUNCTION_DECL || DECL_BUILT_IN (node))
                indent_to (file, indent + 3);

            if (DECL_USER_ALIGN (node))
                fprintf (file, " user");

            fprintf (file, " align %d", DECL_ALIGN (node));
            if (code == FIELD_DECL)
                fprintf (file, " offset_align " HOST_WIDE_INT_PRINT_UNSIGNED,
                         DECL_OFFSET_ALIGN (node));

            if (code == FUNCTION_DECL && DECL_BUILT_IN (node))
            {
                if (DECL_BUILT_IN_CLASS (node) == BUILT_IN_MD)
                    fprintf (file, " built-in BUILT_IN_MD %d", DECL_FUNCTION_CODE (node));
                else
                    fprintf (file, " built-in %s:%s",
                             built_in_class_names[(int) DECL_BUILT_IN_CLASS (node)],
                             built_in_names[(int) DECL_FUNCTION_CODE (node)]);
            }
        }
        if (code == FIELD_DECL)
        {
            print_node (file, "offset", DECL_FIELD_OFFSET (node), indent + 4);
            print_node (file, "bit offset", DECL_FIELD_BIT_OFFSET (node),
                        indent + 4);
            if (DECL_BIT_FIELD_TYPE (node))
                print_node (file, "bit_field_type", DECL_BIT_FIELD_TYPE (node),
                            indent + 4);
        }

        print_node_brief (file, "context", DECL_CONTEXT (node), indent + 4);

        if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
        {
            print_node_brief (file, "attributes",
                              DECL_ATTRIBUTES (node), indent + 4);
            if (code != PARM_DECL)
                print_node_brief (file, "initial", DECL_INITIAL (node),
                                  indent + 4);
        }
        if (CODE_CONTAINS_STRUCT (code, TS_DECL_WRTL))
        {
            print_node_brief (file, "abstract_origin",
                              DECL_ABSTRACT_ORIGIN (node), indent + 4);
        }
        if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
        {
            print_node (file, "result", DECL_RESULT_FLD (node), indent + 4);
        }

        lang_hooks.print_decl (file, node, indent);

        if (DECL_RTL_SET_P (node))
        {
            indent_to (file, indent + 4);
            print_rtl (file, DECL_RTL (node));
        }

        if (code == PARM_DECL)
        {
            print_node (file, "arg-type", DECL_ARG_TYPE (node), indent + 4);

            if (DECL_INCOMING_RTL (node) != 0)
            {
                indent_to (file, indent + 4);
                fprintf (file, "incoming-rtl ");
                print_rtl (file, DECL_INCOMING_RTL (node));
            }
        }
        else if (code == FUNCTION_DECL
                 && DECL_STRUCT_FUNCTION (node) != 0)
        {
            print_node (file, "arguments", DECL_ARGUMENTS (node), indent + 4);
            indent_to (file, indent + 4);
            dump_addr (file, "struct-function ", DECL_STRUCT_FUNCTION (node));
        }

        if ((code == VAR_DECL || code == PARM_DECL)
                && DECL_HAS_VALUE_EXPR_P (node))
            print_node (file, "value-expr", DECL_VALUE_EXPR (node), indent + 4);

        /* Print the decl chain only if decl is at second level.  */
        if (indent == 4)
            print_node (file, "chain", TREE_CHAIN (node), indent + 4);
        else
            print_node_brief (file, "chain", TREE_CHAIN (node), indent + 4);
        break;

    case tcc_type:
        if (TYPE_UNSIGNED (node))
            fputs (" unsigned", file);

        if (TYPE_NO_FORCE_BLK (node))
            fputs (" no-force-blk", file);

        if (TYPE_STRING_FLAG (node))
            fputs (" string-flag", file);

        if (TYPE_NEEDS_CONSTRUCTING (node))
            fputs (" needs-constructing", file);

        if ((code == RECORD_TYPE
                || code == UNION_TYPE
                || code == QUAL_UNION_TYPE
                || code == ARRAY_TYPE)
                && TYPE_REVERSE_STORAGE_ORDER (node))
            fputs (" reverse-storage-order", file);

        /* The transparent-union flag is used for different things in
        different nodes.  */
        if ((code == UNION_TYPE || code == RECORD_TYPE)
                && TYPE_TRANSPARENT_AGGR (node))
            fputs (" transparent-aggr", file);
        else if (code == ARRAY_TYPE
                 && TYPE_NONALIASED_COMPONENT (node))
            fputs (" nonaliased-component", file);

        if (TYPE_PACKED (node))
            fputs (" packed", file);

        if (TYPE_RESTRICT (node))
            fputs (" restrict", file);

        if (TYPE_LANG_FLAG_0 (node))
            fputs (" type_0", file);
        if (TYPE_LANG_FLAG_1 (node))
            fputs (" type_1", file);
        if (TYPE_LANG_FLAG_2 (node))
            fputs (" type_2", file);
        if (TYPE_LANG_FLAG_3 (node))
            fputs (" type_3", file);
        if (TYPE_LANG_FLAG_4 (node))
            fputs (" type_4", file);
        if (TYPE_LANG_FLAG_5 (node))
            fputs (" type_5", file);
        if (TYPE_LANG_FLAG_6 (node))
            fputs (" type_6", file);
        if (TYPE_LANG_FLAG_7 (node))
            fputs (" type_7", file);

        mode = TYPE_MODE (node);
        fprintf (file, " %s", GET_MODE_NAME (mode));

        print_node (file, "size", TYPE_SIZE (node), indent + 4);
        print_node (file, "unit size", TYPE_SIZE_UNIT (node), indent + 4);
        indent_to (file, indent + 3);

        if (TYPE_USER_ALIGN (node))
            fprintf (file, " user");

        fprintf (file, " align %d symtab %d alias set " HOST_WIDE_INT_PRINT_DEC,
                 TYPE_ALIGN (node), TYPE_SYMTAB_ADDRESS (node),
                 (HOST_WIDE_INT) TYPE_ALIAS_SET (node));

        if (TYPE_STRUCTURAL_EQUALITY_P (node))
            fprintf (file, " structural equality");
        else
            dump_addr (file, " canonical type ", TYPE_CANONICAL (node));

        print_node (file, "attributes", TYPE_ATTRIBUTES (node), indent + 4);

        if (INTEGRAL_TYPE_P (node) || code == REAL_TYPE
                || code == FIXED_POINT_TYPE)
        {
            fprintf (file, " precision %d", TYPE_PRECISION (node));
            print_node_brief (file, "min", TYPE_MIN_VALUE (node), indent + 4);
            print_node_brief (file, "max", TYPE_MAX_VALUE (node), indent + 4);
        }

        if (code == ENUMERAL_TYPE)
            print_node (file, "values", TYPE_VALUES (node), indent + 4);
        else if (code == ARRAY_TYPE)
            print_node (file, "domain", TYPE_DOMAIN (node), indent + 4);
        else if (code == VECTOR_TYPE)
            fprintf (file, " nunits %d", (int) TYPE_VECTOR_SUBPARTS (node));
        else if (code == RECORD_TYPE
                 || code == UNION_TYPE
                 || code == QUAL_UNION_TYPE)
            print_node (file, "fields", TYPE_FIELDS (node), indent + 4);
        else if (code == FUNCTION_TYPE
                 || code == METHOD_TYPE)
        {
            if (TYPE_METHOD_BASETYPE (node))
                print_node_brief (file, "method basetype",
                                  TYPE_METHOD_BASETYPE (node), indent + 4);
            print_node (file, "arg-types", TYPE_ARG_TYPES (node), indent + 4);
        }
        else if (code == OFFSET_TYPE)
            print_node_brief (file, "basetype", TYPE_OFFSET_BASETYPE (node),
                              indent + 4);

        if (TYPE_CONTEXT (node))
            print_node_brief (file, "context", TYPE_CONTEXT (node), indent + 4);

        lang_hooks.print_type (file, node, indent);

        if (TYPE_POINTER_TO (node) || TREE_CHAIN (node))
            indent_to (file, indent + 3);

        print_node_brief (file, "pointer_to_this", TYPE_POINTER_TO (node),
                          indent + 4);
        print_node_brief (file, "reference_to_this", TYPE_REFERENCE_TO (node),
                          indent + 4);
        print_node_brief (file, "chain", TREE_CHAIN (node), indent + 4);
        break;

    case tcc_expression:
    case tcc_comparison:
    case tcc_unary:
    case tcc_binary:
    case tcc_reference:
    case tcc_statement:
    case tcc_vl_exp:
        if (code == BIND_EXPR)
        {
            print_node (file, "vars", TREE_OPERAND (node, 0), indent + 4);
            print_node (file, "body", TREE_OPERAND (node, 1), indent + 4);
            print_node (file, "block", TREE_OPERAND (node, 2), indent + 4);
            break;
        }
        if (code == CALL_EXPR)
        {
            call_expr_arg_iterator iter;
            tree arg;
            print_node (file, "fn", CALL_EXPR_FN (node), indent + 4);
            print_node (file, "static_chain", CALL_EXPR_STATIC_CHAIN (node),
                        indent + 4);
            i = 0;
            FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
            {
                char temp[10];
                sprintf (temp, "arg %d", i);
                print_node (file, temp, arg, indent + 4);
                i++;
            }
        }
Exemple #12
0
static const char *
gen_type (const char *ret_val, tree t, formals_style style)
{
  tree chain_p;

  /* If there is a typedef name for this type, use it.  */
  if (TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL)
    data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
  else
    {
      switch (TREE_CODE (t))
	{
	case POINTER_TYPE:
	  if (TYPE_READONLY (t))
	    ret_val = concat ("const ", ret_val, NULL);
	  if (TYPE_VOLATILE (t))
	    ret_val = concat ("volatile ", ret_val, NULL);

	  ret_val = concat ("*", ret_val, NULL);

	  if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
	    ret_val = concat ("(", ret_val, ")", NULL);

	  ret_val = gen_type (ret_val, TREE_TYPE (t), style);

	  return ret_val;

	case ARRAY_TYPE:
	  if (!COMPLETE_TYPE_P (t) || TREE_CODE (TYPE_SIZE (t)) != INTEGER_CST)
	    ret_val = gen_type (concat (ret_val, "[]", NULL),
				TREE_TYPE (t), style);
	  else if (int_size_in_bytes (t) == 0)
	    ret_val = gen_type (concat (ret_val, "[0]", NULL),
				TREE_TYPE (t), style);
	  else
	    {
	      int size = (int_size_in_bytes (t) / int_size_in_bytes (TREE_TYPE (t)));
	      char buff[10];
	      sprintf (buff, "[%d]", size);
	      ret_val = gen_type (concat (ret_val, buff, NULL),
				  TREE_TYPE (t), style);
	    }
	  break;

	case FUNCTION_TYPE:
	  ret_val = gen_type (concat (ret_val,
				      gen_formal_list_for_type (t, style),
				      NULL),
			      TREE_TYPE (t), style);
	  break;

	case IDENTIFIER_NODE:
	  data_type = IDENTIFIER_POINTER (t);
	  break;

	/* The following three cases are complicated by the fact that a
	   user may do something really stupid, like creating a brand new
	   "anonymous" type specification in a formal argument list (or as
	   part of a function return type specification).  For example:

		int f (enum { red, green, blue } color);

	   In such cases, we have no name that we can put into the prototype
	   to represent the (anonymous) type.  Thus, we have to generate the
	   whole darn type specification.  Yuck!  */

	case RECORD_TYPE:
	  if (TYPE_NAME (t))
	    data_type = IDENTIFIER_POINTER (TYPE_NAME (t));
	  else
	    {
	      data_type = "";
	      chain_p = TYPE_FIELDS (t);
	      while (chain_p)
		{
		  data_type = concat (data_type, gen_decl (chain_p, 0, ansi),
				      NULL);
		  chain_p = TREE_CHAIN (chain_p);
		  data_type = concat (data_type, "; ", NULL);
		}
	      data_type = concat ("{ ", data_type, "}", NULL);
	    }
	  data_type = concat ("struct ", data_type, NULL);
	  break;

	case UNION_TYPE:
	  if (TYPE_NAME (t))
	    data_type = IDENTIFIER_POINTER (TYPE_NAME (t));
	  else
	    {
	      data_type = "";
	      chain_p = TYPE_FIELDS (t);
	      while (chain_p)
		{
		  data_type = concat (data_type, gen_decl (chain_p, 0, ansi),
				      NULL);
		  chain_p = TREE_CHAIN (chain_p);
		  data_type = concat (data_type, "; ", NULL);
		}
	      data_type = concat ("{ ", data_type, "}", NULL);
	    }
	  data_type = concat ("union ", data_type, NULL);
	  break;

	case ENUMERAL_TYPE:
	  if (TYPE_NAME (t))
	    data_type = IDENTIFIER_POINTER (TYPE_NAME (t));
	  else
	    {
	      data_type = "";
	      chain_p = TYPE_VALUES (t);
	      while (chain_p)
		{
		  data_type = concat (data_type,
			IDENTIFIER_POINTER (TREE_PURPOSE (chain_p)), NULL);
		  chain_p = TREE_CHAIN (chain_p);
		  if (chain_p)
		    data_type = concat (data_type, ", ", NULL);
		}
	      data_type = concat ("{ ", data_type, " }", NULL);
	    }
	  data_type = concat ("enum ", data_type, NULL);
	  break;

	case TYPE_DECL:
	  data_type = IDENTIFIER_POINTER (DECL_NAME (t));
	  break;

	case INTEGER_TYPE:
	  data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
	  /* Normally, `unsigned' is part of the deal.  Not so if it comes
	     with a type qualifier.  */
	  if (TYPE_UNSIGNED (t) && TYPE_QUALS (t))
	    data_type = concat ("unsigned ", data_type, NULL);
	  break;

	case REAL_TYPE:
	  data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
	  break;

	case VOID_TYPE:
	  data_type = "void";
	  break;

	case ERROR_MARK:
	  data_type = "[ERROR]";
	  break;

	default:
	  gcc_unreachable ();
	}
    }
  if (TYPE_READONLY (t))
    ret_val = concat ("const ", ret_val, NULL);
  if (TYPE_VOLATILE (t))
    ret_val = concat ("volatile ", ret_val, NULL);
  if (TYPE_RESTRICT (t))
    ret_val = concat ("restrict ", ret_val, NULL);
  return ret_val;
}
Exemple #13
0
tree
ubsan_create_data (const char *name, const location_t *ploc,
		   const struct ubsan_mismatch_data *mismatch, ...)
{
  va_list args;
  tree ret, t;
  tree fields[5];
  vec<tree, va_gc> *saved_args = NULL;
  size_t i = 0;
  location_t loc = UNKNOWN_LOCATION;

  /* Firstly, create a pointer to type descriptor type.  */
  tree td_type = ubsan_type_descriptor_type ();
  TYPE_READONLY (td_type) = 1;
  td_type = build_pointer_type (td_type);

  /* Create the structure type.  */
  ret = make_node (RECORD_TYPE);
  if (ploc != NULL)
    {
      loc = LOCATION_LOCUS (*ploc);
      fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
			      ubsan_source_location_type ());
      DECL_CONTEXT (fields[i]) = ret;
      i++;
    }

  va_start (args, mismatch);
  for (t = va_arg (args, tree); t != NULL_TREE;
       i++, t = va_arg (args, tree))
    {
      gcc_checking_assert (i < 3);
      /* Save the tree arguments for later use.  */
      vec_safe_push (saved_args, t);
      fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
			      td_type);
      DECL_CONTEXT (fields[i]) = ret;
      if (i)
	DECL_CHAIN (fields[i - 1]) = fields[i];
    }
  va_end (args);

  if (mismatch != NULL)
    {
      /* We have to add two more decls.  */
      fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
			      pointer_sized_int_node);
      DECL_CONTEXT (fields[i]) = ret;
      DECL_CHAIN (fields[i - 1]) = fields[i];
      i++;

      fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
			      unsigned_char_type_node);
      DECL_CONTEXT (fields[i]) = ret;
      DECL_CHAIN (fields[i - 1]) = fields[i];
      i++;
    }

  TYPE_FIELDS (ret) = fields[0];
  TYPE_NAME (ret) = get_identifier (name);
  layout_type (ret);

  /* Now, fill in the type.  */
  char tmp_name[32];
  static unsigned int ubsan_var_id_num;
  ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_var_id_num++);
  tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
			 ret);
  TREE_STATIC (var) = 1;
  TREE_PUBLIC (var) = 0;
  DECL_ARTIFICIAL (var) = 1;
  DECL_IGNORED_P (var) = 1;
  DECL_EXTERNAL (var) = 0;

  vec<constructor_elt, va_gc> *v;
  vec_alloc (v, i);
  tree ctor = build_constructor (ret, v);

  /* If desirable, set the __ubsan_source_location element.  */
  if (ploc != NULL)
    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));

  size_t nelts = vec_safe_length (saved_args);
  for (i = 0; i < nelts; i++)
    {
      t = (*saved_args)[i];
      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
    }

  if (mismatch != NULL)
    {
      /* Append the pointer data.  */
      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, mismatch->align);
      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, mismatch->ckind);
    }

  TREE_CONSTANT (ctor) = 1;
  TREE_STATIC (ctor) = 1;
  DECL_INITIAL (var) = ctor;
  varpool_finalize_decl (var);

  return var;
}
Exemple #14
0
tree
ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
{
  /* See through any typedefs.  */
  type = TYPE_MAIN_VARIANT (type);

  tree decl = decl_for_type_lookup (type);
  /* It is possible that some of the earlier created DECLs were found
     unused, in that case they weren't emitted and varpool_get_node
     returns NULL node on them.  But now we really need them.  Thus,
     renew them here.  */
  if (decl != NULL_TREE && varpool_get_node (decl))
    return build_fold_addr_expr (decl);

  tree dtype = ubsan_type_descriptor_type ();
  tree type2 = type;
  const char *tname = NULL;
  char *pretty_name;
  unsigned char deref_depth = 0;
  unsigned short tkind, tinfo;

  /* Get the name of the type, or the name of the pointer type.  */
  if (pstyle == UBSAN_PRINT_POINTER)
    {
      gcc_assert (POINTER_TYPE_P (type));
      type2 = TREE_TYPE (type);

      /* Remove any '*' operators from TYPE.  */
      while (POINTER_TYPE_P (type2))
        deref_depth++, type2 = TREE_TYPE (type2);

      if (TREE_CODE (type2) == METHOD_TYPE)
        type2 = TYPE_METHOD_BASETYPE (type2);
    }

  /* If an array, get its type.  */
  type2 = strip_array_types (type2);

  if (pstyle == UBSAN_PRINT_ARRAY)
    {
      while (POINTER_TYPE_P (type2))
        deref_depth++, type2 = TREE_TYPE (type2);
    }

  if (TYPE_NAME (type2) != NULL)
    {
      if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
	tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
      else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
	tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
    }

  if (tname == NULL)
    /* We weren't able to determine the type name.  */
    tname = "<unknown>";

  /* Decorate the type name with '', '*', "struct", or "union".  */
  pretty_name = (char *) alloca (strlen (tname) + 16 + deref_depth);
  if (pstyle == UBSAN_PRINT_POINTER)
    {
      int pos = sprintf (pretty_name, "'%s%s%s%s%s%s%s",
			 TYPE_VOLATILE (type2) ? "volatile " : "",
			 TYPE_READONLY (type2) ? "const " : "",
			 TYPE_RESTRICT (type2) ? "restrict " : "",
			 TYPE_ATOMIC (type2) ? "_Atomic " : "",
			 TREE_CODE (type2) == RECORD_TYPE
			 ? "struct "
			 : TREE_CODE (type2) == UNION_TYPE
			   ? "union " : "", tname,
			 deref_depth == 0 ? "" : " ");
      while (deref_depth-- > 0)
        pretty_name[pos++] = '*';
      pretty_name[pos++] = '\'';
      pretty_name[pos] = '\0';
    }
  else if (pstyle == UBSAN_PRINT_ARRAY)
    {
      /* Pretty print the array dimensions.  */
      gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
      tree t = type;
      int pos = sprintf (pretty_name, "'%s ", tname);
      while (deref_depth-- > 0)
        pretty_name[pos++] = '*';
      while (TREE_CODE (t) == ARRAY_TYPE)
	{
	  pretty_name[pos++] = '[';
	  tree dom = TYPE_DOMAIN (t);
	  if (dom && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
	    pos += sprintf (&pretty_name[pos], HOST_WIDE_INT_PRINT_DEC,
			    tree_to_shwi (TYPE_MAX_VALUE (dom)) + 1);
	  else
	    /* ??? We can't determine the variable name; print VLA unspec.  */
	    pretty_name[pos++] = '*';
	  pretty_name[pos++] = ']';
	  t = TREE_TYPE (t);
	}
      pretty_name[pos++] = '\'';
      pretty_name[pos] = '\0';

     /* Save the tree with stripped types.  */
     type = t;
    }
  else
    sprintf (pretty_name, "'%s'", tname);

  switch (TREE_CODE (type))
    {
    case BOOLEAN_TYPE:
    case ENUMERAL_TYPE:
    case INTEGER_TYPE:
      tkind = 0x0000;
      break;
    case REAL_TYPE:
      /* FIXME: libubsan right now only supports float, double and
	 long double type formats.  */
      if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
	  || TYPE_MODE (type) == TYPE_MODE (double_type_node)
	  || TYPE_MODE (type) == TYPE_MODE (long_double_type_node))
	tkind = 0x0001;
      else
	tkind = 0xffff;
      break;
    default:
      tkind = 0xffff;
      break;
    }
  tinfo = get_ubsan_type_info_for_type (type);

  /* Create a new VAR_DECL of type descriptor.  */
  char tmp_name[32];
  static unsigned int type_var_id_num;
  ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++);
  decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
			  dtype);
  TREE_STATIC (decl) = 1;
  TREE_PUBLIC (decl) = 0;
  DECL_ARTIFICIAL (decl) = 1;
  DECL_IGNORED_P (decl) = 1;
  DECL_EXTERNAL (decl) = 0;

  size_t len = strlen (pretty_name);
  tree str = build_string (len + 1, pretty_name);
  TREE_TYPE (str) = build_array_type (char_type_node,
				      build_index_type (size_int (len)));
  TREE_READONLY (str) = 1;
  TREE_STATIC (str) = 1;
  tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
				    build_int_cst (short_unsigned_type_node,
						   tkind), NULL_TREE,
				    build_int_cst (short_unsigned_type_node,
						   tinfo), NULL_TREE, str);
  TREE_CONSTANT (ctor) = 1;
  TREE_STATIC (ctor) = 1;
  DECL_INITIAL (decl) = ctor;
  varpool_finalize_decl (decl);

  /* Save the VAR_DECL into the hash table.  */
  decl_for_type_insert (type, decl);

  return build_fold_addr_expr (decl);
}
Exemple #15
0
tree
ubsan_type_descriptor (tree type, bool want_pointer_type_p)
{
  /* See through any typedefs.  */
  type = TYPE_MAIN_VARIANT (type);

  tree decl = decl_for_type_lookup (type);
  /* It is possible that some of the earlier created DECLs were found
     unused, in that case they weren't emitted and varpool_get_node
     returns NULL node on them.  But now we really need them.  Thus,
     renew them here.  */
  if (decl != NULL_TREE && varpool_get_node (decl))
    return build_fold_addr_expr (decl);

  tree dtype = ubsan_type_descriptor_type ();
  tree type2 = type;
  const char *tname = NULL;
  char *pretty_name;
  unsigned char deref_depth = 0;
  unsigned short tkind, tinfo;

  /* Get the name of the type, or the name of the pointer type.  */
  if (want_pointer_type_p)
    {
      gcc_assert (POINTER_TYPE_P (type));
      type2 = TREE_TYPE (type);

      /* Remove any '*' operators from TYPE.  */
      while (POINTER_TYPE_P (type2))
        deref_depth++, type2 = TREE_TYPE (type2);

      if (TREE_CODE (type2) == METHOD_TYPE)
        type2 = TYPE_METHOD_BASETYPE (type2);
    }

  if (TYPE_NAME (type2) != NULL)
    {
      if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
	tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
      else
	tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
    }

  if (tname == NULL)
    /* We weren't able to determine the type name.  */
    tname = "<unknown>";

  /* Decorate the type name with '', '*', "struct", or "union".  */
  pretty_name = (char *) alloca (strlen (tname) + 16 + deref_depth);
  if (want_pointer_type_p)
    {
      int pos = sprintf (pretty_name, "'%s%s%s%s%s%s%s",
			 TYPE_VOLATILE (type2) ? "volatile " : "",
			 TYPE_READONLY (type2) ? "const " : "",
			 TYPE_RESTRICT (type2) ? "restrict " : "",
			 TYPE_ATOMIC (type2) ? "_Atomic " : "",
			 TREE_CODE (type2) == RECORD_TYPE
			 ? "struct "
			 : TREE_CODE (type2) == UNION_TYPE
			   ? "union " : "", tname,
			 deref_depth == 0 ? "" : " ");
      while (deref_depth-- > 0)
        pretty_name[pos++] = '*';
      pretty_name[pos++] = '\'';
      pretty_name[pos] = '\0';
    }
  else
    sprintf (pretty_name, "'%s'", tname);

  switch (TREE_CODE (type))
    {
    case INTEGER_TYPE:
      tkind = 0x0000;
      break;
    case REAL_TYPE:
      tkind = 0x0001;
      break;
    default:
      tkind = 0xffff;
      break;
    }
  tinfo = get_ubsan_type_info_for_type (type);

  /* Create a new VAR_DECL of type descriptor.  */
  char tmp_name[32];
  static unsigned int type_var_id_num;
  ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++);
  decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
			  dtype);
  TREE_STATIC (decl) = 1;
  TREE_PUBLIC (decl) = 0;
  DECL_ARTIFICIAL (decl) = 1;
  DECL_IGNORED_P (decl) = 1;
  DECL_EXTERNAL (decl) = 0;

  size_t len = strlen (pretty_name);
  tree str = build_string (len + 1, pretty_name);
  TREE_TYPE (str) = build_array_type (char_type_node,
				      build_index_type (size_int (len)));
  TREE_READONLY (str) = 1;
  TREE_STATIC (str) = 1;
  tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
				    build_int_cst (short_unsigned_type_node,
						   tkind), NULL_TREE,
				    build_int_cst (short_unsigned_type_node,
						   tinfo), NULL_TREE, str);
  TREE_CONSTANT (ctor) = 1;
  TREE_STATIC (ctor) = 1;
  DECL_INITIAL (decl) = ctor;
  rest_of_decl_compilation (decl, 1, 0);

  /* Save the VAR_DECL into the hash table.  */
  decl_for_type_insert (type, decl);

  return build_fold_addr_expr (decl);
}
Exemple #16
0
tree
ubsan_create_data (const char *name, location_t loc, ...)
{
    va_list args;
    tree ret, t;
    tree fields[3];
    VEC(tree, gc) *saved_args = NULL;
    size_t i = 0;

    /* Firstly, create a pointer to type descriptor type.  */
    tree td_type = ubsan_type_descriptor_type ();
    TYPE_READONLY (td_type) = 1;
    td_type = build_pointer_type (td_type);

    /* Create the structure type.  */
    ret = make_node (RECORD_TYPE);
    if (loc != UNKNOWN_LOCATION)
    {
        fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
                                ubsan_source_location_type ());
        DECL_CONTEXT (fields[i]) = ret;
        i++;
    }

    va_start (args, loc);
    for (t = va_arg (args, tree); t != NULL_TREE;
            i++, t = va_arg (args, tree))
    {
        gcc_checking_assert (i < 3);
        /* Save the tree argument for later use.  */
        VEC_safe_push (tree, gc, saved_args, t);
        fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
                                td_type);
        DECL_CONTEXT (fields[i]) = ret;
        if (i)
            DECL_CHAIN (fields[i - 1]) = fields[i];
    }
    TYPE_FIELDS (ret) = fields[0];
    TYPE_NAME (ret) = get_identifier (name);
    layout_type (ret);
    va_end (args);

    /* Now, fill in the type.  */
    char tmp_name[32];
    static unsigned int ubsan_var_id_num;
    ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_var_id_num++);
    tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
                           ret);
    TREE_STATIC (var) = 1;
    TREE_PUBLIC (var) = 0;
    DECL_ARTIFICIAL (var) = 1;
    DECL_IGNORED_P (var) = 1;
    DECL_EXTERNAL (var) = 0;

    VEC(constructor_elt, gc) *v;
    v = VEC_alloc (constructor_elt, gc, i);

    tree ctor = build_constructor (ret, v);

    /* If desirable, set the __ubsan_source_location element.  */
    if (loc != UNKNOWN_LOCATION)
        CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));

    size_t nelts = VEC_length (tree, saved_args);
    for (i = 0; i < nelts; i++)
    {
        t = VEC_index (tree, saved_args, i);
        CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
    }

    TREE_CONSTANT (ctor) = 1;
    TREE_STATIC (ctor) = 1;
    DECL_INITIAL (var) = ctor;
    rest_of_decl_compilation (var, 1, 0);

    return var;
}