FreeBSD/contrib/gcc/cp/typeck.c
/* This function is called by the parser to process a class member
   access expression of the form OBJECT.NAME.  NAME is a node used by
   the parser to represent a name; it is not yet a DECL.  It may,
   however, be a BASELINK where the BASELINK_FUNCTIONS is a
   TEMPLATE_ID_EXPR.  Templates must be looked up by the parser, and
   there is no reason to do the lookup twice, so the parser keeps the
   BASELINK.  TEMPLATE_P is true iff NAME was explicitly declared to
   be a template via the use of the "A::template B" syntax.  */
This function is called by the parser to process a class member
access expression of the form OBJECT.NAME.  NAME is a node used by
the parser to represent a name; it is not yet a DECL.  It may,
however, be a BASELINK where the BASELINK_FUNCTIONS is a
TEMPLATE_ID_EXPR.  Templates must be looked up by the parser, and
there is no reason to do the lookup twice, so the parser keeps the
BASELINK.  TEMPLATE_P is true iff NAME was explicitly declared to
be a template via the use of the "A::template B" syntax.
This function is called by the parser to process a class member access expression of the form OBJECT . NAME . NAME is a node used by the parser to represent a name ; it is not yet a DECL . It may however be a BASELINK where the BASELINK_FUNCTIONS is a TEMPLATE_ID_EXPR . Templates must be looked up by the parser and there is no reason to do the lookup twice so the parser keeps the BASELINK . TEMPLATE_P is true iff NAME was explicitly declared to be a template via the use of the " A :: template B " syntax .
tree
finish_class_member_access_expr (tree object, tree name, bool template_p)
{
  tree expr;
  tree object_type;
  tree member;
  tree access_path = NULL_TREE;
  tree orig_object = object;
  tree orig_name = name;
  if (object == error_mark_node || name == error_mark_node)
    return error_mark_node;
  if (!objc_is_public (object, name))
    return error_mark_node;
  object_type = TREE_TYPE (object);
  if (processing_template_decl)
    {
      if (
	  dependent_type_p (object_type)
	  || TREE_CODE (object) == IDENTIFIER_NODE
	  || (TREE_CODE (name) == TEMPLATE_ID_EXPR
	      && dependent_template_id_p (TREE_OPERAND (name, 0),
					  TREE_OPERAND (name, 1)))
	  || (TREE_CODE (name) == SCOPE_REF
	      && TYPE_P (TREE_OPERAND (name, 0))
	      && dependent_type_p (TREE_OPERAND (name, 0))))
	return build_min_nt (COMPONENT_REF, object, name, NULL_TREE);
      object = build_non_dependent_expr (object);
    }
  if (!currently_open_class (object_type)
      && !complete_type_or_else (object_type, object))
    return error_mark_node;
  if (!CLASS_TYPE_P (object_type))
    {
      error ("request for member %qD in %qE, which is of non-class type %qT",
	     name, object, object_type);
      return error_mark_node;
    }
  if (BASELINK_P (name))
    member = name;
  else
    {
      bool is_template_id = false;
      tree template_args = NULL_TREE;
      tree scope;
      if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
	{
	  is_template_id = true;
	  template_args = TREE_OPERAND (name, 1);
	  name = TREE_OPERAND (name, 0);
	  if (TREE_CODE (name) == OVERLOAD)
	    name = DECL_NAME (get_first_fn (name));
	  else if (DECL_P (name))
	    name = DECL_NAME (name);
	}
      if (TREE_CODE (name) == SCOPE_REF)
	{
	  scope = TREE_OPERAND (name, 0);
	  name = TREE_OPERAND (name, 1);
	  if (TREE_CODE (scope) == NAMESPACE_DECL)
	    {
	      error ("%<%D::%D%> is not a member of %qT",
		     scope, name, object_type);
	      return error_mark_node;
	    }
	  gcc_assert (CLASS_TYPE_P (scope));
	  gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE
		      || TREE_CODE (name) == BIT_NOT_EXPR);
	  access_path = lookup_base (object_type, scope, ba_check, NULL);
	  if (access_path == error_mark_node)
	    return error_mark_node;
	  if (!access_path)
	    {
	      error ("%qT is not a base of %qT", scope, object_type);
	      return error_mark_node;
	    }
	}
      else
	{
	  scope = NULL_TREE;
	  access_path = object_type;
	}
      if (TREE_CODE (name) == BIT_NOT_EXPR)
	member = lookup_destructor (object, scope, name);
      else
	{
	  member = lookup_member (access_path, name, 1,
				  false);
	  if (member == NULL_TREE)
	    {
	      error ("%qD has no member named %qE", object_type, name);
	      return error_mark_node;
	    }
	  if (member == error_mark_node)
	    return error_mark_node;
	}
      if (is_template_id)
	{
	  tree template = member;
	  if (BASELINK_P (template))
	    template = lookup_template_function (template, template_args);
	  else
	    {
	      error ("%qD is not a member template function", name);
	      return error_mark_node;
	    }
	}
    }
  if (TREE_DEPRECATED (member))
    warn_deprecated_use (member);
  if (template_p)
    check_template_keyword (member);
  expr = build_class_member_access_expr (object, member, access_path,
					 false);
  if (processing_template_decl && expr != error_mark_node)
    {
      if (BASELINK_P (member))
	{
	  if (TREE_CODE (orig_name) == SCOPE_REF)
	    BASELINK_QUALIFIED_P (member) = 1;
	  orig_name = member;
	}
      return build_min_non_dep (COMPONENT_REF, expr,
				orig_object, orig_name,
				NULL_TREE);
    }
  return expr;
}
tree finish_class_member_access_expr ( tree object , tree name , bool template_p ) { tree expr ; tree object_type ; tree member ; tree access_path = NULL_TREE ; tree orig_object = object ; tree orig_name = name ; if ( object == error_mark_node || name == error_mark_node ) return error_mark_node ; if ( ! objc_is_public ( object , name ) ) return error_mark_node ; object_type = TREE_TYPE ( object ) ; if ( processing_template_decl ) { if ( dependent_type_p ( object_type ) || TREE_CODE ( object ) == IDENTIFIER_NODE || ( TREE_CODE ( name ) == TEMPLATE_ID_EXPR && dependent_template_id_p ( TREE_OPERAND ( name , 0 ) , TREE_OPERAND ( name , 1 ) ) ) || ( TREE_CODE ( name ) == SCOPE_REF && TYPE_P ( TREE_OPERAND ( name , 0 ) ) && dependent_type_p ( TREE_OPERAND ( name , 0 ) ) ) ) return build_min_nt ( COMPONENT_REF , object , name , NULL_TREE ) ; object = build_non_dependent_expr ( object ) ; } if ( ! currently_open_class ( object_type ) && ! complete_type_or_else ( object_type , object ) ) return error_mark_node ; if ( ! CLASS_TYPE_P ( object_type ) ) { error ( " " , name , object , object_type ) ; return error_mark_node ; } if ( BASELINK_P ( name ) ) member = name ; else { bool is_template_id = false ; tree template_args = NULL_TREE ; tree scope ; if ( TREE_CODE ( name ) == TEMPLATE_ID_EXPR ) { is_template_id = true ; template_args = TREE_OPERAND ( name , 1 ) ; name = TREE_OPERAND ( name , 0 ) ; if ( TREE_CODE ( name ) == OVERLOAD ) name = DECL_NAME ( get_first_fn ( name ) ) ; else if ( DECL_P ( name ) ) name = DECL_NAME ( name ) ; } if ( TREE_CODE ( name ) == SCOPE_REF ) { scope = TREE_OPERAND ( name , 0 ) ; name = TREE_OPERAND ( name , 1 ) ; if ( TREE_CODE ( scope ) == NAMESPACE_DECL ) { error ( " " , scope , name , object_type ) ; return error_mark_node ; } gcc_assert ( CLASS_TYPE_P ( scope ) ) ; gcc_assert ( TREE_CODE ( name ) == IDENTIFIER_NODE || TREE_CODE ( name ) == BIT_NOT_EXPR ) ; access_path = lookup_base ( object_type , scope , ba_check , NULL ) ; if ( access_path == error_mark_node ) return error_mark_node ; if ( ! access_path ) { error ( " " , scope , object_type ) ; return error_mark_node ; } } else { scope = NULL_TREE ; access_path = object_type ; } if ( TREE_CODE ( name ) == BIT_NOT_EXPR ) member = lookup_destructor ( object , scope , name ) ; else { member = lookup_member ( access_path , name , 1 , false ) ; if ( member == NULL_TREE ) { error ( " " , object_type , name ) ; return error_mark_node ; } if ( member == error_mark_node ) return error_mark_node ; } if ( is_template_id ) { tree template = member ; if ( BASELINK_P ( template ) ) template = lookup_template_function ( template , template_args ) ; else { error ( " " , name ) ; return error_mark_node ; } } } if ( TREE_DEPRECATED ( member ) ) warn_deprecated_use ( member ) ; if ( template_p ) check_template_keyword ( member ) ; expr = build_class_member_access_expr ( object , member , access_path , false ) ; if ( processing_template_decl && expr != error_mark_node ) { if ( BASELINK_P ( member ) ) { if ( TREE_CODE ( orig_name ) == SCOPE_REF ) BASELINK_QUALIFIED_P ( member ) = 1 ; orig_name = member ; } return build_min_non_dep ( COMPONENT_REF , expr , orig_object , orig_name , NULL_TREE ) ; } return expr ; }
This function is called by the parser to process a class member
access expression of the form OBJECT.NAME.
This function is called by the parser to process a class member access expression of the form OBJECT . NAME .
/* If OBJECT is an ObjC class instance, we must obey ObjC access rules.  */ /* If OBJECT_TYPE is dependent, so is OBJECT.NAME.  */ /* If NAME is just an IDENTIFIER_NODE, then the expression
	     is dependent.  */ /* If NAME is "f<args>", where either 'f' or 'args' is
	     dependent, then the expression is dependent.  */ /* If NAME is "T::X" where "T" is dependent, then the
	     expression is dependent.  */ /* [expr.ref]

     The type of the first expression shall be "class object" (of a
     complete type).  */ /* A member function that has already been looked up.  */ /* A qualified name.  The qualifying class or namespace `S'
	     has already been looked up; it is either a TYPE or a
	     NAMESPACE_DECL.  */ /* If SCOPE is a namespace, then the qualified name does not
	     name a member of OBJECT_TYPE.  */ /* Find the base of OBJECT_TYPE corresponding to SCOPE.  */ /* Look up the member.  */ /*protect=*/ /*want_type=*/ /*preserve_reference=*/