⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cp-decl2.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
		&& TREE_CODE (TREE_VALUE (parms)) == TREE_LIST)	      TREE_VALUE (parms)		= grokdeclarator (TREE_VALUE (TREE_VALUE (parms)),				  TREE_PURPOSE (TREE_VALUE (parms)),				  TYPENAME, 0, NULL_TREE);	    if (parms)	      {		if (TREE_VALUE (parms) != void_type_node)		  error ("operator <typename> requires empty parameter list");		else		  /* Canonicalize parameter lists.  */		  TREE_OPERAND (tmp, 1) = void_list_node;	      }	    last = grokdeclarator (TREE_OPERAND (decl, 0),				   TREE_TYPE (decl),				   TYPENAME, 0, NULL_TREE);	    TREE_OPERAND (tmp, 0) = build_typename_overload (last);	    TREE_TYPE (TREE_OPERAND (tmp, 0)) = last;	    return tmp;	  }	case INDIRECT_REF:	case ADDR_EXPR:	case ARRAY_REF:	  break;	case SCOPE_REF:	  /* This is legal when declaring a conversion to	     something of type pointer-to-member.  */	  if (TREE_CODE (TREE_OPERAND (tmp, 1)) == INDIRECT_REF)	    {	      tmp = TREE_OPERAND (tmp, 1);	    }	  else	    {#if 0	      /* We may need to do this if grokdeclarator cannot handle this.  */	      error ("type `member of class %s' invalid return type",		     TYPE_NAME_STRING (TREE_OPERAND (tmp, 0)));	      TREE_OPERAND (tmp, 1) = build_parse_node (INDIRECT_REF, TREE_OPERAND (tmp, 1));#endif	      tmp = TREE_OPERAND (tmp, 1);	    }	  break;	default:	  my_friendly_assert (0, 196);	}      last = tmp;      tmp = TREE_OPERAND (tmp, 0);    }  if (call_required)    error ("operator <typename> construct requires parameter list");  last = grokdeclarator (TREE_OPERAND (decl, 0),			 TREE_TYPE (decl),			 TYPENAME, 0, NULL_TREE);  tmp = build_parse_node (CALL_EXPR, build_typename_overload (last),			  void_list_node, NULL_TREE);  TREE_TYPE (TREE_OPERAND (tmp, 0)) = last;  return tmp;}/* When a function is declared with an initializer,   do the right thing.  Currently, there are two possibilities:   class B   {    public:     // initialization possibility #1.     virtual void f () = 0;     int g ();   };      class D1 : B   {    public:     int d1;     // error, no f ();   };      class D2 : B   {    public:     int d2;     void f ();   };      class D3 : B   {    public:     int d3;     // initialization possibility #2     void f () = B::f;   };*/static voidgrok_function_init (decl, init)     tree decl;     tree init;{  /* An initializer for a function tells how this function should     be inherited.  */  tree type = TREE_TYPE (decl);  extern tree abort_fndecl;  if (TREE_CODE (type) == FUNCTION_TYPE)    error_with_decl (decl, "initializer specified for non-member function `%s'");  else if (DECL_VINDEX (decl) == NULL_TREE)    error_with_decl (decl, "initializer specified for non-virtual method `%s'");  else if (integer_zerop (init))    {      /* Mark this function as being "defined".  */      DECL_INITIAL (decl) = error_mark_node;      /* Give this node rtl from `abort'.  */      DECL_RTL (decl) = DECL_RTL (abort_fndecl);      DECL_ABSTRACT_VIRTUAL_P (decl) = 1;    }  else if (TREE_CODE (init) == OFFSET_REF	   && TREE_OPERAND (init, 0) == NULL_TREE	   && TREE_CODE (TREE_TYPE (init)) == METHOD_TYPE)    {      tree basetype = DECL_CLASS_CONTEXT (init);      tree basefn = TREE_OPERAND (init, 1);      if (TREE_CODE (basefn) != FUNCTION_DECL)	error_with_decl (decl, "non-method initializer invalid for method `%s'");      else if (! BINFO_OFFSET_ZEROP (TYPE_BINFO (DECL_CLASS_CONTEXT (basefn))))	sorry ("base member function from other than first base class");      else	{	  tree binfo = get_binfo (basetype, TYPE_METHOD_BASETYPE (type), 1);	  if (binfo == error_mark_node)	    ;	  else if (binfo == 0)	    error_not_base_type (TYPE_METHOD_BASETYPE (TREE_TYPE (init)),				 TYPE_METHOD_BASETYPE (type));	  else	    {	      /* Mark this function as being defined,		 and give it new rtl.  */	      DECL_INITIAL (decl) = error_mark_node;	      DECL_RTL (decl) = DECL_RTL (basefn);	    }	}    }  else    error_with_decl (decl, "invalid initializer for virtual method `%s'");}/* When we get a declaration of the form   type cname::fname ...   the node for `cname::fname' gets built here in a special way.   Namely, we push into `cname's scope.  When this declaration is   processed, we pop back out.  */treebuild_push_scope (cname, name)     tree cname;     tree name;{  extern int current_class_depth;  tree ctype, rval;  if (cname == error_mark_node)    return error_mark_node;  ctype = IDENTIFIER_TYPE_VALUE (cname);  if (ctype == NULL_TREE || ! IS_AGGR_TYPE (ctype))    {      error ("`%s' not defined as aggregate type", IDENTIFIER_POINTER (cname));      return name;    }  rval = build_parse_node (SCOPE_REF, cname, name);  /* Don't need to push the scope here, but we do need to return     a SCOPE_REF for something like     class foo { typedef int bar (foo::*foo_fn)(void); };  */  if (ctype == current_class_type)    return rval;  pushclass (ctype, 3);  TREE_COMPLEXITY (rval) = current_class_depth;  return rval;}void cplus_decl_attributes (decl, attributes)     tree decl, attributes;{  if (decl)    decl_attributes (decl, attributes);}/* CONSTRUCTOR_NAME:   Return the name for the constructor (or destructor) for the specified   class.  Argument can be RECORD_TYPE, TYPE_DECL, or IDENTIFIER_NODE.  */treeconstructor_name (thing)     tree thing;{  tree t;  if (TREE_CODE (thing) == UNINSTANTIATED_P_TYPE)    return DECL_NAME (UPT_TEMPLATE (thing));  if (TREE_CODE (thing) == RECORD_TYPE || TREE_CODE (thing) == UNION_TYPE)    thing = TYPE_NAME (thing);  if (TREE_CODE (thing) == TYPE_DECL      || (TREE_CODE (thing) == TEMPLATE_DECL	  && DECL_TEMPLATE_IS_CLASS (thing)))    thing = DECL_NAME (thing);  my_friendly_assert (TREE_CODE (thing) == IDENTIFIER_NODE, 197);  t = IDENTIFIER_TEMPLATE (thing);  if (!t)    return thing;  t = TREE_PURPOSE (t);  return DECL_NAME (t);}/* Cache the value of this class's main virtual function table pointer   in a register variable.  This will save one indirection if a   more than one virtual function call is made this function.  */voidsetup_vtbl_ptr (){  extern rtx base_init_insns;  if (base_init_insns == 0      && DECL_CONSTRUCTOR_P (current_function_decl))    emit_base_init (current_class_type, 0);#if 0  /* This has something a little wrong with it.     On a sun4, code like:        be L6        ld [%i0],%o1     is generated, when the below is used when -O4 is given.  The delay     slot it filled with an instruction that is safe, when this isn't     used, like in:        be L6        sethi %hi(LC1),%o0        ld [%i0],%o1     on code like:        struct A {          virtual void print() { printf("xxx"); }          void f();        };        void A::f() {          if (this) {            print();          } else {            printf("0");          }        }     And that is why this is disabled for now. (mrs)  */  if ((flag_this_is_variable & 1) == 0      && optimize      && current_class_type      && CLASSTYPE_VSIZE (current_class_type)      && ! DECL_STATIC_FUNCTION_P (current_function_decl))    {      tree vfield = build_vfield_ref (C_C_D, current_class_type);      current_vtable_decl = CLASSTYPE_VTBL_PTR (current_class_type);      DECL_RTL (current_vtable_decl) = 0;      DECL_INITIAL (current_vtable_decl) = error_mark_node;      /* Have to cast the initializer, since it may have come from a	 more base class then we ascribe CURRENT_VTABLE_DECL to be.  */      finish_decl (current_vtable_decl, convert_force (TREE_TYPE (current_vtable_decl), vfield), 0, 0);      current_vtable_decl = build_indirect_ref (current_vtable_decl, 0);    }  else#endif    current_vtable_decl = NULL_TREE;}/* Record the existence of an addressable inline function.  */voidmark_inline_for_output (decl)     tree decl;{  if (DECL_PENDING_INLINE_INFO (decl) != 0      && ! DECL_PENDING_INLINE_INFO (decl)->deja_vu)    {      struct pending_inline *t = pending_inlines;      my_friendly_assert (DECL_SAVED_INSNS (decl) == 0, 198);      while (t)	{	  if (t == DECL_PENDING_INLINE_INFO (decl))	    break;	  t = t->next;	}      if (t == 0)	{	  t = DECL_PENDING_INLINE_INFO (decl);	  t->next = pending_inlines;	  pending_inlines = t;	}      DECL_PENDING_INLINE_INFO (decl) = 0;    }  pending_addressable_inlines = perm_tree_cons (NULL_TREE, decl,						pending_addressable_inlines);}voidclear_temp_name (){  temp_name_counter = 0;}/* Hand off a unique name which can be used for variable we don't really   want to know about anyway, for example, the anonymous variables which   are needed to make references work.  Declare this thing so we can use it.   The variable created will be of type TYPE.   STATICP is nonzero if this variable should be static.  */treeget_temp_name (type, staticp)     tree type;     int staticp;{  char buf[sizeof (AUTO_TEMP_FORMAT) + 20];  tree decl;  int toplev = global_bindings_p ();  push_obstacks_nochange ();  if (toplev || staticp)    {      end_temporary_allocation ();      sprintf (buf, AUTO_TEMP_FORMAT, global_temp_name_counter++);      decl = pushdecl_top_level (build_decl (VAR_DECL, get_identifier (buf), type));    }  else    {      sprintf (buf, AUTO_TEMP_FORMAT, temp_name_counter++);      decl = pushdecl (build_decl (VAR_DECL, get_identifier (buf), type));    }  TREE_USED (decl) = 1;  TREE_STATIC (decl) = staticp;  /* If this is a local variable, then lay out its rtl now.     Otherwise, callers of this function are responsible for dealing     with this variable's rtl.  */  if (! toplev)    {      expand_decl (decl);      expand_decl_init (decl);    }  pop_obstacks ();  return decl;}/* Get a variable which we can use for multiple assignments.   It is not entered into current_binding_level, because   that breaks things when it comes time to do final cleanups   (which take place "outside" the binding contour of the function).  */treeget_temp_regvar (type, init)     tree type, init;{  static char buf[sizeof (AUTO_TEMP_FORMAT) + 20] = { '_' };  tree decl;  sprintf (buf+1, AUTO_TEMP_FORMAT, temp_name_counter++);  decl = build_decl (VAR_DECL, get_identifier (buf), type);  TREE_USED (decl) = 1;  DECL_REGISTER (decl) = 1;  if (init)    store_init_value (decl, init);  /* We can expand these without fear, since they cannot need     constructors or destructors.  */  expand_decl (decl);  expand_decl_init (decl);  if (type_needs_gc_entry (type))    DECL_GC_OFFSET (decl) = size_int (++current_function_obstack_index);  return decl;}/* Make the macro TEMP_NAME_P available to units which do not   include c-tree.h.  */inttemp_name_p (decl)     tree decl;{  return TEMP_NAME_P (decl);}/* Finish off the processing of a UNION_TYPE structure.   If there are static members, then all members are   static, and must be laid out together.  If the   union is an anonymous union, we arrange for that   as well.  PUBLIC_P is nonzero if this union is   not declared static.  */voidfinish_anon_union (anon_union_decl)     tree anon_union_decl;{  tree type = TREE_TYPE (anon_union_decl);  tree field, main_decl = NULL_TREE;  tree elems = NULL_TREE;  int public_p = TREE_PUBLIC (anon_union_decl);  int static_p = TREE_STATIC (anon_union_decl);  int external_p = DECL_EXTERNAL (anon_union_decl);  if ((field = TYPE_FIELDS (type)) == NULL_TREE)    return;  if (public_p && (static_p || external_p))    error ("optimizer cannot handle global anonymous unions");  while (field)    {      tree decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));      /* tell `pushdecl' that this is not tentative.  */      DECL_INITIAL (decl) = error_mark_node;      TREE_PUBLIC (decl) = public_p;      TREE_STATIC (decl) = static_p;      DECL_EXTERNAL (decl) = external_p;      decl = pushdecl (decl);      /* Only write out one anon union element--choose the one that	 can hold them all.  */      if (main_decl == NULL_TREE

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -