Beispiel #1
0
tree
make_alias_for (tree function, tree newid)
{
    tree alias = build_decl (FUNCTION_DECL, newid, TREE_TYPE (function));
    DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (function);
    cxx_dup_lang_specific_decl (alias);
    DECL_CONTEXT (alias) = NULL;
    TREE_READONLY (alias) = TREE_READONLY (function);
    TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (function);
    TREE_PUBLIC (alias) = 0;
    DECL_INTERFACE_KNOWN (alias) = 1;
    DECL_NOT_REALLY_EXTERN (alias) = 1;
    DECL_THIS_STATIC (alias) = 1;
    DECL_SAVED_FUNCTION_DATA (alias) = NULL;
    DECL_DESTRUCTOR_P (alias) = 0;
    DECL_CONSTRUCTOR_P (alias) = 0;
    DECL_CLONED_FUNCTION (alias) = NULL_TREE;
    DECL_EXTERNAL (alias) = 0;
    DECL_ARTIFICIAL (alias) = 1;
    DECL_NO_STATIC_CHAIN (alias) = 1;
    DECL_PENDING_INLINE_P (alias) = 0;
    DECL_INLINE (alias) = 0;
    DECL_DECLARED_INLINE_P (alias) = 0;
    DECL_DEFERRED_FN (alias) = 0;
    DECL_USE_TEMPLATE (alias) = 0;
    DECL_TEMPLATE_INSTANTIATED (alias) = 0;
    DECL_TEMPLATE_INFO (alias) = NULL;
    DECL_INITIAL (alias) = error_mark_node;
    TREE_ADDRESSABLE (alias) = 1;
    TREE_USED (alias) = 1;
    SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias));
    TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1;
    return alias;
}
Beispiel #2
0
void
expand_end_catch_block (void)
{
  if (! doing_eh (1))
    return;

  /* The exception being handled is rethrown if control reaches the end of
     a handler of the function-try-block of a constructor or destructor.  */
  if (in_function_try_handler
      && (DECL_CONSTRUCTOR_P (current_function_decl)
	  || DECL_DESTRUCTOR_P (current_function_decl)))
    finish_expr_stmt (build_throw (NULL_TREE));
}
Beispiel #3
0
static void
cp_ubsan_maybe_instrument_return (tree fndecl)
{
  if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
      || DECL_CONSTRUCTOR_P (fndecl)
      || DECL_DESTRUCTOR_P (fndecl)
      || !targetm.warn_func_return (fndecl))
    return;

  tree t = DECL_SAVED_TREE (fndecl);
  while (t)
    {
      switch (TREE_CODE (t))
	{
	case BIND_EXPR:
	  t = BIND_EXPR_BODY (t);
	  continue;
	case TRY_FINALLY_EXPR:
	  t = TREE_OPERAND (t, 0);
	  continue;
	case STATEMENT_LIST:
	  {
	    tree_stmt_iterator i = tsi_last (t);
	    if (!tsi_end_p (i))
	      {
		t = tsi_stmt (i);
		continue;
	      }
	  }
	  break;
	case RETURN_EXPR:
	  return;
	default:
	  break;
	}
      break;
    }
  if (t == NULL_TREE)
    return;
  t = DECL_SAVED_TREE (fndecl);
  if (TREE_CODE (t) == BIND_EXPR
      && TREE_CODE (BIND_EXPR_BODY (t)) == STATEMENT_LIST)
    {
      tree_stmt_iterator i = tsi_last (BIND_EXPR_BODY (t));
      t = ubsan_instrument_return (DECL_SOURCE_LOCATION (fndecl));
      tsi_link_after (&i, t, TSI_NEW_STMT);
    }
}
Beispiel #4
0
static tree
make_alias_for_thunk (tree function)
{
  tree alias;
  char buf[256];

#if defined (TARGET_IS_PE_COFF)
  if (DECL_ONE_ONLY (function))
    return function;
#endif

  ASM_GENERATE_INTERNAL_LABEL (buf, "LTHUNK", thunk_labelno);
  thunk_labelno++;
  alias = build_decl (FUNCTION_DECL, get_identifier (buf),
		      TREE_TYPE (function));
  DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (function);
  cxx_dup_lang_specific_decl (alias);
  DECL_CONTEXT (alias) = NULL;
  TREE_READONLY (alias) = TREE_READONLY (function);
  TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (function);
  TREE_PUBLIC (alias) = 0;
  DECL_INTERFACE_KNOWN (alias) = 1;
  DECL_NOT_REALLY_EXTERN (alias) = 1;
  DECL_THIS_STATIC (alias) = 1;
  DECL_SAVED_FUNCTION_DATA (alias) = NULL;
  DECL_DESTRUCTOR_P (alias) = 0;
  DECL_CONSTRUCTOR_P (alias) = 0;
  DECL_CLONED_FUNCTION (alias) = NULL_TREE;
  DECL_EXTERNAL (alias) = 0;
  DECL_ARTIFICIAL (alias) = 1;
  DECL_NO_STATIC_CHAIN (alias) = 1;
  DECL_PENDING_INLINE_P (alias) = 0;
  DECL_INLINE (alias) = 0;
  DECL_DECLARED_INLINE_P (alias) = 0;
  DECL_DEFERRED_FN (alias) = 0;
  DECL_USE_TEMPLATE (alias) = 0;
  DECL_TEMPLATE_INSTANTIATED (alias) = 0;
  DECL_TEMPLATE_INFO (alias) = NULL;
  DECL_INITIAL (alias) = error_mark_node;
  TREE_ADDRESSABLE (alias) = 1;
  TREE_USED (alias) = 1;
  SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias));
  TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1;
  if (!flag_syntax_only)
    assemble_alias (alias, DECL_ASSEMBLER_NAME (function));
  return alias;
}
Beispiel #5
0
tree
make_alias_for (tree target, tree newid)
{
  tree alias = build_decl (DECL_SOURCE_LOCATION (target),
			   TREE_CODE (target), newid, TREE_TYPE (target));
  DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (target);
  cxx_dup_lang_specific_decl (alias);
  DECL_CONTEXT (alias) = NULL;
  TREE_READONLY (alias) = TREE_READONLY (target);
  TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (target);
  TREE_PUBLIC (alias) = 0;
  DECL_INTERFACE_KNOWN (alias) = 1;
  if (DECL_LANG_SPECIFIC (alias))
    {
      DECL_NOT_REALLY_EXTERN (alias) = 1;
      DECL_USE_TEMPLATE (alias) = 0;
      DECL_TEMPLATE_INFO (alias) = NULL;
    }
  DECL_EXTERNAL (alias) = 0;
  DECL_ARTIFICIAL (alias) = 1;
  DECL_TEMPLATE_INSTANTIATED (alias) = 0;
  if (TREE_CODE (alias) == FUNCTION_DECL)
    {
      DECL_SAVED_FUNCTION_DATA (alias) = NULL;
      DECL_DESTRUCTOR_P (alias) = 0;
      DECL_CONSTRUCTOR_P (alias) = 0;
      DECL_PENDING_INLINE_P (alias) = 0;
      DECL_DECLARED_INLINE_P (alias) = 0;
      DECL_INITIAL (alias) = error_mark_node;
      DECL_ARGUMENTS (alias) = copy_list (DECL_ARGUMENTS (target));
    }
  else
    TREE_STATIC (alias) = 1;
  TREE_ADDRESSABLE (alias) = 1;
  TREE_USED (alias) = 1;
  SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias));
  TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1;
  return alias;
}
Beispiel #6
0
bool
cp_dump_tree (void* dump_info, tree t)
{
  enum tree_code code;
  dump_info_p di = (dump_info_p) dump_info;

  /* Figure out what kind of node this is.  */
  code = TREE_CODE (t);

  if (DECL_P (t))
    {
      if (DECL_LANG_SPECIFIC (t) && DECL_LANGUAGE (t) != lang_cplusplus)
	dump_string (di, language_to_string (DECL_LANGUAGE (t)));
    }

  switch (code)
    {
    case IDENTIFIER_NODE:
      if (IDENTIFIER_OPNAME_P (t))
	{
	  dump_string (di, "operator");
	  return true;
	}
      else if (IDENTIFIER_TYPENAME_P (t))
	{
	  dump_child ("tynm", TREE_TYPE (t));
	  return true;
	}
      break;

    case OFFSET_TYPE:
      dump_string (di, "ptrmem");
      dump_child ("ptd", TYPE_PTRMEM_POINTED_TO_TYPE (t));
      dump_child ("cls", TYPE_PTRMEM_CLASS_TYPE (t));
      return true;

    case RECORD_TYPE:
      if (TYPE_PTRMEMFUNC_P (t))
	{
	  dump_string (di, "ptrmem");
	  dump_child ("ptd", TYPE_PTRMEM_POINTED_TO_TYPE (t));
	  dump_child ("cls", TYPE_PTRMEM_CLASS_TYPE (t));
	  return true;
	}
      /* Fall through.  */

    case UNION_TYPE:
      /* Is it a type used as a base? */
      if (TYPE_CONTEXT (t) && TREE_CODE (TYPE_CONTEXT (t)) == TREE_CODE (t)
	  && CLASSTYPE_AS_BASE (TYPE_CONTEXT (t)) == t)
	{
	  dump_child ("bfld", TYPE_CONTEXT (t));
	  return true;
	}
      
      if (! IS_AGGR_TYPE (t))
	break;

      dump_child ("vfld", TYPE_VFIELD (t));
      if (CLASSTYPE_TEMPLATE_SPECIALIZATION(t))
        dump_string(di, "spec");

      if (!dump_flag (di, TDF_SLIM, t) && TYPE_BINFO (t))
	{
	  int i;
	  tree binfo;
	  tree base_binfo;
	  
	  for (binfo = TYPE_BINFO (t), i = 0;
	       BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
	    {
	      dump_child ("base", BINFO_TYPE (base_binfo));
	      if (BINFO_VIRTUAL_P (base_binfo)) 
		dump_string (di, "virtual");
	      dump_access (di, base_binfo);
	    }
	}
      break;

    case FIELD_DECL:
      dump_access (di, t);
      if (DECL_MUTABLE_P (t))
        dump_string(di, "mutable");
      break;

    case VAR_DECL:
      if (TREE_CODE (CP_DECL_CONTEXT (t)) == RECORD_TYPE)
        dump_access (di, t);
      if (TREE_STATIC (t) && !TREE_PUBLIC (t))
        dump_string (di, "static");
      break; 

    case FUNCTION_DECL:
      if (!DECL_THUNK_P (t))
	{
          if (DECL_OVERLOADED_OPERATOR_P (t)) {
	    dump_string (di, "operator");
            dump_op (di, t);
          }
	  if (DECL_FUNCTION_MEMBER_P (t)) 
	    {
	      dump_string (di, "member");
	      dump_access (di, t);
	    }
          if (DECL_PURE_VIRTUAL_P (t))
            dump_string (di, "pure");
          if (DECL_VIRTUAL_P (t))
            dump_string (di, "virtual");
	  if (DECL_CONSTRUCTOR_P (t))
	    dump_string (di, "constructor");
	  if (DECL_DESTRUCTOR_P (t))
	    dump_string (di, "destructor");
	  if (DECL_CONV_FN_P (t))
	    dump_string (di, "conversion");
	  if (DECL_GLOBAL_CTOR_P (t))
	    dump_string (di, "global init");
	  if (DECL_GLOBAL_DTOR_P (t))
	    dump_string (di, "global fini");
	  if (DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t))
	    dump_string (di, "pseudo tmpl");
	}
      else
	{
	  tree virt = THUNK_VIRTUAL_OFFSET (t);
	  
	  dump_string (di, "thunk");
	  if (DECL_THIS_THUNK_P (t))
	    dump_string (di, "this adjusting");
	  else
	    {
	      dump_string (di, "result adjusting");
	      if (virt)
		virt = BINFO_VPTR_FIELD (virt);
	    }
	  dump_int (di, "fixd", THUNK_FIXED_OFFSET (t));
	  if (virt)
	    dump_int (di, "virt", tree_low_cst (virt, 0));
	  dump_child ("fn", DECL_INITIAL (t));
	}
      break;

    case NAMESPACE_DECL:
      if (DECL_NAMESPACE_ALIAS (t))
	dump_child ("alis", DECL_NAMESPACE_ALIAS (t));
      else if (!dump_flag (di, TDF_SLIM, t))
	dump_child ("dcls", cp_namespace_decls (t));
      break;

    case TEMPLATE_DECL:
      dump_child ("rslt", DECL_TEMPLATE_RESULT (t));
      dump_child ("inst", DECL_TEMPLATE_INSTANTIATIONS (t));
      dump_child ("spcs", DECL_TEMPLATE_SPECIALIZATIONS (t));
      dump_child ("prms", DECL_TEMPLATE_PARMS (t));
      break;

    case OVERLOAD:
      dump_child ("crnt", OVL_CURRENT (t));
      dump_child ("chan", OVL_CHAIN (t));
      break;

    case TRY_BLOCK:
      dump_stmt (di, t);
      if (CLEANUP_P (t))
	dump_string (di, "cleanup");
      dump_child ("body", TRY_STMTS (t));
      dump_child ("hdlr", TRY_HANDLERS (t));
      break;

    case EH_SPEC_BLOCK:
      dump_stmt (di, t);
      dump_child ("body", EH_SPEC_STMTS (t));
      dump_child ("raises", EH_SPEC_RAISES (t));
      break;

    case PTRMEM_CST:
      dump_child ("clas", PTRMEM_CST_CLASS (t));
      dump_child ("mbr", PTRMEM_CST_MEMBER (t));
      break;

    case THROW_EXPR:
      /* These nodes are unary, but do not have code class `1'.  */
      dump_child ("op 0", TREE_OPERAND (t, 0));
      break;

    case AGGR_INIT_EXPR:
      dump_int (di, "ctor", AGGR_INIT_VIA_CTOR_P (t));
      dump_child ("fn", TREE_OPERAND (t, 0));
      dump_child ("args", TREE_OPERAND (t, 1));
      dump_child ("decl", TREE_OPERAND (t, 2));
      break;
      
    case HANDLER:
      dump_stmt (di, t);
      dump_child ("parm", HANDLER_PARMS (t));
      dump_child ("body", HANDLER_BODY (t));
      break;

    case MUST_NOT_THROW_EXPR:
      dump_stmt (di, t);
      dump_child ("body", TREE_OPERAND (t, 0));
      break;

    case USING_STMT:
      dump_stmt (di, t);
      dump_child ("nmsp", USING_STMT_NAMESPACE (t));
      break;

    case CLEANUP_STMT:
      dump_stmt (di, t);
      dump_child ("decl", CLEANUP_DECL (t));
      dump_child ("expr", CLEANUP_EXPR (t));
      dump_child ("body", CLEANUP_BODY (t));
      break;

    case IF_STMT:
      dump_stmt (di, t);
      dump_child ("cond", IF_COND (t));
      dump_child ("then", THEN_CLAUSE (t));
      dump_child ("else", ELSE_CLAUSE (t));
      break;

    default:
      break;
    }

  return c_dump_tree (di, t);
}
Beispiel #7
0
tree
make_thunk (tree function, bool this_adjusting,
            tree fixed_offset, tree virtual_offset)
{
    HOST_WIDE_INT d;
    tree thunk;

    gcc_assert (TREE_CODE (function) == FUNCTION_DECL);
    /* We can have this thunks to covariant thunks, but not vice versa.  */
    gcc_assert (!DECL_THIS_THUNK_P (function));
    gcc_assert (!DECL_RESULT_THUNK_P (function) || this_adjusting);

    /* Scale the VIRTUAL_OFFSET to be in terms of bytes.  */
    if (this_adjusting && virtual_offset)
        virtual_offset
            = size_binop (MULT_EXPR,
                          virtual_offset,
                          convert (ssizetype,
                                   TYPE_SIZE_UNIT (vtable_entry_type)));

    d = tree_low_cst (fixed_offset, 0);

    /* See if we already have the thunk in question.  For this_adjusting
       thunks VIRTUAL_OFFSET will be an INTEGER_CST, for covariant thunks it
       will be a BINFO.  */
    for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))
        if (DECL_THIS_THUNK_P (thunk) == this_adjusting
                && THUNK_FIXED_OFFSET (thunk) == d
                && !virtual_offset == !THUNK_VIRTUAL_OFFSET (thunk)
                && (!virtual_offset
                    || (this_adjusting
                        ? tree_int_cst_equal (THUNK_VIRTUAL_OFFSET (thunk),
                                              virtual_offset)
                        : THUNK_VIRTUAL_OFFSET (thunk) == virtual_offset)))
            return thunk;

    /* All thunks must be created before FUNCTION is actually emitted;
       the ABI requires that all thunks be emitted together with the
       function to which they transfer control.  */
    gcc_assert (!TREE_ASM_WRITTEN (function));
    /* Likewise, we can only be adding thunks to a function declared in
       the class currently being laid out.  */
    gcc_assert (TYPE_SIZE (DECL_CONTEXT (function))
                && TYPE_BEING_DEFINED (DECL_CONTEXT (function)));

    thunk = build_decl (FUNCTION_DECL, NULL_TREE, TREE_TYPE (function));
    DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function);
    cxx_dup_lang_specific_decl (thunk);
    DECL_THUNKS (thunk) = NULL_TREE;

    DECL_CONTEXT (thunk) = DECL_CONTEXT (function);
    TREE_READONLY (thunk) = TREE_READONLY (function);
    TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function);
    TREE_PUBLIC (thunk) = TREE_PUBLIC (function);
    SET_DECL_THUNK_P (thunk, this_adjusting);
    THUNK_TARGET (thunk) = function;
    THUNK_FIXED_OFFSET (thunk) = d;
    THUNK_VIRTUAL_OFFSET (thunk) = virtual_offset;
    THUNK_ALIAS (thunk) = NULL_TREE;

    /* The thunk itself is not a constructor or destructor, even if
       the thing it is thunking to is.  */
    DECL_INTERFACE_KNOWN (thunk) = 1;
    DECL_NOT_REALLY_EXTERN (thunk) = 1;
    DECL_SAVED_FUNCTION_DATA (thunk) = NULL;
    DECL_DESTRUCTOR_P (thunk) = 0;
    DECL_CONSTRUCTOR_P (thunk) = 0;
    DECL_EXTERNAL (thunk) = 1;
    DECL_ARTIFICIAL (thunk) = 1;
    /* Even if this thunk is a member of a local class, we don't
       need a static chain.  */
    DECL_NO_STATIC_CHAIN (thunk) = 1;
    /* The THUNK is not a pending inline, even if the FUNCTION is.  */
    DECL_PENDING_INLINE_P (thunk) = 0;
    DECL_INLINE (thunk) = 0;
    DECL_DECLARED_INLINE_P (thunk) = 0;
    /* Nor has it been deferred.  */
    DECL_DEFERRED_FN (thunk) = 0;
    /* Nor is it a template instantiation.  */
    DECL_USE_TEMPLATE (thunk) = 0;
    DECL_TEMPLATE_INFO (thunk) = NULL;

    /* Add it to the list of thunks associated with FUNCTION.  */
    TREE_CHAIN (thunk) = DECL_THUNKS (function);
    DECL_THUNKS (function) = thunk;

    return thunk;
}