Example #1
0
tree
get_tinfo_decl (tree type)
{
    tree name;
    tree d;

    if (COMPLETE_TYPE_P (type)
            && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
    {
        error ("cannot create type information for type %qT because "
               "its size is variable",
               type);
        return error_mark_node;
    }

    if (TREE_CODE (type) == METHOD_TYPE)
        type = build_function_type (TREE_TYPE (type),
                                    TREE_CHAIN (TYPE_ARG_TYPES (type)));

    /* For a class type, the variable is cached in the type node
       itself.  */
    if (CLASS_TYPE_P (type))
    {
        d = CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type));
        if (d)
            return d;
    }

    name = mangle_typeinfo_for_type (type);

    d = IDENTIFIER_GLOBAL_VALUE (name);
    if (!d)
    {
        tree var_desc = get_pseudo_ti_desc (type);

        d = build_lang_decl (VAR_DECL, name, TINFO_PSEUDO_TYPE (var_desc));
        SET_DECL_ASSEMBLER_NAME (d, name);
        /* Remember the type it is for.  */
        TREE_TYPE (name) = type;
        DECL_TINFO_P (d) = 1;
        DECL_ARTIFICIAL (d) = 1;
#ifdef KEY /* g++ does not actually ignore it (note push operation below),
              so we cannot either */
        if (!flag_spin_file)
#endif
            DECL_IGNORED_P (d) = 1;
        TREE_READONLY (d) = 1;
        TREE_STATIC (d) = 1;
        /* Mark the variable as undefined -- but remember that we can
        define it later if we need to do so.  */
        DECL_EXTERNAL (d) = 1;
        DECL_NOT_REALLY_EXTERN (d) = 1;
        if (CLASS_TYPE_P (type))
            CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d;
        set_linkage_according_to_type (type, d);
        pushdecl_top_level_and_finish (d, NULL_TREE);

        /* Add decl to the global array of tinfo decls.  */
        VEC_safe_push (tree, unemitted_tinfo_decls, d);
    }
Example #2
0
static int
can_convert_eh (tree to, tree from)
{
  to = non_reference (to);
  from = non_reference (from);

  if (TYPE_PTR_P (to) && TYPE_PTR_P (from))
    {
      to = TREE_TYPE (to);
      from = TREE_TYPE (from);

      if (! at_least_as_qualified_p (to, from))
	return 0;

      if (VOID_TYPE_P (to))
	return 1;

      /* Else fall through.  */
    }

  if (CLASS_TYPE_P (to) && CLASS_TYPE_P (from)
      && publicly_uniquely_derived_p (to, from))
    return 1;

  return 0;
}
Example #3
0
tree
cp_ubsan_maybe_instrument_downcast (location_t loc, tree type, tree op)
{
  if (!POINTER_TYPE_P (type)
      || !POINTER_TYPE_P (TREE_TYPE (op))
      || !CLASS_TYPE_P (TREE_TYPE (type))
      || !CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (op)))
      || !DERIVED_FROM_P (TREE_TYPE (TREE_TYPE (op)), TREE_TYPE (type)))
    return NULL_TREE;

  return cp_ubsan_maybe_instrument_vptr (loc, op, TREE_TYPE (type), true,
					 TREE_CODE (type) == POINTER_TYPE
					 ? UBSAN_DOWNCAST_POINTER
					 : UBSAN_DOWNCAST_REFERENCE);
}
Example #4
0
tree
cp_unit_size_without_reusable_padding (tree type)
{
  if (CLASS_TYPE_P (type))
    return CLASSTYPE_SIZE_UNIT (type);
  return TYPE_SIZE_UNIT (type);
}
Example #5
0
File: friend.c Project: AHelper/gcc
void
add_friend (tree type, tree decl, bool complain)
{
  tree typedecl;
  tree list;
  tree name;
  tree ctx;

  if (decl == error_mark_node)
    return;

  typedecl = TYPE_MAIN_DECL (type);
  list = DECL_FRIENDLIST (typedecl);
  name = DECL_NAME (decl);
  type = TREE_TYPE (typedecl);

  while (list)
    {
      if (name == FRIEND_NAME (list))
	{
	  tree friends = FRIEND_DECLS (list);
	  for (; friends ; friends = TREE_CHAIN (friends))
	    {
	      if (decl == TREE_VALUE (friends))
		{
		  if (complain)
		    warning (OPT_Wredundant_decls,
			     "%qD is already a friend of class %qT",
			     decl, type);
		  return;
		}
	    }

	  maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);

	  TREE_VALUE (list) = tree_cons (NULL_TREE, decl,
					 TREE_VALUE (list));
	  return;
	}
      list = TREE_CHAIN (list);
    }

  ctx = DECL_CONTEXT (decl);
  if (ctx && CLASS_TYPE_P (ctx) && !uses_template_parms (ctx))
    perform_or_defer_access_check (TYPE_BINFO (ctx), decl, decl,
				   tf_warning_or_error);

  maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);

  DECL_FRIENDLIST (typedecl)
    = tree_cons (DECL_NAME (decl), build_tree_list (NULL_TREE, decl),
		 DECL_FRIENDLIST (typedecl));
  if (!uses_template_parms (type))
    DECL_BEFRIENDING_CLASSES (decl)
      = tree_cons (NULL_TREE, type,
		   DECL_BEFRIENDING_CLASSES (decl));
}
Example #6
0
static bool
ok_to_generate_alias_set_for_type (tree t)
{
    if (TYPE_PTRMEMFUNC_P (t))
        return true;
    if (AGGREGATE_TYPE_P (t))
    {
        if ((TREE_CODE (t) == RECORD_TYPE) || (TREE_CODE (t) == UNION_TYPE))
        {
            tree fields;
            /* Backend-created structs are safe.  */
            if (! CLASS_TYPE_P (t))
                return true;
            /* PODs are safe.  */
            if (! CLASSTYPE_NON_POD_P(t))
                return true;
            /* Classes with virtual baseclasses are not.  */
            if (TYPE_USES_VIRTUAL_BASECLASSES (t))
                return false;
            /* Recursively check the base classes.  */
            if (TYPE_BINFO (t) != NULL && TYPE_BINFO_BASETYPES (t) != NULL)
            {
                int i;
                for (i = 0; i < TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (t)); i++)
                {
                    tree binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i);
                    if (!ok_to_generate_alias_set_for_type (BINFO_TYPE (binfo)))
                        return false;
                }
            }
            /* Check all the fields.  */
            for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields))
            {
                if (TREE_CODE (fields) != FIELD_DECL)
                    continue;
                if (! ok_to_generate_alias_set_for_type (TREE_TYPE (fields)))
                    return false;
            }
            return true;
        }
        else if (TREE_CODE (t) == ARRAY_TYPE)
            return ok_to_generate_alias_set_for_type (TREE_TYPE (t));
        else
            /* This should never happen, we dealt with all the aggregate
               types that can appear in C++ above.  */
            abort ();
    }
    else
        return true;
}
Example #7
0
static int
dtor_nothrow (tree type)
{
  if (type == NULL_TREE)
    return 0;

  if (!CLASS_TYPE_P (type))
    return 1;

  if (CLASSTYPE_LAZY_DESTRUCTOR (type))
    lazily_declare_fn (sfk_destructor, type);

  return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type));
}
Example #8
0
tree
cp_ubsan_maybe_instrument_downcast (location_t loc, tree type,
				    tree intype, tree op)
{
  if (!POINTER_TYPE_P (type)
      || !POINTER_TYPE_P (intype)
      || !POINTER_TYPE_P (TREE_TYPE (op))
      || !CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (op)))
      || !is_properly_derived_from (TREE_TYPE (type), TREE_TYPE (intype)))
    return NULL_TREE;

  return cp_ubsan_maybe_instrument_vptr (loc, op, TREE_TYPE (type), true,
					 TREE_CODE (type) == POINTER_TYPE
					 ? UBSAN_DOWNCAST_POINTER
					 : UBSAN_DOWNCAST_REFERENCE);
}
Example #9
0
static bool
omp_var_to_track (tree decl)
{
  tree type = TREE_TYPE (decl);
  if (is_invisiref_parm (decl))
    type = TREE_TYPE (type);
  while (TREE_CODE (type) == ARRAY_TYPE)
    type = TREE_TYPE (type);
  if (type == error_mark_node || !CLASS_TYPE_P (type))
    return false;
  if (VAR_P (decl) && DECL_THREAD_LOCAL_P (decl))
    return false;
  if (cxx_omp_predetermined_sharing (decl) != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
    return false;
  return true;
}
Example #10
0
int
cp_empty_type_p (tree exp)
{
  gcc_assert(TYPE_P(exp));
  if (VOID_TYPE_P(exp))
    return 0;

  /* C++ classes with non-trivial constructors or non-trivial
     assignment operators are assumed non-empty, thus assignments of
     these types can't be elided.  */
  if (CLASS_TYPE_P(exp)
      && (TYPE_HAS_COMPLEX_INIT_REF(exp)
          || TYPE_HAS_COMPLEX_ASSIGN_REF(exp)))
    return 0;

  return is_empty_class(exp);
}
Example #11
0
static bool
cp_ubsan_instrument_vptr_p (tree type)
{
  if (!flag_rtti || flag_sanitize_undefined_trap_on_error)
    return false;

  if (!do_ubsan_in_current_function ())
    return false;

  if (type)
    {
      type = TYPE_MAIN_VARIANT (type);
      if (!CLASS_TYPE_P (type) || !CLASSTYPE_VTABLES (type))
	return false;
    }

  return true;
}
Example #12
0
void
i386_pe_adjust_class_at_definition (tree t)
{
  tree member;

  gcc_assert (CLASS_TYPE_P (t));

 /* We only look at dllimport.  The only thing that dllexport does is
    add stuff to a '.drectiv' section at end-of-file, so no need to do
    anything for dllexport'd classes until we generate RTL. */  
  if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (t)) == NULL_TREE)
    return;

  /* We don't actually add the attribute to the decl, just set the flag
     that signals that the address of this symbol is not a compile-time
     constant.   Any subsequent out-of-class declaration of members wil
     cause the DECL_DLLIMPORT_P flag to be unset.
     (See  tree.c: merge_dllimport_decl_attributes).
     That is just right since out-of class declarations can only be a
     definition.  We recheck the class members  at RTL generation to
     emit warnings if this has happened.  Definition of static data member
     of dllimport'd class always causes an error (as per MS compiler).
     */

  /* Check static VAR_DECL's.  */
  for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
    if (TREE_CODE (member) == VAR_DECL)     
      maybe_add_dllimport (member);
    
  /* Check FUNCTION_DECL's.  */
  for (member = TYPE_METHODS (t); member;  member = TREE_CHAIN (member))
    if (TREE_CODE (member) == FUNCTION_DECL)
      maybe_add_dllimport (member);
 
  /* Check vtables  */
  for (member = CLASSTYPE_VTABLES (t); member;  member = TREE_CHAIN (member))
    if (TREE_CODE (member) == VAR_DECL) 
      maybe_add_dllimport (member);

