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

📄 decl2.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
  if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)    {      /* Must add the class instance variable up front.  */      /* Right now we just make this a pointer.  But later	 we may wish to make it special.  */      tree type = TREE_VALUE (arg_types);      int constp = 1;      if ((flag_this_is_variable > 0)	  && (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function)))	constp = 0;      if (DECL_CONSTRUCTOR_P (function))	{	  if (TYPE_USES_VIRTUAL_BASECLASSES (ctype))	    {	      DECL_CONSTRUCTOR_FOR_VBASE_P (function) = 1;	      /* In this case we need "in-charge" flag saying whether		 this constructor is responsible for initialization		 of virtual baseclasses or not.  */	      parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node);	      /* Mark the artificial `__in_chrg' parameter as "artificial".  */	      SET_DECL_ARTIFICIAL (parm);	      DECL_ARG_TYPE (parm) = integer_type_node;	      DECL_REGISTER (parm) = 1;	      TREE_CHAIN (parm) = last_function_parms;	      last_function_parms = parm;	    }	}      parm = build_decl (PARM_DECL, this_identifier, type);      /* Mark the artificial `this' parameter as "artificial".  */      SET_DECL_ARTIFICIAL (parm);      DECL_ARG_TYPE (parm) = type;      /* We can make this a register, so long as we don't	 accidentally complain if someone tries to take its address.  */      DECL_REGISTER (parm) = 1;      if (constp)	TREE_READONLY (parm) = 1;      TREE_CHAIN (parm) = last_function_parms;      last_function_parms = parm;    }  if (flags == DTOR_FLAG)    {      char *buf, *dbuf;      tree const_integer_type = build_type_variant (integer_type_node, 1, 0);      int len = sizeof (DESTRUCTOR_DECL_PREFIX)-1;      arg_types = hash_tree_chain (const_integer_type, void_list_node);      TREE_SIDE_EFFECTS (arg_types) = 1;      /* Build the overload name.  It will look like `7Example'.  */      if (IDENTIFIER_TYPE_VALUE (cname))	dbuf = build_overload_name (IDENTIFIER_TYPE_VALUE (cname), 1, 1);      else if (IDENTIFIER_LOCAL_VALUE (cname))	dbuf = build_overload_name (TREE_TYPE (IDENTIFIER_LOCAL_VALUE (cname)), 1, 1);      else      /* Using ctype fixes the `X::Y::~Y()' crash.  The cname has no type when	 it's defined out of the class definition, since poplevel_class wipes	 it out.  This used to be internal error 346.  */	dbuf = build_overload_name (ctype, 1, 1);      buf = (char *) alloca (strlen (dbuf) + sizeof (DESTRUCTOR_DECL_PREFIX));      bcopy (DESTRUCTOR_DECL_PREFIX, buf, len);      buf[len] = '\0';      strcat (buf, dbuf);      DECL_ASSEMBLER_NAME (function) = get_identifier (buf);      parm = build_decl (PARM_DECL, in_charge_identifier, const_integer_type);      /* Mark the artificial `__in_chrg' parameter as "artificial".  */      SET_DECL_ARTIFICIAL (parm);      TREE_USED (parm) = 1;#if 0      /* We don't need to mark the __in_chrg parameter itself as `const' 	 since its type is already `const int'.  In fact we MUST NOT mark 	 it as `const' cuz that will screw up the debug info (causing it 	 to say that the type of __in_chrg is `const const int').  */      TREE_READONLY (parm) = 1;#endif      DECL_ARG_TYPE (parm) = const_integer_type;      /* This is the same chain as DECL_ARGUMENTS (...).  */      TREE_CHAIN (last_function_parms) = parm;      fntype = build_cplus_method_type (qualtype, void_type_node,					arg_types);      if (raises)	{	  fntype = build_exception_variant (fntype, raises);	}      TREE_TYPE (function) = fntype;      TYPE_HAS_DESTRUCTOR (ctype) = 1;    }  else    {      tree these_arg_types;      if (DECL_CONSTRUCTOR_FOR_VBASE_P (function))	{	  arg_types = hash_tree_chain (integer_type_node,				       TREE_CHAIN (arg_types));	  fntype = build_cplus_method_type (qualtype,					    TREE_TYPE (TREE_TYPE (function)),					    arg_types);	  if (raises)	    {	      fntype = build_exception_variant (fntype, raises);	    }	  TREE_TYPE (function) = fntype;	  arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));	}      these_arg_types = arg_types;      if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)	/* Only true for static member functions.  */	these_arg_types = hash_tree_chain (build_pointer_type (qualtype),					   arg_types);      DECL_ASSEMBLER_NAME (function)	= build_decl_overload (fn_name, these_arg_types,			       1 + DECL_CONSTRUCTOR_P (function));#if 0      /* This code is going into the compiler, but currently, it makes	 libg++/src/Integer.cc not compile.  The problem is that the nice name	 winds up going into the symbol table, and conversion operations look	 for the manged name.  */      substitute_nice_name (function);#endif    }  DECL_ARGUMENTS (function) = last_function_parms;  /* First approximations.  */  DECL_CONTEXT (function) = ctype;  DECL_CLASS_CONTEXT (function) = ctype;}/* Work on the expr used by alignof (this is only called by the parser).  */treegrok_alignof (expr)     tree expr;{  tree best, t;  int bestalign;  if (TREE_CODE (expr) == COMPONENT_REF      && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))    error ("`__alignof__' applied to a bit-field");  if (TREE_CODE (expr) == INDIRECT_REF)    {      best = t = TREE_OPERAND (expr, 0);      bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));      while (TREE_CODE (t) == NOP_EXPR	     && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE)	{	  int thisalign;	  t = TREE_OPERAND (t, 0);	  thisalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));	  if (thisalign > bestalign)	    best = t, bestalign = thisalign;	}      return c_alignof (TREE_TYPE (TREE_TYPE (best)));    }  else    {      /* ANSI says arrays and fns are converted inside comma.	 But we can't convert them in build_compound_expr	 because that would break commas in lvalues.	 So do the conversion here if operand was a comma.  */      if (TREE_CODE (expr) == COMPOUND_EXPR	  && (TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE	      || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE))	expr = default_conversion (expr);      return c_alignof (TREE_TYPE (expr));    }}/* Create an ARRAY_REF, checking for the user doing things backwards   along the way.  */treegrok_array_decl (array_expr, index_exp)     tree array_expr, index_exp;{  tree type = TREE_TYPE (array_expr);  tree p1, p2, i1, i2;  if (type == error_mark_node || index_exp == error_mark_node)    return error_mark_node;  if (type == NULL_TREE)    {      /* Something has gone very wrong.  Assume we are mistakenly reducing	 an expression instead of a declaration.  */      error ("parser may be lost: is there a '{' missing somewhere?");      return NULL_TREE;    }  if (TREE_CODE (type) == OFFSET_TYPE      || TREE_CODE (type) == REFERENCE_TYPE)    type = TREE_TYPE (type);  /* If they have an `operator[]', use that.  */  if (TYPE_LANG_SPECIFIC (type)      && TYPE_OVERLOADS_ARRAY_REF (type))    return build_opfncall (ARRAY_REF, LOOKUP_NORMAL,			   array_expr, index_exp, NULL_TREE);  /* Otherwise, create an ARRAY_REF for a pointer or array type.  */  if (TREE_CODE (type) == ARRAY_TYPE)    p1 = array_expr;  else    p1 = build_expr_type_conversion (WANT_POINTER, array_expr, 0);  if (TREE_CODE (TREE_TYPE (index_exp)) == ARRAY_TYPE)    p2 = index_exp;  else    p2 = build_expr_type_conversion (WANT_POINTER, index_exp, 0);  i1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, array_expr, 0);  i2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, index_exp, 0);  if ((p1 && i2) && (i1 && p2))    error ("ambiguous conversion for array subscript");  if (p1 && i2)    array_expr = p1, index_exp = i2;  else if (i1 && p2)    array_expr = p2, index_exp = i1;  else    {      cp_error ("invalid types `%T[%T]' for array subscript",		type, TREE_TYPE (index_exp));      return error_mark_node;    }  if (array_expr == error_mark_node || index_exp == error_mark_node)    error ("ambiguous conversion for array subscript");  return build_array_ref (array_expr, index_exp);}/* Given the cast expression EXP, checking out its validity.   Either return   an error_mark_node if there was an unavoidable error, return a cast to   void for trying to delete a pointer w/ the value 0, or return the   call to delete.  If DOING_VEC is 1, we handle things differently   for doing an array delete.  If DOING_VEC is 2, they gave us the   array size as an argument to delete.   Implements ARM $5.3.4.  This is called from the parser.  */treedelete_sanity (exp, size, doing_vec, use_global_delete)     tree exp, size;     int doing_vec, use_global_delete;{  tree t = stabilize_reference (convert_from_reference (exp));  tree type = TREE_TYPE (t);  enum tree_code code = TREE_CODE (type);  /* For a regular vector delete (aka, no size argument) we will pass     this down as a NULL_TREE into build_vec_delete.  */  tree maxindex = NULL_TREE;  /* This is used for deleting arrays.  */  tree elt_size;  switch (doing_vec)    {    case 2:      maxindex = build_binary_op (MINUS_EXPR, size, integer_one_node, 1);      if (! flag_traditional)	pedwarn ("anachronistic use of array size in vector delete");      /* Fall through.  */    case 1:      elt_size = c_sizeof (type);      break;    default:      if (code != POINTER_TYPE)	{	  cp_error ("type `%#T' argument given to `delete', expected pointer",		    type);	  return error_mark_node;	}      /* Deleting a pointer with the value zero is valid and has no effect.  */      if (integer_zerop (t))	return build1 (NOP_EXPR, void_type_node, t);    }  if (code == POINTER_TYPE)    {#if 0      /* As of Valley Forge, you can delete a pointer to constant.  */      /* You can't delete a pointer to constant.  */      if (TREE_READONLY (TREE_TYPE (type)))	{	  error ("`const *' cannot be deleted");	  return error_mark_node;	}#endif      /* You also can't delete functions.  */      if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)	{	  error ("cannot delete a function");	  return error_mark_node;	}    }#if 0  /* If the type has no destructor, then we should build a regular     delete, instead of a vector delete.  Otherwise, we would end     up passing a bogus offset into __builtin_delete, which is     not expecting it.  */   if (doing_vec      && TREE_CODE (type) == POINTER_TYPE      && !TYPE_HAS_DESTRUCTOR (TREE_TYPE (type)))    {      doing_vec = 0;      use_global_delete = 1;    }#endif  if (doing_vec)    return build_vec_delete (t, maxindex, elt_size, integer_one_node,			     integer_two_node, use_global_delete);  else    {      if (IS_AGGR_TYPE (TREE_TYPE (type))	  && TYPE_GETS_REG_DELETE (TREE_TYPE (type)))	{	  /* Only do access checking here; we'll be calling op delete	     from the destructor.  */	  tree tmp = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, t,				     size_zero_node, NULL_TREE);	  if (tmp == error_mark_node)	    return error_mark_node;	}      return build_delete (type, t, integer_three_node,			   LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE,			   use_global_delete);    }}/* Sanity check: report error if this function FUNCTION is not   really a member of the class (CTYPE) it is supposed to belong to.   CNAME is the same here as it is for grokclassfn above.  */treecheck_classfn (ctype, cname, function)     tree ctype, cname, function;{  tree fn_name = DECL_NAME (function);  tree fndecl;  tree method_vec = CLASSTYPE_METHOD_VEC (ctype);  tree *methods = 0;  tree *end = 0;  if (method_vec != 0)    {      methods = &TREE_VEC_ELT (method_vec, 0);      end = TREE_VEC_END (method_vec);      /* First suss out ctors and dtors.  */      if (*methods && fn_name == DECL_NAME (*methods))	goto got_it;      while (++methods != end)	{	  if (fn_name == DECL_NAME (*methods))	    {	    got_it:	      fndecl = *methods;	      while (fndecl)		{		  if (DECL_ASSEMBLER_NAME (function) == DECL_ASSEMBLER_NAME (fndecl))		    return fndecl;#if 0		  /* This should work, but causes libg++ to fail		     make check-tFix. */		  /* We have to do more extensive argument checking here, as		     the name may have been changed by asm("new_name"). */		  if (decls_match (function, fndecl))		    return fndecl;#else		  if (DECL_NAME (function) == DECL_NAME (fndecl))		    {		      tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function));		      tree p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl));		      /* Get rid of the this parameter on functions that become			 static. */		      if (DECL_STATIC_FUNCTION_P (fndecl)			  && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)			p1 = TREE_CHAIN (p1);		      if (comptypes (TREE_TYPE (TREE_TYPE (function)),				     TREE_TYPE (TREE_TYPE (fndecl)), 1)			  && compparms (p1, p2, 3))			{			  if (DECL_STATIC_FUNCTION_P (fndecl)			      && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)			    revert_static_member_fn (&function, NULL, NULL);			  return fndecl;			}		    }#endif		  fndecl = DECL_CHAIN (fndecl);		}	      break;		/* loser */	    }	}    }  if (methods != end)    {      tree fndecl = *methods;      cp_error ("prototype for `%#D' does not match any in class `%T'",		function, ctype);      cp_error_at ("candidate%s: %+#D", DECL_CHAIN (fndecl) ? "s are" : " is",		   fndecl);      while (fndecl = DECL_CHAIN (fndecl), fndecl)	cp_error_at ("                %#D", fndecl);    }  else    {      methods = 0;      cp_error ("no `%#D' member function declared in class `%T'",		function, ctype);    }  /* If we did not find the method in the class, add it to     avoid spurious errors.  */  add_method (ctype, methods, function);  return NULL_TREE;}/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted)   of a structure component, returning a FIELD_DECL node.   QUALS is a list of type qualifiers for this decl (such as for declaring   const member functions).   This is done during the parsing of the struct declaration.   The FIELD_DECL nodes are chained together and the lot of them   are ultimately passed to `build_struct' to make the RECORD_TYPE node.

⌨️ 快捷键说明

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