FreeBSD/contrib/gcc/cp/class.c
/* Check the data members (both static and non-static), class-scoped
   typedefs, etc., appearing in the declaration of T.  Issue
   appropriate diagnostics.  Sets ACCESS_DECLS to a list (in
   declaration order) of access declarations; each TREE_VALUE in this
   list is a USING_DECL.

   In addition, set the following flags:

     EMPTY_P
       The class is empty, i.e., contains no non-static data members.

     CANT_HAVE_CONST_CTOR_P
       This class cannot have an implicitly generated copy constructor
       taking a const reference.

     CANT_HAVE_CONST_ASN_REF
       This class cannot have an implicitly generated assignment
       operator taking a const reference.

   All of these flags should be initialized before calling this
   function.

   Returns a pointer to the end of the TYPE_FIELDs chain; additional
   fields can be added by adding to this chain.  */
Check the data members (both static and non-static), class-scoped
typedefs, etc., appearing in the declaration of T.  Issue
appropriate diagnostics.  Sets ACCESS_DECLS to a list (in
declaration order) of access declarations; each TREE_VALUE in this
list is a USING_DECL.

In addition, set the following flags.

EMPTY_P
The class is empty, i.e., contains no non-static data members.

CANT_HAVE_CONST_CTOR_P
This class cannot have an implicitly generated copy constructor
taking a const reference.

CANT_HAVE_CONST_ASN_REF
This class cannot have an implicitly generated assignment
operator taking a const reference.

All of these flags should be initialized before calling this
function.

Returns a pointer to the end of the TYPE_FIELDs chain; additional
fields can be added by adding to this chain.
Check the data members ( both static and non - static ) class - scoped typedefs etc . appearing in the declaration of T . Issue appropriate diagnostics . Sets ACCESS_DECLS to a list ( in declaration order ) of access declarations ; each TREE_VALUE in this list is a USING_DECL . In addition set the following flags . EMPTY_P The class is empty i . e . contains no non - static data members . CANT_HAVE_CONST_CTOR_P This class cannot have an implicitly generated copy constructor taking a const reference . CANT_HAVE_CONST_ASN_REF This class cannot have an implicitly generated assignment operator taking a const reference . All of these flags should be initialized before calling this function . Returns a pointer to the end of the TYPE_FIELDs chain ; additional fields can be added by adding to this chain .
static void
check_field_decls (tree t, tree *access_decls,
		   int *cant_have_const_ctor_p,
		   int *no_const_asn_ref_p)
{
  tree *field;
  tree *next;
  bool has_pointers;
  int any_default_members;
  int cant_pack = 0;
  *access_decls = NULL_TREE;
  has_pointers = false;
  any_default_members = 0;
  for (field = &TYPE_FIELDS (t); *field; field = next)
    {
      tree x = *field;
      tree type = TREE_TYPE (x);
      next = &TREE_CHAIN (x);
      if (TREE_CODE (x) == USING_DECL)
	{
	  *field = TREE_CHAIN (x);
	  *access_decls = tree_cons (NULL_TREE, x, *access_decls);
	  next = field;
	  continue;
	}
      if (TREE_CODE (x) == TYPE_DECL
	  || TREE_CODE (x) == TEMPLATE_DECL)
	continue;
      DECL_CONTEXT (x) = t;
      DECL_NONLOCAL (x) = 1;
      if (TREE_CODE (t) == UNION_TYPE)
	{
	  if (TREE_CODE (x) == VAR_DECL)
	    {
	      error ("%q+D may not be static because it is a member of a union", x);
	      continue;
	    }
	  if (TREE_CODE (type) == REFERENCE_TYPE)
	    {
	      error ("%q+D may not have reference type %qT because"
		     " it is a member of a union",
		     x, type);
	      continue;
	    }
	}
      if (TREE_CODE (type) == FUNCTION_TYPE)
	{
	  error ("field %q+D invalidly declared function type", x);
	  type = build_pointer_type (type);
	  TREE_TYPE (x) = type;
	}
      else if (TREE_CODE (type) == METHOD_TYPE)
	{
	  error ("field %q+D invalidly declared method type", x);
	  type = build_pointer_type (type);
	  TREE_TYPE (x) = type;
	}
      if (type == error_mark_node)
	continue;
      if (TREE_CODE (x) == CONST_DECL || TREE_CODE (x) == VAR_DECL)
	continue;
      if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
	CLASSTYPE_NON_AGGREGATE (t) = 1;
      if (TREE_CODE (type) == REFERENCE_TYPE)
	{
	  CLASSTYPE_NON_POD_P (t) = 1;
	  if (DECL_INITIAL (x) == NULL_TREE)
	    SET_CLASSTYPE_REF_FIELDS_NEED_INIT (t, 1);
	  TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
	  if (! TYPE_HAS_CONSTRUCTOR (t) && CLASSTYPE_NON_AGGREGATE (t)
	      && extra_warnings)
	    warning (OPT_Wextra, "non-static reference %q+#D in class without a constructor", x);
	}
      type = strip_array_types (type);
      if (TYPE_PACKED (t))
	{
	  if (!pod_type_p (type) && !TYPE_PACKED (type))
	    {
	      warning
		(0,
		 "ignoring packed attribute because of unpacked non-POD field %q+#D",
		 x);
	      cant_pack = 1;
	    }
	  else if (TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT)
	    DECL_PACKED (x) = 1;
	}
      if (DECL_C_BIT_FIELD (x) && integer_zerop (DECL_INITIAL (x)))
	;
      else
	{
	  CLASSTYPE_EMPTY_P (t) = 0;
	  CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
	  if (CLASS_TYPE_P (type)
	      && CLASSTYPE_CONTAINS_EMPTY_CLASS_P (type))
	    CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 1;
	}
      if (TYPE_PTR_P (type)
	  && !TYPE_PTRFN_P (type)
	  && !TYPE_PTR_TO_MEMBER_P (type))
	has_pointers = true;
      if (CLASS_TYPE_P (type))
	{
	  if (CLASSTYPE_REF_FIELDS_NEED_INIT (type))
	    SET_CLASSTYPE_REF_FIELDS_NEED_INIT (t, 1);
	  if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (type))
	    SET_CLASSTYPE_READONLY_FIELDS_NEED_INIT (t, 1);
	}
      if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (type))
	CLASSTYPE_HAS_MUTABLE (t) = 1;
      if (! pod_type_p (type))
	CLASSTYPE_NON_POD_P (t) = 1;
      if (! zero_init_p (type))
	CLASSTYPE_NON_ZERO_INIT_P (t) = 1;
      if (CP_TYPE_CONST_P (type))
	{
	  C_TYPE_FIELDS_READONLY (t) = 1;
	  if (DECL_INITIAL (x) == NULL_TREE)
	    SET_CLASSTYPE_READONLY_FIELDS_NEED_INIT (t, 1);
	  TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
	  if (! TYPE_HAS_CONSTRUCTOR (t) && CLASSTYPE_NON_AGGREGATE (t)
	      && extra_warnings)
	    warning (OPT_Wextra, "non-static const member %q+#D in class without a constructor", x);
	}
      else if (CLASS_TYPE_P (type))
	{
	  C_TYPE_FIELDS_READONLY (t) |= C_TYPE_FIELDS_READONLY (type);
	  SET_CLASSTYPE_READONLY_FIELDS_NEED_INIT (t,
	    CLASSTYPE_READONLY_FIELDS_NEED_INIT (t)
	    | CLASSTYPE_READONLY_FIELDS_NEED_INIT (type));
	}
      if (constructor_name_p (DECL_NAME (x), t) && TYPE_HAS_CONSTRUCTOR (t))
	pedwarn ("field %q+#D with same name as class", x);
      if (DECL_C_BIT_FIELD (x))
	check_bitfield_decl (x);
      else
	check_field_decl (x, t,
			  cant_have_const_ctor_p,
			  no_const_asn_ref_p,
			  &any_default_members);
    }
  if (warn_ecpp
      && has_pointers
      && TYPE_HAS_CONSTRUCTOR (t)
      && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
      && !(TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t)))
    {
      warning (OPT_Weffc__, "%q#T has pointer data members", t);
      if (! TYPE_HAS_INIT_REF (t))
	{
	  warning (OPT_Weffc__,
		   "  but does not override %<%T(const %T&)%>", t, t);
	  if (!TYPE_HAS_ASSIGN_REF (t))
	    warning (OPT_Weffc__, "  or %<operator=(const %T&)%>", t);
	}
      else if (! TYPE_HAS_ASSIGN_REF (t))
	warning (OPT_Weffc__,
		 "  but does not override %<operator=(const %T&)%>", t);
    }
  if (cant_pack)
    TYPE_PACKED (t) = 0;
  finish_struct_anon (t);
  *access_decls = nreverse (*access_decls);
}
static void check_field_decls ( tree t , tree * access_decls , int * cant_have_const_ctor_p , int * no_const_asn_ref_p ) { tree * field ; tree * next ; bool has_pointers ; int any_default_members ; int cant_pack = 0 ; * access_decls = NULL_TREE ; has_pointers = false ; any_default_members = 0 ; for ( field = & TYPE_FIELDS ( t ) ; * field ; field = next ) { tree x = * field ; tree type = TREE_TYPE ( x ) ; next = & TREE_CHAIN ( x ) ; if ( TREE_CODE ( x ) == USING_DECL ) { * field = TREE_CHAIN ( x ) ; * access_decls = tree_cons ( NULL_TREE , x , * access_decls ) ; next = field ; continue ; } if ( TREE_CODE ( x ) == TYPE_DECL || TREE_CODE ( x ) == TEMPLATE_DECL ) continue ; DECL_CONTEXT ( x ) = t ; DECL_NONLOCAL ( x ) = 1 ; if ( TREE_CODE ( t ) == UNION_TYPE ) { if ( TREE_CODE ( x ) == VAR_DECL ) { error ( " " , x ) ; continue ; } if ( TREE_CODE ( type ) == REFERENCE_TYPE ) { error ( " " " " , x , type ) ; continue ; } } if ( TREE_CODE ( type ) == FUNCTION_TYPE ) { error ( " " , x ) ; type = build_pointer_type ( type ) ; TREE_TYPE ( x ) = type ; } else if ( TREE_CODE ( type ) == METHOD_TYPE ) { error ( " " , x ) ; type = build_pointer_type ( type ) ; TREE_TYPE ( x ) = type ; } if ( type == error_mark_node ) continue ; if ( TREE_CODE ( x ) == CONST_DECL || TREE_CODE ( x ) == VAR_DECL ) continue ; if ( TREE_PRIVATE ( x ) || TREE_PROTECTED ( x ) ) CLASSTYPE_NON_AGGREGATE ( t ) = 1 ; if ( TREE_CODE ( type ) == REFERENCE_TYPE ) { CLASSTYPE_NON_POD_P ( t ) = 1 ; if ( DECL_INITIAL ( x ) == NULL_TREE ) SET_CLASSTYPE_REF_FIELDS_NEED_INIT ( t , 1 ) ; TYPE_HAS_COMPLEX_ASSIGN_REF ( t ) = 1 ; if ( ! TYPE_HAS_CONSTRUCTOR ( t ) && CLASSTYPE_NON_AGGREGATE ( t ) && extra_warnings ) warning ( OPT_Wextra , " " , x ) ; } type = strip_array_types ( type ) ; if ( TYPE_PACKED ( t ) ) { if ( ! pod_type_p ( type ) && ! TYPE_PACKED ( type ) ) { warning ( 0 , " " , x ) ; cant_pack = 1 ; } else if ( TYPE_ALIGN ( TREE_TYPE ( x ) ) > BITS_PER_UNIT ) DECL_PACKED ( x ) = 1 ; } if ( DECL_C_BIT_FIELD ( x ) && integer_zerop ( DECL_INITIAL ( x ) ) ) ; else { CLASSTYPE_EMPTY_P ( t ) = 0 ; CLASSTYPE_NEARLY_EMPTY_P ( t ) = 0 ; if ( CLASS_TYPE_P ( type ) && CLASSTYPE_CONTAINS_EMPTY_CLASS_P ( type ) ) CLASSTYPE_CONTAINS_EMPTY_CLASS_P ( t ) = 1 ; } if ( TYPE_PTR_P ( type ) && ! TYPE_PTRFN_P ( type ) && ! TYPE_PTR_TO_MEMBER_P ( type ) ) has_pointers = true ; if ( CLASS_TYPE_P ( type ) ) { if ( CLASSTYPE_REF_FIELDS_NEED_INIT ( type ) ) SET_CLASSTYPE_REF_FIELDS_NEED_INIT ( t , 1 ) ; if ( CLASSTYPE_READONLY_FIELDS_NEED_INIT ( type ) ) SET_CLASSTYPE_READONLY_FIELDS_NEED_INIT ( t , 1 ) ; } if ( DECL_MUTABLE_P ( x ) || TYPE_HAS_MUTABLE_P ( type ) ) CLASSTYPE_HAS_MUTABLE ( t ) = 1 ; if ( ! pod_type_p ( type ) ) CLASSTYPE_NON_POD_P ( t ) = 1 ; if ( ! zero_init_p ( type ) ) CLASSTYPE_NON_ZERO_INIT_P ( t ) = 1 ; if ( CP_TYPE_CONST_P ( type ) ) { C_TYPE_FIELDS_READONLY ( t ) = 1 ; if ( DECL_INITIAL ( x ) == NULL_TREE ) SET_CLASSTYPE_READONLY_FIELDS_NEED_INIT ( t , 1 ) ; TYPE_HAS_COMPLEX_ASSIGN_REF ( t ) = 1 ; if ( ! TYPE_HAS_CONSTRUCTOR ( t ) && CLASSTYPE_NON_AGGREGATE ( t ) && extra_warnings ) warning ( OPT_Wextra , " " , x ) ; } else if ( CLASS_TYPE_P ( type ) ) { C_TYPE_FIELDS_READONLY ( t ) |= C_TYPE_FIELDS_READONLY ( type ) ; SET_CLASSTYPE_READONLY_FIELDS_NEED_INIT ( t , CLASSTYPE_READONLY_FIELDS_NEED_INIT ( t ) | CLASSTYPE_READONLY_FIELDS_NEED_INIT ( type ) ) ; } if ( constructor_name_p ( DECL_NAME ( x ) , t ) && TYPE_HAS_CONSTRUCTOR ( t ) ) pedwarn ( " " , x ) ; if ( DECL_C_BIT_FIELD ( x ) ) check_bitfield_decl ( x ) ; else check_field_decl ( x , t , cant_have_const_ctor_p , no_const_asn_ref_p , & any_default_members ) ; } if ( warn_ecpp && has_pointers && TYPE_HAS_CONSTRUCTOR ( t ) && TYPE_HAS_NONTRIVIAL_DESTRUCTOR ( t ) && ! ( TYPE_HAS_INIT_REF ( t ) && TYPE_HAS_ASSIGN_REF ( t ) ) ) { warning ( OPT_Weffc__ , " " , t ) ; if ( ! TYPE_HAS_INIT_REF ( t ) ) { warning ( OPT_Weffc__ , " " , t , t ) ; if ( ! TYPE_HAS_ASSIGN_REF ( t ) ) warning ( OPT_Weffc__ , " " , t ) ; } else if ( ! TYPE_HAS_ASSIGN_REF ( t ) ) warning ( OPT_Weffc__ , " " , t ) ; } if ( cant_pack ) TYPE_PACKED ( t ) = 0 ; finish_struct_anon ( t ) ; * access_decls = nreverse ( * access_decls ) ; }
Check the data members (both static and non-static), class-scoped
typedefs, etc., appearing in the declaration of T.  Issue
appropriate diagnostics.
Check the data members ( both static and non - static ) class - scoped typedefs etc . appearing in the declaration of T . Issue appropriate diagnostics .
/* Assume there are no access declarations.  */ /* Assume this class has no pointer members.  */ /* Assume none of the members of this class have default
     initializations.  */ /* Prune the access declaration from the list of fields.  */ /* Save the access declarations for our caller.  */ /* Since we've reset *FIELD there's no reason to skip to the
	     next field.  */ /* If we've gotten this far, it's a data member, possibly static,
	 or an enumerator.  */ /* When this goes into scope, it will be a non-local reference.  */ /* [class.union]

	     If a union contains a static data member, or a member of
	     reference type, the program is ill-formed.  */ /* Perform error checking that did not get done in
	 grokdeclarator.  */ /* Now it can only be a FIELD_DECL.  */ /* If this is of reference type, check if it needs an init.
	 Also do a little ANSI jig if necessary.  */ /* ARM $12.6.2: [A member initializer list] (or, for an
	     aggregate, initialization by a brace-enclosed list) is the
	     only way to initialize nonstatic const and reference
	     members.  */ /* We don't treat zero-width bitfields as making a class
	   non-empty.  */ /* The class is non-empty.  */ /* The class is not even nearly empty.  */ /* If one of the data members contains an empty class,
	     so does T.  */ /* This is used by -Weffc++ (see below). Warn only for pointers
	 to members which might hold dynamic memory. So do not warn
	 for pointers to functions or pointers to members.  */ /* DR 148 now allows pointers to members (which are POD themselves),
	   to be allowed in POD structs.  */ /* If any field is const, the structure type is pseudo-const.  */ /* ARM $12.6.2: [A member initializer list] (or, for an
	     aggregate, initialization by a brace-enclosed list) is the
	     only way to initialize nonstatic const and reference
	     members.  */ /* A field that is pseudo-const makes the structure likewise.  */ /* Core issue 80: A nonstatic data member is required to have a
	 different name from the class iff the class has a
	 user-defined constructor.  */ /* We set DECL_C_BIT_FIELD in grokbitfield.
	 If the type and width are valid, we'll also set DECL_BIT_FIELD.  */ /* Effective C++ rule 11: if a class has dynamic memory held by pointers,
     it should also define a copy constructor and an assignment operator to
     implement the correct copy semantic (deep vs shallow, etc.). As it is
     not feasible to check whether the constructors do allocate dynamic memory
     and store it within members, we approximate the warning like this:

     -- Warn only if there are members which are pointers
     -- Warn only if there is a non-trivial constructor (otherwise,
	there cannot be memory allocated).
     -- Warn only if there is a non-trivial destructor. We assume that the
	user at least implemented the cleanup correctly, and a destructor
	is needed to free dynamic memory.

     This seems enough for practical purposes.  */ /* If any of the fields couldn't be packed, unset TYPE_PACKED.  */ /* Check anonymous struct/anonymous union fields.  */ /* We've built up the list of access declarations in reverse order.
     Fix that now.  */