/* We leave typeinfo tables alone.  We can't mark TI objects as
     dllimport, since the address of a secondary VTT may be needed
     for static initialization of a primary VTT.  VTT's  of
     dllimport'd classes should always be link-once COMDAT.  */ 
}
Example #13
0
static tree
synthesize_exception_spec (tree type, tree (*extractor) (tree, void*),
                           void *client)
{
  tree raises = empty_except_spec;
  tree fields = TYPE_FIELDS (type);
  int i, n_bases = CLASSTYPE_N_BASECLASSES (type);
  tree binfos = TYPE_BINFO_BASETYPES (type);

  for (i = 0; i != n_bases; i++)
    {
      tree base = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
      tree fn = (*extractor) (base, client);
      if (fn)
        {
          tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));
          
          raises = merge_exception_specifiers (raises, fn_raises);
        }
    }
  for (; fields; fields = TREE_CHAIN (fields))
    {
      tree type = TREE_TYPE (fields);
      tree fn;
      
      if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
        continue;
      while (TREE_CODE (type) == ARRAY_TYPE)
  	type = TREE_TYPE (type);
      if (!CLASS_TYPE_P (type))
        continue;
      
      fn = (*extractor) (type, client);
      if (fn)
        {
          tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));
          
          raises = merge_exception_specifiers (raises, fn_raises);
        }
    }
  return raises;
}
Example #14
0
static tree
synthesize_exception_spec (tree type, tree (*extractor) (tree, void*),
                           void *client)
{
    tree raises = empty_except_spec;
    tree fields = TYPE_FIELDS (type);
    tree binfo, base_binfo;
    int i;

    for (binfo = TYPE_BINFO (type), i = 0;
            BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
    {
        tree fn = (*extractor) (BINFO_TYPE (base_binfo), client);
        if (fn)
        {
            tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));

            raises = merge_exception_specifiers (raises, fn_raises);
        }
    }
    for (; fields; fields = TREE_CHAIN (fields))
    {
        tree type = TREE_TYPE (fields);
        tree fn;

        if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
            continue;
        while (TREE_CODE (type) == ARRAY_TYPE)
            type = TREE_TYPE (type);
        if (!CLASS_TYPE_P (type))
            continue;

        fn = (*extractor) (type, client);
        if (fn)
        {
            tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));

            raises = merge_exception_specifiers (raises, fn_raises);
        }
    }
    return raises;
}
Example #15
0
static bool
cp_ubsan_instrument_vptr_p (tree type)
{
  if (!flag_rtti || flag_sanitize_undefined_trap_on_error)
    return false;

  if (current_function_decl
      && lookup_attribute ("no_sanitize_undefined",
			   DECL_ATTRIBUTES (current_function_decl)))
    return false;

  if (type)
    {
      type = TYPE_MAIN_VARIANT (type);
      if (!CLASS_TYPE_P (type) || !CLASSTYPE_VTABLES (type))
	return false;
    }

  return true;
}
Example #16
0
void
cxx_omp_finish_clause (tree c)
{
  tree decl, inner_type;
  bool make_shared = false;

  if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE)
    return;

  decl = OMP_CLAUSE_DECL (c);
  decl = require_complete_type (decl);
  inner_type = TREE_TYPE (decl);
  if (decl == error_mark_node)
    make_shared = true;
  else if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
    {
      if (is_invisiref_parm (decl))
	inner_type = TREE_TYPE (inner_type);
      else
	{
	  error ("%qE implicitly determined as %<firstprivate%> has reference type",
		 decl);
	  make_shared = true;
	}
    }

  /* We're interested in the base element, not arrays.  */
  while (TREE_CODE (inner_type) == ARRAY_TYPE)
    inner_type = TREE_TYPE (inner_type);

  /* Check for special function availability by building a call to one.
     Save the results, because later we won't be in the right context
     for making these queries.  */
  if (!make_shared
      && CLASS_TYPE_P (inner_type)
      && cxx_omp_create_clause_info (c, inner_type, false, true, false))
    make_shared = true;

  if (make_shared)
    OMP_CLAUSE_CODE (c) = OMP_CLAUSE_SHARED;
}
Example #17
0
static HOST_WIDE_INT
cxx_get_alias_set (tree t)
{
    if (TREE_CODE (t) == RECORD_TYPE
            && TYPE_CONTEXT (t) && CLASS_TYPE_P (TYPE_CONTEXT (t))
            && CLASSTYPE_AS_BASE (TYPE_CONTEXT (t)) == t)
        /* The base variant of a type must be in the same alias set as the
           complete type.  */
        return get_alias_set (TYPE_CONTEXT (t));

    if (/* It's not yet safe to use alias sets for some classes in C++.  */
        !ok_to_generate_alias_set_for_type (t)
        /* Nor is it safe to use alias sets for pointers-to-member
        functions, due to the fact that there may be more than one
         RECORD_TYPE type corresponding to the same pointer-to-member
         type.  */
        || TYPE_PTRMEMFUNC_P (t))
        return 0;

    return c_common_get_alias_set (t);
}
Example #18
0
static bool
cp_ubsan_instrument_vptr_p (tree type)
{
  if (!flag_rtti || flag_sanitize_undefined_trap_on_error)
    return false;

  if (!sanitize_flags_p (SANITIZE_VPTR))
    return false;

  if (current_function_decl == NULL_TREE)
    return false;

  if (type)
    {
      type = TYPE_MAIN_VARIANT (type);
      if (!CLASS_TYPE_P (type) || !CLASSTYPE_VTABLES (type))
	return false;
    }

  return true;
}
Example #19
0
tree
cp_expr_size (tree exp)
{
  tree type = TREE_TYPE (exp);

  if (CLASS_TYPE_P (type))
    {
      /* The backend should not be interested in the size of an expression
	 of a type with both of these set; all copies of such types must go
	 through a constructor or assignment op.  */
      gcc_assert (!TYPE_HAS_COMPLEX_INIT_REF (type)
		  || !TYPE_HAS_COMPLEX_ASSIGN_REF (type)
		  /* But storing a CONSTRUCTOR isn't a copy.  */
		  || TREE_CODE (exp) == CONSTRUCTOR
		  /* And, the gimplifier will sometimes make a copy of
		     an aggregate.  In particular, for a case like:

			struct S { S(); };
			struct X { int a; S s; };
			X x = { 0 };

		     the gimplifier will create a temporary with
		     static storage duration, perform static
		     initialization of the temporary, and then copy
		     the result.  Since the "s" subobject is never
		     constructed, this is a valid transformation.  */
		  || CP_AGGREGATE_TYPE_P (type));

      /* This would be wrong for a type with virtual bases, but they are
	 caught by the assert above.  */
      return (is_empty_class (type)
	      ? size_zero_node
	      : CLASSTYPE_SIZE_UNIT (type));
    }
  else
    /* Use the default code.  */
    return lhd_expr_size (exp);
}
Example #20
0
static tree
cp_expr_size (tree exp)
{
    if (CLASS_TYPE_P (TREE_TYPE (exp)))
    {
        /* The backend should not be interested in the size of an expression
        of a type with both of these set; all copies of such types must go
         through a constructor or assignment op.  */
        if (TYPE_HAS_COMPLEX_INIT_REF (TREE_TYPE (exp))
                && TYPE_HAS_COMPLEX_ASSIGN_REF (TREE_TYPE (exp))
                /* But storing a CONSTRUCTOR isn't a copy.  */
                && TREE_CODE (exp) != CONSTRUCTOR)
            abort ();
        /* This would be wrong for a type with virtual bases, but they are
        caught by the abort above.  */
        return (is_empty_class (TREE_TYPE (exp))
                ? size_zero_node
                : CLASSTYPE_SIZE_UNIT (TREE_TYPE (exp)));
    }
    else
        /* Use the default code.  */
        return lhd_expr_size (exp);
}
Example #21
0
tree
build_throw (tree exp)
{
  if (exp == error_mark_node)
    return exp;

  if (processing_template_decl)
    {
      if (cfun)
	current_function_returns_abnormally = 1;
      exp = build_min (THROW_EXPR, void_type_node, exp);
      SET_EXPR_LOCATION (exp, input_location);
      return exp;
    }

  if (exp && null_node_p (exp))
    warning (0, "throwing NULL, which has integral, not pointer type");

  if (exp != NULL_TREE)
    {
      if (!is_admissible_throw_operand_or_catch_parameter (exp, true))
	return error_mark_node;
    }

  if (! doing_eh ())
    return error_mark_node;

  if (exp)
    {
      tree throw_type;
      tree temp_type;
      tree cleanup;
      tree object, ptr;
      tree tmp;
      tree allocate_expr;

      /* The CLEANUP_TYPE is the internal type of a destructor.  */
      if (!cleanup_type)
	{
	  tmp = build_function_type_list (void_type_node,
					  ptr_type_node, NULL_TREE);
	  cleanup_type = build_pointer_type (tmp);
	}

      if (!throw_fn)
	{
	  tree name = get_identifier ("__cxa_throw");
	  throw_fn = get_global_binding (name);
	  if (!throw_fn)
	    {
	      /* Declare void __cxa_throw (void*, void*, void (*)(void*)).  */
	      /* ??? Second argument is supposed to be "std::type_info*".  */
	      tmp = build_function_type_list (void_type_node,
					      ptr_type_node, ptr_type_node,
					      cleanup_type, NULL_TREE);
	      throw_fn = push_throw_library_fn (name, tmp);

	      if (flag_tm)
		{
		  tree itm_name = get_identifier ("_ITM_cxa_throw");
		  tree itm_fn = get_global_binding (itm_name);
		  if (!itm_fn)
		    itm_fn = push_throw_library_fn (itm_name, tmp);
		  apply_tm_attr (itm_fn, get_identifier ("transaction_pure"));
		  record_tm_replacement (throw_fn, itm_fn);
		}
	    }
	}

      /* [except.throw]

	 A throw-expression initializes a temporary object, the type
	 of which is determined by removing any top-level
	 cv-qualifiers from the static type of the operand of throw
	 and adjusting the type from "array of T" or "function return
	 T" to "pointer to T" or "pointer to function returning T"
	 respectively.  */
      temp_type = is_bitfield_expr_with_lowered_type (exp);
      if (!temp_type)
	temp_type = cv_unqualified (type_decays_to (TREE_TYPE (exp)));

      /* OK, this is kind of wacky.  The standard says that we call
	 terminate when the exception handling mechanism, after
	 completing evaluation of the expression to be thrown but
	 before the exception is caught (_except.throw_), calls a
	 user function that exits via an uncaught exception.

	 So we have to protect the actual initialization of the
	 exception object with terminate(), but evaluate the
	 expression first.  Since there could be temps in the
	 expression, we need to handle that, too.  We also expand
	 the call to __cxa_allocate_exception first (which doesn't
	 matter, since it can't throw).  */

      /* Allocate the space for the exception.  */
      allocate_expr = do_allocate_exception (temp_type);
      allocate_expr = get_target_expr (allocate_expr);
      ptr = TARGET_EXPR_SLOT (allocate_expr);
      TARGET_EXPR_CLEANUP (allocate_expr) = do_free_exception (ptr);
      CLEANUP_EH_ONLY (allocate_expr) = 1;

      object = build_nop (build_pointer_type (temp_type), ptr);
      object = cp_build_fold_indirect_ref (object);

      /* And initialize the exception object.  */
      if (CLASS_TYPE_P (temp_type))
	{
	  int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING;
	  vec<tree, va_gc> *exp_vec;
	  bool converted = false;

	  /* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes
	     treated as an rvalue for the purposes of overload resolution
	     to favor move constructors over copy constructors.  */
	  if (/* Must be a local, automatic variable.  */
	      VAR_P (exp)
	      && DECL_CONTEXT (exp) == current_function_decl
	      && ! TREE_STATIC (exp)
	      /* The variable must not have the `volatile' qualifier.  */
	      && !(cp_type_quals (TREE_TYPE (exp)) & TYPE_QUAL_VOLATILE))
	    {
	      tree moved = move (exp);
	      exp_vec = make_tree_vector_single (moved);
	      moved = (build_special_member_call
		       (object, complete_ctor_identifier, &exp_vec,
			TREE_TYPE (object), flags|LOOKUP_PREFER_RVALUE,
			tf_none));
	      release_tree_vector (exp_vec);
	      if (moved != error_mark_node)
		{
		  exp = moved;
		  converted = true;
		}
	    }

	  /* Call the copy constructor.  */
	  if (!converted)
	    {
	      exp_vec = make_tree_vector_single (exp);
	      exp = (build_special_member_call
		     (object, complete_ctor_identifier, &exp_vec,
		      TREE_TYPE (object), flags, tf_warning_or_error));
	      release_tree_vector (exp_vec);
	    }

	  if (exp == error_mark_node)
	    {
	      error ("  in thrown expression");
	      return error_mark_node;
	    }
	}
      else
	{
	  tmp = decay_conversion (exp, tf_warning_or_error);
	  if (tmp == error_mark_node)
	    return error_mark_node;
	  exp = build2 (INIT_EXPR, temp_type, object, tmp);
	}

      /* Mark any cleanups from the initialization as MUST_NOT_THROW, since
	 they are run after the exception object is initialized.  */
      cp_walk_tree_without_duplicates (&exp, wrap_cleanups_r, 0);

      /* Prepend the allocation.  */
      exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);

      /* Force all the cleanups to be evaluated here so that we don't have
	 to do them during unwinding.  */
      exp = build1 (CLEANUP_POINT_EXPR, void_type_node, exp);

      throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));

      cleanup = NULL_TREE;
      if (type_build_dtor_call (TREE_TYPE (object)))
	{
	  tree dtor_fn = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
					  complete_dtor_identifier, 0);
	  dtor_fn = BASELINK_FUNCTIONS (dtor_fn);
	  mark_used (dtor_fn);
	  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object)))
	    {
	      cxx_mark_addressable (dtor_fn);
	      /* Pretend it's a normal function.  */
	      cleanup = build1 (ADDR_EXPR, cleanup_type, dtor_fn);
	    }
	}
      if (cleanup == NULL_TREE)
	cleanup = build_int_cst (cleanup_type, 0);

      /* ??? Indicate that this function call throws throw_type.  */
      tmp = cp_build_function_call_nary (throw_fn, tf_warning_or_error,
					 ptr, throw_type, cleanup, NULL_TREE);

      /* Tack on the initialization stuff.  */
      exp = build2 (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp);
    }
  else
    {
      /* Rethrow current exception.  */
      if (!rethrow_fn)
	{
	  tree name = get_identifier ("__cxa_rethrow");
	  rethrow_fn = get_global_binding (name);
	  if (!rethrow_fn)
	    /* Declare void __cxa_rethrow (void).  */
	    rethrow_fn = push_throw_library_fn
	      (name, build_function_type_list (void_type_node, NULL_TREE));

	  if (flag_tm)
	    apply_tm_attr (rethrow_fn, get_identifier ("transaction_pure"));
	}

      /* ??? Indicate that this function call allows exceptions of the type
	 of the enclosing catch block (if known).  */
      exp = cp_build_function_call_vec (rethrow_fn, NULL, tf_warning_or_error);
    }

  exp = build1 (THROW_EXPR, void_type_node, exp);
  SET_EXPR_LOCATION (exp, input_location);

  return exp;
}
Example #22
0
void
i386_pe_adjust_class_at_definition (tree t)
{
  tree member;

  gcc_assert (CLASS_TYPE_P (t));
 
 
  if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (t)) != NULL_TREE)
    {
      tree tmv = TYPE_MAIN_VARIANT (t);

      /* Make sure that we set dllexport attribute to typeinfo's
	 base declaration, as otherwise it would fail to be exported as
	 it isn't a class-member.  */
      if (tmv != NULL_TREE
	  && CLASSTYPE_TYPEINFO_VAR (tmv) != NULL_TREE)
	{
	  tree na, ti_decl = CLASSTYPE_TYPEINFO_VAR (tmv);
	  na = tree_cons (get_identifier ("dllexport"), NULL_TREE,
			  NULL_TREE);
	  decl_attributes (&ti_decl, na, 0);
	}

      /* Check static VAR_DECL's.  */
      for (member = TYPE_FIELDS (t); member; member = DECL_CHAIN (member))
	if (TREE_CODE (member) == VAR_DECL)     
	  maybe_add_dllexport (member);
    
      /* Check FUNCTION_DECL's.  */
      for (member = TYPE_METHODS (t); member;  member = DECL_CHAIN (member))
	if (TREE_CODE (member) == FUNCTION_DECL)
	  {
	    tree thunk;
	    maybe_add_dllexport (member);
	  
	    /* Also add the attribute to its thunks.  */
	    for (thunk = DECL_THUNKS (member); thunk;
		 thunk = TREE_CHAIN (thunk))
	      maybe_add_dllexport (thunk);
	}
      /* Check vtables  */
      for (member = CLASSTYPE_VTABLES (t); member;  member = DECL_CHAIN (member))
	if (TREE_CODE (member) == VAR_DECL) 
	  maybe_add_dllexport (member);
    }

  else if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (t)) != NULL_TREE)
    {
      /* We don't actually add the attribute to the decl, just set the flag
	 that signals that the address of this symbol is not a compile-time
	 constant.   Any subsequent out-of-class declaration of members wil
	 cause the DECL_DLLIMPORT_P flag to be unset.
	 (See  tree.c: merge_dllimport_decl_attributes).
	 That is just right since out-of class declarations can only be a
	 definition.   */

      /* Check static VAR_DECL's.  */
      for (member = TYPE_FIELDS (t); member; member = DECL_CHAIN (member))
	if (TREE_CODE (member) == VAR_DECL)     
	  maybe_add_dllimport (member);
    
      /* Check FUNCTION_DECL's.  */
      for (member = TYPE_METHODS (t); member;  member = DECL_CHAIN (member))
	if (TREE_CODE (member) == FUNCTION_DECL)
	  {
	    tree thunk;
	    maybe_add_dllimport (member);
	  
	    /* Also add the attribute to its thunks.  */
	    for (thunk = DECL_THUNKS (member); thunk;
		 thunk = DECL_CHAIN (thunk))
	      maybe_add_dllimport (thunk);
	 }
 
      /* Check vtables  */
      for (member = CLASSTYPE_VTABLES (t); member;  member = DECL_CHAIN (member))
	if (TREE_CODE (member) == VAR_DECL) 
	  maybe_add_dllimport (member);

      /* We leave typeinfo tables alone.  We can't mark TI objects as
	dllimport, since the address of a secondary VTT may be needed
	for static initialization of a primary VTT.  VTT's  of
	dllimport'd classes should always be link-once COMDAT.  */ 
    }
}
Example #23
0
tree
do_friend (tree ctype, tree declarator, tree decl,
           tree attrlist, enum overload_flags flags,
           bool funcdef_flag)
{
    gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
    gcc_assert (!ctype || MAYBE_CLASS_TYPE_P (ctype));

    /* Every decl that gets here is a friend of something.  */
    DECL_FRIEND_P (decl) = 1;

    /* Unfortunately, we have to handle attributes here.  Normally we would
       handle them in start_decl_1, but since this is a friend decl start_decl_1
       never gets to see it.  */

    /* Set attributes here so if duplicate decl, will have proper attributes.  */
    cplus_decl_attributes (&decl, attrlist, 0);

    if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
    {
        declarator = TREE_OPERAND (declarator, 0);
        if (is_overloaded_fn (declarator))
            declarator = DECL_NAME (get_first_fn (declarator));
    }

    if (ctype)
    {
        /* CLASS_TEMPLATE_DEPTH counts the number of template headers for
        the enclosing class.  FRIEND_DEPTH counts the number of template
         headers used for this friend declaration.  TEMPLATE_MEMBER_P is
         true if a template header in FRIEND_DEPTH is intended for
         DECLARATOR.  For example, the code

           template <class T> struct A {
             template <class U> struct B {
               template <class V> template <class W>
        	 friend void C<V>::f(W);
             };
           };

         will eventually give the following results

         1. CLASS_TEMPLATE_DEPTH equals 2 (for `T' and `U').
         2. FRIEND_DEPTH equals 2 (for `V' and `W').
         3. TEMPLATE_MEMBER_P is true (for `W').  */

        int class_template_depth = template_class_depth (current_class_type);
        int friend_depth = processing_template_decl - class_template_depth;
        /* We will figure this out later.  */
        bool template_member_p = false;

        tree cname = TYPE_NAME (ctype);
        if (TREE_CODE (cname) == TYPE_DECL)
            cname = DECL_NAME (cname);

        /* A method friend.  */
        if (flags == NO_SPECIAL && declarator == cname)
            DECL_CONSTRUCTOR_P (decl) = 1;

        grokclassfn (ctype, decl, flags);

        if (friend_depth)
        {
            if (!uses_template_parms_level (ctype, class_template_depth
                                            + friend_depth))
                template_member_p = true;
        }

        /* A nested class may declare a member of an enclosing class
        to be a friend, so we do lookup here even if CTYPE is in
         the process of being defined.  */
        if (class_template_depth
                || COMPLETE_TYPE_P (ctype)
                || (CLASS_TYPE_P (ctype) && TYPE_BEING_DEFINED (ctype)))
        {
            if (DECL_TEMPLATE_INFO (decl))
                /* DECL is a template specialization.  No need to
                   build a new TEMPLATE_DECL.  */
                ;
            else if (class_template_depth)
                /* We rely on tsubst_friend_function to check the
                   validity of the declaration later.  */
                decl = push_template_decl_real (decl, /*is_friend=*/true);
            else
                decl = check_classfn (ctype, decl,
                                      template_member_p
                                      ? current_template_parms
                                      : NULL_TREE);

            if (template_member_p && decl && TREE_CODE (decl) == FUNCTION_DECL)
                decl = DECL_TI_TEMPLATE (decl);

            if (decl)
                add_friend (current_class_type, decl, /*complain=*/true);
        }
        else
            error ("member %qD declared as friend before type %qT defined",
                   decl, ctype);
    }
    /* A global friend.
       @@ or possibly a friend from a base class ?!?  */
    else if (TREE_CODE (decl) == FUNCTION_DECL)
    {
        int is_friend_template = PROCESSING_REAL_TEMPLATE_DECL_P ();

        /* Friends must all go through the overload machinery,
        even though they may not technically be overloaded.

         Note that because classes all wind up being top-level
         in their scope, their friend wind up in top-level scope as well.  */
        if (funcdef_flag)
            SET_DECL_FRIEND_CONTEXT (decl, current_class_type);

        if (! DECL_USE_TEMPLATE (decl))
        {
            /* We must check whether the decl refers to template
               arguments before push_template_decl_real adds a
               reference to the containing template class.  */
            int warn = (warn_nontemplate_friend
                        && ! funcdef_flag && ! is_friend_template
                        && current_template_parms
                        && uses_template_parms (decl));

            if (is_friend_template
                    || template_class_depth (current_class_type) != 0)
                /* We can't call pushdecl for a template class, since in
                   general, such a declaration depends on template
                   parameters.  Instead, we call pushdecl when the class
                   is instantiated.  */
                decl = push_template_decl_real (decl, /*is_friend=*/true);
            else if (current_function_decl)
            {
                /* This must be a local class.  11.5p11:

                If a friend declaration appears in a local class (9.8) and
                 the name specified is an unqualified name, a prior
                 declaration is looked up without considering scopes that
                 are outside the innermost enclosing non-class scope. For a
                 friend function declaration, if there is no prior
                 declaration, the program is ill-formed.  */
                tree t = lookup_name_innermost_nonclass_level (DECL_NAME (decl));
                if (t)
                    decl = pushdecl_maybe_friend (decl, /*is_friend=*/true);
                else
                {
                    error ("friend declaration %qD in local class without "
                           "prior declaration", decl);
                    return error_mark_node;
                }
            }
            else
            {
                /* We can't use pushdecl, as we might be in a template
                class specialization, and pushdecl will insert an
                 unqualified friend decl into the template parameter
                 scope, rather than the namespace containing it.  */
                tree ns = decl_namespace_context (decl);

                push_nested_namespace (ns);
                decl = pushdecl_namespace_level (decl, /*is_friend=*/true);
                pop_nested_namespace (ns);
            }

            if (warn)
            {
                static int explained;
                bool warned;

                warned = warning (OPT_Wnon_template_friend, "friend declaration "
                                  "%q#D declares a non-template function", decl);
                if (! explained && warned)
                {
                    inform (input_location, "(if this is not what you intended, make sure "
                            "the function template has already been declared "
                            "and add <> after the function name here) ");
                    explained = 1;
                }
            }
        }

        if (decl == error_mark_node)
            return error_mark_node;

        add_friend (current_class_type,
                    is_friend_template ? DECL_TI_TEMPLATE (decl) : decl,
                    /*complain=*/true);
        DECL_FRIEND_P (decl) = 1;
    }

    return decl;
}
Example #24
0
void
make_friend_class (tree type, tree friend_type, bool complain)
{
    tree classes;

    /* CLASS_TEMPLATE_DEPTH counts the number of template headers for
       the enclosing class.  FRIEND_DEPTH counts the number of template
       headers used for this friend declaration.  TEMPLATE_MEMBER_P,
       defined inside the `if' block for TYPENAME_TYPE case, is true if
       a template header in FRIEND_DEPTH is intended for DECLARATOR.
       For example, the code

         template <class T> struct A {
     template <class U> struct B {
       template <class V> template <class W>
         friend class C<V>::D;
     };
         };

       will eventually give the following results

       1. CLASS_TEMPLATE_DEPTH equals 2 (for `T' and `U').
       2. FRIEND_DEPTH equals 2 (for `V' and `W').
       3. TEMPLATE_MEMBER_P is true (for `W').

       The friend is a template friend iff FRIEND_DEPTH is nonzero.  */

    int class_template_depth = template_class_depth (type);
    int friend_depth = processing_template_decl - class_template_depth;

    if (! MAYBE_CLASS_TYPE_P (friend_type))
    {
        error ("invalid type %qT declared %<friend%>", friend_type);
        return;
    }

    if (friend_depth)
        /* If the TYPE is a template then it makes sense for it to be
           friends with itself; this means that each instantiation is
           friends with all other instantiations.  */
    {
        if (CLASS_TYPE_P (friend_type)
                && CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type)
                && uses_template_parms (friend_type))
        {
            /* [temp.friend]
               Friend declarations shall not declare partial
               specializations.  */
            error ("partial specialization %qT declared %<friend%>",
                   friend_type);
            return;
        }
    }
    else if (same_type_p (type, friend_type))
    {
        if (complain)
            warning (0, "class %qT is implicitly friends with itself",
                     type);
        return;
    }

    /* [temp.friend]

       A friend of a class or class template can be a function or
       class template, a specialization of a function template or
       class template, or an ordinary (nontemplate) function or
       class.  */
    if (!friend_depth)
        ;/* ok */
    else if (TREE_CODE (friend_type) == TYPENAME_TYPE)
    {
        if (TREE_CODE (TYPENAME_TYPE_FULLNAME (friend_type))
                == TEMPLATE_ID_EXPR)
        {
            /* template <class U> friend class T::X<U>; */
            /* [temp.friend]
               Friend declarations shall not declare partial
               specializations.  */
            error ("partial specialization %qT declared %<friend%>",
                   friend_type);
            return;
        }
        else
        {
            /* We will figure this out later.  */
            bool template_member_p = false;

            tree ctype = TYPE_CONTEXT (friend_type);
            tree name = TYPE_IDENTIFIER (friend_type);
            tree decl;

            if (!uses_template_parms_level (ctype, class_template_depth
                                            + friend_depth))
                template_member_p = true;

            if (class_template_depth)
            {
                /* We rely on tsubst_friend_class to check the
                validity of the declaration later.  */
                if (template_member_p)
                    friend_type
                        = make_unbound_class_template (ctype,
                                                       name,
                                                       current_template_parms,
                                                       tf_error);
                else
                    friend_type
                        = make_typename_type (ctype, name, class_type, tf_error);
            }
            else
            {
                decl = lookup_member (ctype, name, 0, true);
                if (!decl)
                {
                    error ("%qT is not a member of %qT", name, ctype);
                    return;
                }
                if (template_member_p && !DECL_CLASS_TEMPLATE_P (decl))
                {
                    error ("%qT is not a member class template of %qT",
                           name, ctype);
                    error ("%q+D declared here", decl);
                    return;
                }
                if (!template_member_p && (TREE_CODE (decl) != TYPE_DECL
                                           || !CLASS_TYPE_P (TREE_TYPE (decl))))
                {
                    error ("%qT is not a nested class of %qT",
                           name, ctype);
                    error ("%q+D declared here", decl);
                    return;
                }

                friend_type = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl));
            }
        }
    }
    else if (TREE_CODE (friend_type) == TEMPLATE_TYPE_PARM)
    {
        /* template <class T> friend class T; */
        error ("template parameter type %qT declared %<friend%>", friend_type);
        return;
    }
    else if (!CLASSTYPE_TEMPLATE_INFO (friend_type))
    {
        /* template <class T> friend class A; where A is not a template */
        error ("%q#T is not a template", friend_type);
        return;
    }
    else
        /* template <class T> friend class A; where A is a template */
        friend_type = CLASSTYPE_TI_TEMPLATE (friend_type);

    if (friend_type == error_mark_node)
        return;

    /* See if it is already a friend.  */
    for (classes = CLASSTYPE_FRIEND_CLASSES (type);
            classes;
            classes = TREE_CHAIN (classes))
    {
        tree probe = TREE_VALUE (classes);

        if (TREE_CODE (friend_type) == TEMPLATE_DECL)
        {
            if (friend_type == probe)
            {
                if (complain)
                    warning (0, "%qD is already a friend of %qT", probe, type);
                break;
            }
        }
        else if (TREE_CODE (probe) != TEMPLATE_DECL)
        {
            if (same_type_p (probe, friend_type))
            {
                if (complain)
                    warning (0, "%qT is already a friend of %qT", probe, type);
                break;
            }
        }
    }

    if (!classes)
    {
        maybe_add_class_template_decl_list (type, friend_type, /*friend_p=*/1);

        CLASSTYPE_FRIEND_CLASSES (type)
            = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
        if (TREE_CODE (friend_type) == TEMPLATE_DECL)
            friend_type = TREE_TYPE (friend_type);
        if (!uses_template_parms (type))
            CLASSTYPE_BEFRIENDING_CLASSES (friend_type)
                = tree_cons (NULL_TREE, type,
                             CLASSTYPE_BEFRIENDING_CLASSES (friend_type));
    }
}
Example #25
0
File: ptree.c Project: AHelper/gcc
void
cxx_print_type (FILE *file, tree node, int indent)
{
  switch (TREE_CODE (node))
    {
    case TEMPLATE_TYPE_PARM:
    case TEMPLATE_TEMPLATE_PARM:
    case BOUND_TEMPLATE_TEMPLATE_PARM:
      indent_to (file, indent + 3);
      fprintf (file, "index %d level %d orig_level %d",
	       TEMPLATE_TYPE_IDX (node), TEMPLATE_TYPE_LEVEL (node),
	       TEMPLATE_TYPE_ORIG_LEVEL (node));
      return;

    case FUNCTION_TYPE:
    case METHOD_TYPE:
      if (TYPE_RAISES_EXCEPTIONS (node))
	print_node (file, "throws", TYPE_RAISES_EXCEPTIONS (node), indent + 4);
      return;

    case RECORD_TYPE:
    case UNION_TYPE:
      break;

    case DECLTYPE_TYPE:
      print_node (file, "expr", DECLTYPE_TYPE_EXPR (node), indent + 4);
      return;

    case TYPENAME_TYPE:
      print_node (file, "fullname", TYPENAME_TYPE_FULLNAME (node),
		  indent + 4);
      return;

    case TYPE_PACK_EXPANSION:
      print_node (file, "args", PACK_EXPANSION_EXTRA_ARGS (node), indent + 4);
      return;

    default:
      return;
    }

  if (TYPE_PTRMEMFUNC_P (node))
    print_node (file, "ptrmemfunc fn type", TYPE_PTRMEMFUNC_FN_TYPE (node),
		indent + 4);

  if (! CLASS_TYPE_P (node))
    return;

  indent_to (file, indent + 4);
  fprintf (file, "full-name \"%s\"",
	   type_as_string (node, TFF_CLASS_KEY_OR_ENUM));

  indent_to (file, indent + 3);

  if (TYPE_NEEDS_CONSTRUCTING (node))
    fputs ( " needs-constructor", file);
  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (node))
    fputs (" needs-destructor", file);
  if (TYPE_HAS_DEFAULT_CONSTRUCTOR (node))
    fputs (" X()", file);
  if (TYPE_HAS_CONVERSION (node))
    fputs (" has-type-conversion", file);
  if (TYPE_HAS_COPY_CTOR (node))
    {
      if (TYPE_HAS_CONST_COPY_CTOR (node))
	fputs (" X(constX&)", file);
      else
	fputs (" X(X&)", file);
    }
  if (TYPE_HAS_NEW_OPERATOR (node))
    fputs (" new", file);
  if (TYPE_HAS_ARRAY_NEW_OPERATOR (node))
    fputs (" new[]", file);
  if (TYPE_GETS_DELETE (node) & 1)
    fputs (" delete", file);
  if (TYPE_GETS_DELETE (node) & 2)
    fputs (" delete[]", file);
  if (TYPE_HAS_COPY_ASSIGN (node))
    fputs (" this=(X&)", file);
  if (CLASSTYPE_SORTED_FIELDS (node))
    fprintf (file, " sorted-fields %p",
	     (void *) CLASSTYPE_SORTED_FIELDS (node));

  if (TREE_CODE (node) == RECORD_TYPE)
    {
      if (TYPE_BINFO (node))
	fprintf (file, " n_parents=%d",
		 BINFO_N_BASE_BINFOS (TYPE_BINFO (node)));
      else
	fprintf (file, " no-binfo");

      fprintf (file, " use_template=%d", CLASSTYPE_USE_TEMPLATE (node));
      if (CLASSTYPE_INTERFACE_ONLY (node))
	fprintf (file, " interface-only");
      if (CLASSTYPE_INTERFACE_UNKNOWN (node))
	fprintf (file, " interface-unknown");
    }
}
Example #26
0
File: cvt.c Project: h4ck3rm1k3/gcc
tree
ocp_convert (tree type, tree expr, int convtype, int flags)
{
  tree e = expr;
  enum tree_code code = TREE_CODE (type);
  const char *invalid_conv_diag;

  if (error_operand_p (e) || type == error_mark_node)
    return error_mark_node;

  complete_type (type);
  complete_type (TREE_TYPE (expr));

  if ((invalid_conv_diag
       = targetm.invalid_conversion (TREE_TYPE (expr), type)))
    {
      error (invalid_conv_diag);
      return error_mark_node;
    }

  e = integral_constant_value (e);

  if (MAYBE_CLASS_TYPE_P (type) && (convtype & CONV_FORCE_TEMP))
    /* We need a new temporary; don't take this shortcut.  */;
  else if (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (e)))
    {
      if (same_type_p (type, TREE_TYPE (e)))
	/* The call to fold will not always remove the NOP_EXPR as
	   might be expected, since if one of the types is a typedef;
	   the comparison in fold is just equality of pointers, not a
	   call to comptypes.  We don't call fold in this case because
	   that can result in infinite recursion; fold will call
	   convert, which will call ocp_convert, etc.  */
	return e;
      /* For complex data types, we need to perform componentwise
	 conversion.  */
      else if (TREE_CODE (type) == COMPLEX_TYPE)
	return fold_if_not_in_template (convert_to_complex (type, e));
      else if (TREE_CODE (e) == TARGET_EXPR)
	{
	  /* Don't build a NOP_EXPR of class type.  Instead, change the
	     type of the temporary.  */
	  TREE_TYPE (e) = TREE_TYPE (TARGET_EXPR_SLOT (e)) = type;
	  return e;
	}
      else
	{
	  /* We shouldn't be treating objects of ADDRESSABLE type as
	     rvalues.  */
	  gcc_assert (!TREE_ADDRESSABLE (type));
	  return fold_if_not_in_template (build_nop (type, e));
	}
    }

  if (code == VOID_TYPE && (convtype & CONV_STATIC))
    {
      e = convert_to_void (e, /*implicit=*/NULL, tf_warning_or_error);
      return e;
    }

  if (INTEGRAL_CODE_P (code))
    {
      tree intype = TREE_TYPE (e);

      if (TREE_CODE (type) == ENUMERAL_TYPE)
	{
	  /* enum = enum, enum = int, enum = float, (enum)pointer are all
	     errors.  */
	  if (((INTEGRAL_OR_ENUMERATION_TYPE_P (intype)
		|| TREE_CODE (intype) == REAL_TYPE)
	       && ! (convtype & CONV_STATIC))
	      || TREE_CODE (intype) == POINTER_TYPE)
	    {
	      if (flags & LOOKUP_COMPLAIN)
		permerror (input_location, "conversion from %q#T to %q#T", intype, type);

	      if (!flag_permissive)
		return error_mark_node;
	    }

	  /* [expr.static.cast]

	     8. A value of integral or enumeration type can be explicitly
	     converted to an enumeration type. The value is unchanged if
	     the original value is within the range of the enumeration
	     values. Otherwise, the resulting enumeration value is
	     unspecified.  */
	  if (TREE_CODE (expr) == INTEGER_CST && !int_fits_type_p (expr, type))
	    warning (OPT_Wconversion, 
		     "the result of the conversion is unspecified because "
		     "%qE is outside the range of type %qT",
		     expr, type);
	}
      if (MAYBE_CLASS_TYPE_P (intype))
	{
	  tree rval;
	  rval = build_type_conversion (type, e);
	  if (rval)
	    return rval;
	  if (flags & LOOKUP_COMPLAIN)
	    error ("%q#T used where a %qT was expected", intype, type);
	  return error_mark_node;
	}
      if (code == BOOLEAN_TYPE)
	return cp_truthvalue_conversion (e);

      return fold_if_not_in_template (convert_to_integer (type, e));
    }
  if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type))
    return fold_if_not_in_template (cp_convert_to_pointer (type, e));
  if (code == VECTOR_TYPE)
    {
      tree in_vtype = TREE_TYPE (e);
      if (MAYBE_CLASS_TYPE_P (in_vtype))
	{
	  tree ret_val;
	  ret_val = build_type_conversion (type, e);
	  if (ret_val)
	    return ret_val;
	  if (flags & LOOKUP_COMPLAIN)
	    error ("%q#T used where a %qT was expected", in_vtype, type);
	  return error_mark_node;
	}
      return fold_if_not_in_template (convert_to_vector (type, e));
    }
  if (code == REAL_TYPE || code == COMPLEX_TYPE)
    {
      if (MAYBE_CLASS_TYPE_P (TREE_TYPE (e)))
	{
	  tree rval;
	  rval = build_type_conversion (type, e);
	  if (rval)
	    return rval;
	  else
	    if (flags & LOOKUP_COMPLAIN)
	      error ("%q#T used where a floating point value was expected",
			TREE_TYPE (e));
	}
      if (code == REAL_TYPE)
	return fold_if_not_in_template (convert_to_real (type, e));
      else if (code == COMPLEX_TYPE)
	return fold_if_not_in_template (convert_to_complex (type, e));
    }

  /* New C++ semantics:  since assignment is now based on
     memberwise copying,  if the rhs type is derived from the
     lhs type, then we may still do a conversion.  */
  if (RECORD_OR_UNION_CODE_P (code))
    {
      tree dtype = TREE_TYPE (e);
      tree ctor = NULL_TREE;

      dtype = TYPE_MAIN_VARIANT (dtype);

      /* Conversion between aggregate types.  New C++ semantics allow
	 objects of derived type to be cast to objects of base type.
	 Old semantics only allowed this between pointers.

	 There may be some ambiguity between using a constructor
	 vs. using a type conversion operator when both apply.  */

      ctor = e;

      if (abstract_virtuals_error (NULL_TREE, type))
	return error_mark_node;

      if (BRACE_ENCLOSED_INITIALIZER_P (ctor))
	ctor = perform_implicit_conversion (type, ctor, tf_warning_or_error);
      else if ((flags & LOOKUP_ONLYCONVERTING)
	       && ! (CLASS_TYPE_P (dtype) && DERIVED_FROM_P (type, dtype)))
	/* For copy-initialization, first we create a temp of the proper type
	   with a user-defined conversion sequence, then we direct-initialize
	   the target with the temp (see [dcl.init]).  */
	ctor = build_user_type_conversion (type, ctor, flags);
      else
	ctor = build_special_member_call (NULL_TREE,
					  complete_ctor_identifier,
					  build_tree_list (NULL_TREE, ctor),
					  type, flags,
                                          tf_warning_or_error);
      if (ctor)
	return build_cplus_new (type, ctor);
    }

  if (flags & LOOKUP_COMPLAIN)
    error ("conversion from %qT to non-scalar type %qT requested",
	   TREE_TYPE (expr), type);
  return error_mark_node;
}
Example #27
0
void
cxx_print_type (FILE *file, tree node, int indent)
{
  switch (TREE_CODE (node))
    {
    case TEMPLATE_TYPE_PARM:
    case TEMPLATE_TEMPLATE_PARM:
    case BOUND_TEMPLATE_TEMPLATE_PARM:
      indent_to (file, indent + 3);
      fprintf (file, "index " HOST_WIDE_INT_PRINT_DEC " level "
	       HOST_WIDE_INT_PRINT_DEC " orig_level " HOST_WIDE_INT_PRINT_DEC,
	       TEMPLATE_TYPE_IDX (node), TEMPLATE_TYPE_LEVEL (node),
	       TEMPLATE_TYPE_ORIG_LEVEL (node));
      return;

    case FUNCTION_TYPE:
    case METHOD_TYPE:
      if (TYPE_RAISES_EXCEPTIONS (node))
	print_node (file, "throws", TYPE_RAISES_EXCEPTIONS (node), indent + 4);
      return;

    case RECORD_TYPE:
    case UNION_TYPE:
      break;

    default:
      return;
    }

  if (TYPE_PTRMEMFUNC_P (node))
    print_node (file, "ptrmemfunc fn type", TYPE_PTRMEMFUNC_FN_TYPE (node),
		indent + 4);

  if (! CLASS_TYPE_P (node))
    return;

  indent_to (file, indent + 3);

  if (TYPE_NEEDS_CONSTRUCTING (node))
    fputs ( "needs-constructor", file);
  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (node))
    fputs (" needs-destructor", file);
  if (TYPE_HAS_DEFAULT_CONSTRUCTOR (node))
    fputs (" X()", file);
  if (TYPE_HAS_CONVERSION (node))
    fputs (" has-type-conversion", file);
  if (TYPE_HAS_INIT_REF (node))
    {
      if (TYPE_HAS_CONST_INIT_REF (node))
	fputs (" X(constX&)", file);
      else
	fputs (" X(X&)", file);
    }
  if (TYPE_HAS_NEW_OPERATOR (node))
    fputs (" new", file);
  if (TYPE_HAS_ARRAY_NEW_OPERATOR (node))
    fputs (" new[]", file);
  if (TYPE_GETS_DELETE (node) & 1)
    fputs (" delete", file);
  if (TYPE_GETS_DELETE (node) & 2)
    fputs (" delete[]", file);
  if (TYPE_HAS_ASSIGN_REF (node))
    fputs (" this=(X&)", file);

  if (TREE_CODE (node) == RECORD_TYPE)
    {
      if (TYPE_BINFO (node))
	fprintf (file, " n_parents=%d",
		 BINFO_N_BASE_BINFOS (TYPE_BINFO (node)));
      else
	fprintf (file, " no-binfo");

      fprintf (file, " use_template=%d", CLASSTYPE_USE_TEMPLATE (node));
      if (CLASSTYPE_INTERFACE_ONLY (node))
	fprintf (file, " interface-only");
      if (CLASSTYPE_INTERFACE_UNKNOWN (node))
	fprintf (file, " interface-unknown");
    }
}
Example #28
0
void
make_friend_class (tree type, tree friend_type, bool complain)
{
  tree classes;

  /* CLASS_TEMPLATE_DEPTH counts the number of template headers for
     the enclosing class.  FRIEND_DEPTH counts the number of template
     headers used for this friend declaration.  TEMPLATE_MEMBER_P,
     defined inside the `if' block for TYPENAME_TYPE case, is true if
     a template header in FRIEND_DEPTH is intended for DECLARATOR.
     For example, the code

       template <class T> struct A {
	 template <class U> struct B {
	   template <class V> template <class W>
	     friend class C<V>::D;
	 };
       };

     will eventually give the following results

     1. CLASS_TEMPLATE_DEPTH equals 2 (for `T' and `U').
     2. FRIEND_DEPTH equals 2 (for `V' and `W').
     3. TEMPLATE_MEMBER_P is true (for `W').

     The friend is a template friend iff FRIEND_DEPTH is nonzero.  */

  int class_template_depth = template_class_depth (type);
  int friend_depth = processing_template_decl - class_template_depth;

  if (! MAYBE_CLASS_TYPE_P (friend_type)
      && TREE_CODE (friend_type) != TEMPLATE_TEMPLATE_PARM)
    {
      /* N1791: If the type specifier in a friend declaration designates a
	 (possibly cv-qualified) class type, that class is declared as a
	 friend; otherwise, the friend declaration is ignored.

         So don't complain in C++11 mode.  */
      if (cxx_dialect < cxx11)
	pedwarn (input_location, complain ? 0 : OPT_Wpedantic,
		 "invalid type %qT declared %<friend%>", friend_type);
      return;
    }

  friend_type = cv_unqualified (friend_type);

  if (check_for_bare_parameter_packs (friend_type))
    return;

  if (friend_depth)
    {
      /* [temp.friend] Friend declarations shall not declare partial
	 specializations.  */
      if (CLASS_TYPE_P (friend_type)
	  && CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type)
	  && uses_template_parms (friend_type))
	{
	  error ("partial specialization %qT declared %<friend%>",
		 friend_type);
	  return;
	}

      if (TYPE_TEMPLATE_INFO (friend_type)
	  && !PRIMARY_TEMPLATE_P (TYPE_TI_TEMPLATE (friend_type)))
	{
	  error ("%qT is not a template", friend_type);
	  inform (location_of (friend_type), "previous declaration here");
	  if (TYPE_CLASS_SCOPE_P (friend_type)
	      && CLASSTYPE_TEMPLATE_INFO (TYPE_CONTEXT (friend_type))
	      && currently_open_class (TYPE_CONTEXT (friend_type)))
	    inform (input_location, "perhaps you need explicit template "
		    "arguments in your nested-name-specifier");
	  return;
	}
    }

  /* It makes sense for a template class to be friends with itself,
     that means the instantiations can be friendly.  Other cases are
     not so meaningful.  */
  if (!friend_depth && same_type_p (type, friend_type))
    {
      if (complain)
	warning (0, "class %qT is implicitly friends with itself",
		 type);
      return;
    }

  /* [temp.friend]

     A friend of a class or class template can be a function or
     class template, a specialization of a function template or
     class template, or an ordinary (nontemplate) function or
     class.  */
  if (!friend_depth)
    ;/* ok */
  else if (TREE_CODE (friend_type) == TYPENAME_TYPE)
    {
      if (TREE_CODE (TYPENAME_TYPE_FULLNAME (friend_type))
	  == TEMPLATE_ID_EXPR)
	{
	  /* template <class U> friend class T::X<U>; */
	  /* [temp.friend]
	     Friend declarations shall not declare partial
	     specializations.  */
	  error ("partial specialization %qT declared %<friend%>",
		 friend_type);
	  return;
	}
      else
	{
	  /* We will figure this out later.  */
	  bool template_member_p = false;

	  tree ctype = TYPE_CONTEXT (friend_type);
	  tree name = TYPE_IDENTIFIER (friend_type);
	  tree decl;

	  if (!uses_template_parms_level (ctype, class_template_depth
						 + friend_depth))
	    template_member_p = true;

	  if (class_template_depth)
	    {
	      /* We rely on tsubst_friend_class to check the
		 validity of the declaration later.  */
	      if (template_member_p)
		friend_type
		  = make_unbound_class_template (ctype,
						 name,
						 current_template_parms,
						 tf_error);
	      else
		friend_type
		  = make_typename_type (ctype, name, class_type, tf_error);
	    }
	  else
	    {
	      decl = lookup_member (ctype, name, 0, true, tf_warning_or_error);
	      if (!decl)
		{
		  error ("%qT is not a member of %qT", name, ctype);
		  return;
		}
	      if (template_member_p && !DECL_CLASS_TEMPLATE_P (decl))
		{
		  error ("%qT is not a member class template of %qT",
			 name, ctype);
		  inform (DECL_SOURCE_LOCATION (decl),
			  "%qD declared here", decl);
		  return;
		}
	      if (!template_member_p && (TREE_CODE (decl) != TYPE_DECL
					 || !CLASS_TYPE_P (TREE_TYPE (decl))))
		{
		  error ("%qT is not a nested class of %qT",
			 name, ctype);
		  inform (DECL_SOURCE_LOCATION (decl),
			  "%qD declared here", decl);
		  return;
		}

	      friend_type = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl));
	    }
	}
    }
  else if (TREE_CODE (friend_type) == TEMPLATE_TYPE_PARM)
    {
      /* template <class T> friend class T; */
      error ("template parameter type %qT declared %<friend%>", friend_type);
      return;
    }
  else if (TREE_CODE (friend_type) == TEMPLATE_TEMPLATE_PARM)
    friend_type = TYPE_NAME (friend_type);
  else if (!CLASSTYPE_TEMPLATE_INFO (friend_type))
    {
      /* template <class T> friend class A; where A is not a template */
      error ("%q#T is not a template", friend_type);
      return;
    }
  else
    /* template <class T> friend class A; where A is a template */
    friend_type = CLASSTYPE_TI_TEMPLATE (friend_type);

  if (friend_type == error_mark_node)
    return;

  /* See if it is already a friend.  */
  for (classes = CLASSTYPE_FRIEND_CLASSES (type);
       classes;
       classes = TREE_CHAIN (classes))
    {
      tree probe = TREE_VALUE (classes);

      if (TREE_CODE (friend_type) == TEMPLATE_DECL)
	{
	  if (friend_type == probe)
	    {
	      if (complain)
		warning (OPT_Wredundant_decls,
			 "%qD is already a friend of %qT", probe, type);
	      break;
	    }
	}
      else if (TREE_CODE (probe) != TEMPLATE_DECL)
	{
	  if (same_type_p (probe, friend_type))
	    {
	      if (complain)
		warning (OPT_Wredundant_decls,
			 "%qT is already a friend of %qT", probe, type);
	      break;
	    }
	}
    }

  if (!classes)
    {
      maybe_add_class_template_decl_list (type, friend_type, /*friend_p=*/1);

      CLASSTYPE_FRIEND_CLASSES (type)
	= tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
      if (TREE_CODE (friend_type) == TEMPLATE_DECL)
	friend_type = TREE_TYPE (friend_type);
      if (!uses_template_parms (type))
	CLASSTYPE_BEFRIENDING_CLASSES (friend_type)
	  = tree_cons (NULL_TREE, type,
		       CLASSTYPE_BEFRIENDING_CLASSES (friend_type));
    }
}