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

📄 cp-type2.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Report error messages, build initializers, and perform   some front-end optimizations for C++ compiler.   Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.   Hacked by Michael Tiemann (tiemann@cygnus.com)This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  *//* This file is part of the C++ front end.   It contains routines to build C++ expressions given their operands,   including computing the types of the result, C and C++ specific error   checks, and some optimization.   There are also routines to build RETURN_STMT nodes and CASE_STMT nodes,   and to process initializations in declarations (since they work   like a strange sort of assignment).  */#include "config.h"#include <stdio.h>#include "tree.h"#include "cp-tree.h"#include "flags.h"static tree process_init_constructor ();tree digest_init ();void incomplete_type_error ();void readonly_warning_or_error ();extern tree convert_for_initialization ();extern int errorcount;extern int sorrycount;/* Print an error message stemming from an attempt to use   BASETYPE as a base class for TYPE.  */treeerror_not_base_type (basetype, type)     tree basetype, type;{  tree name1;  tree name2;  if (TREE_CODE (basetype) == FUNCTION_DECL)    basetype = DECL_CLASS_CONTEXT (basetype);  name1 = TYPE_NAME (basetype);  name2 = TYPE_NAME (type);  if (TREE_CODE (name1) == TYPE_DECL)    name1 = DECL_NAME (name1);  if (TREE_CODE (name2) == TYPE_DECL)    name2 = DECL_NAME (name2);  error ("type `%s' is not a base type for type `%s'",	 IDENTIFIER_POINTER (name1), IDENTIFIER_POINTER (name2));  return error_mark_node;}treebinfo_or_else (parent_or_type, type)     tree parent_or_type, type;{  tree binfo;  if (TYPE_MAIN_VARIANT (parent_or_type) == TYPE_MAIN_VARIANT (type))    return parent_or_type;  if (binfo = get_binfo (parent_or_type, TYPE_MAIN_VARIANT (type), 0))    {      if (binfo == error_mark_node)	return NULL_TREE;      return binfo;    }  error_not_base_type (parent_or_type, type);  return NULL_TREE;}/* Print an error message stemming from an invalid use of an   aggregate type.   TYPE is the type or binfo which draws the error.   MSG is the message to print.   ARG is an optional argument which may provide more information.  */voiderror_with_aggr_type (type, msg, arg)     tree type;     char *msg;     int arg;{  tree name;  if (TREE_CODE (type) == TREE_VEC)    type = BINFO_TYPE (type);  name = TYPE_NAME (type);  if (TREE_CODE (name) == TYPE_DECL)    name = DECL_NAME (name);  error (msg, IDENTIFIER_POINTER (name), arg);}/* Warn or give error about storing in something that is `const'.  *//* for now, because the compiler is getting pickier about const'ness   give users a non-fatal warning instead of an error, this will   revert back to a hard error after a release or two.  This is   to not screw the user that has valid code for which the compiler   does not treat it right.  */#if 0#define const_error error#else#define const_error pedwarn#endifvoidreadonly_warning_or_error (arg, string)     tree arg;     char *string;{  char *fmt;  if (TREE_CODE (arg) == COMPONENT_REF)    {      if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))        fmt = "%s of member `%s' in read-only structure";      else        fmt = "%s of read-only member `%s'";      const_error (fmt, string, lang_printable_name (TREE_OPERAND (arg, 1)));    }  else if (TREE_CODE (arg) == VAR_DECL)    {      if (DECL_LANG_SPECIFIC (arg)	  && DECL_IN_AGGR_P (arg)	  && !TREE_STATIC (arg))	fmt = "%s of constant field `%s'";      else	fmt = "%s of read-only variable `%s'";      const_error (fmt, string, lang_printable_name (arg));    }  else if (TREE_CODE (arg) == PARM_DECL)    {      const_error ("%s of read-only parameter `%s'",		   string, lang_printable_name (arg));    }  else if (TREE_CODE (arg) == INDIRECT_REF           && TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))) == REFERENCE_TYPE           && (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL               || TREE_CODE (TREE_OPERAND (arg, 0)) == PARM_DECL))    {      const_error ("%s of read-only reference `%s'",		   string, lang_printable_name (TREE_OPERAND (arg, 0)));    }  else	           {      const_error ("%s of read-only location", string);    }}/* Print an error message for invalid use of a type which declares   virtual functions which are not inheritable.  */voidabstract_virtuals_error (decl, type)     tree decl;     tree type;{  char *typename = TYPE_NAME_STRING (type);  tree u = CLASSTYPE_ABSTRACT_VIRTUALS (type);  if (decl)    {      if (TREE_CODE (decl) == RESULT_DECL)	return;      if (TREE_CODE (decl) == VAR_DECL)	error_with_decl (decl, "cannot declare variable `%s' to be of type `%s'", typename);      else if (TREE_CODE (decl) == PARM_DECL)	error_with_decl (decl, "cannot declare parameter `%s' to be of type `%s'", typename);      else if (TREE_CODE (decl) == FIELD_DECL)	error_with_decl (decl, "cannot declare field `%s' to be of type `%s'", typename);      else if (TREE_CODE (decl) == FUNCTION_DECL	       && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)	error_with_decl (decl, "invalid return type for method `%s'");      else if (TREE_CODE (decl) == FUNCTION_DECL)	error_with_decl (decl, "invalid return type for function `%s'");    }  else error ("cannot allocate an object of type `%s'", typename);  /* Only go through this once.  */  if (TREE_PURPOSE (u) == NULL_TREE)    {      error ("since the following virtual functions are abstract:");      TREE_PURPOSE (u) = error_mark_node;      while (u)	{	  error_with_decl (TREE_VALUE (u), "%s");	  u = TREE_CHAIN (u);	}    }  else error ("since type `%s' has abstract virtual functions", typename);}/* Print an error message for invalid use of an incomplete type.   VALUE is the expression that was used (or 0 if that isn't known)   and TYPE is the type that was invalid.  */voidincomplete_type_error (value, type)     tree value;     tree type;{  char *errmsg;  /* Avoid duplicate error message.  */  if (TREE_CODE (type) == ERROR_MARK)    return;  if (value != 0 && (TREE_CODE (value) == VAR_DECL		     || TREE_CODE (value) == PARM_DECL))    error ("`%s' has an incomplete type",	   IDENTIFIER_POINTER (DECL_NAME (value)));  else    {    retry:      /* We must print an error message.  Be clever about what it says.  */      switch (TREE_CODE (type))	{	case RECORD_TYPE:	  errmsg = "invalid use of undefined type `struct %s'";	  break;	case UNION_TYPE:	  errmsg = "invalid use of undefined type `union %s'";	  break;	case ENUMERAL_TYPE:	  errmsg = "invalid use of undefined type `enum %s'";	  break;	case VOID_TYPE:	  error ("invalid use of void expression");	  return;	case ARRAY_TYPE:	  if (TYPE_DOMAIN (type))	    {	      type = TREE_TYPE (type);	      goto retry;	    }	  error ("invalid use of array with unspecified bounds");	  return;	case OFFSET_TYPE:	  error ("invalid use of member type (did you forget the `&' ?)");	  return;	default:	  my_friendly_abort (108);	}      error_with_aggr_type (type, errmsg);    }}/* There are times when the compiler can get very confused, confused   to the point of giving up by aborting, simply because of previous   input errors.  It is much better to have the user go back and   correct those errors first, and see if it makes us happier, than it   is to abort on him.  This is because when one has a 10,000 line   program, and the compiler comes back with ``core dump'', the user   is left not knowing even where to begin to fix things and no place   to even try and work around things.   The parameter is to uniquely identify the problem to the user, so   that they can say, I am having problem 59, and know that fix 7 will   probably solve their problem.  Or, we can document what problem   59 is, so they can understand how to work around it, should they   ever run into it.   Note, there will be no more calls in the C++ front end to abort,   because the C++ front end is so unreliable still.  The C front end   can get away with calling abort, because for most of the calls to   abort on most machines, it, I suspect, can be proven that it is   impossible to ever call abort.  The same is not yet true for C++,   one day, maybe it will be.  (mrs) *//* First used: 0 (reserved), Last used: 345 */voidmy_friendly_abort (i)     int i;{  if (i == 0)    error ("Internal compiler error.");  else if (errorcount + sorrycount == 1)    fatal ("please fix above error, and try recompiling.");  else if (errorcount > 0 || sorrycount > 0)    fatal ("please fix above errors, and try recompiling.");  else    error ("Internal compiler error %d.", i);  fatal ("Please report this to `bug-g++@prep.ai.mit.edu'.");}voidmy_friendly_assert (cond, where)     int cond, where;{  if (cond == 0)    {      /* Don't say "please fix above errors", since it's quite	 possible that we've lost somewhere unrelated to an error.  */      errorcount = sorrycount = 0;      my_friendly_abort (where);    }}/* Return nonzero if VALUE is a valid constant-valued expression   for use in initializing a static variable; one that can be an   element of a "constant" initializer.   Return 1 if the value is absolute; return 2 if it is relocatable.   We assume that VALUE has been folded as much as possible;   therefore, we do not need to check for such things as   arithmetic-combinations of integers.  */static intinitializer_constant_valid_p (value)     tree value;{  switch (TREE_CODE (value))    {    case CONSTRUCTOR:      return TREE_STATIC (value);    case INTEGER_CST:    case REAL_CST:    case STRING_CST:      return 1;    case ADDR_EXPR:      return 2;    case CONVERT_EXPR:    case NOP_EXPR:      /* Allow conversions between types of the same kind.  */      if (TREE_CODE (TREE_TYPE (value))	  == TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))))	return initializer_constant_valid_p (TREE_OPERAND (value, 0));      /* Allow (int) &foo.  */      if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE)	return initializer_constant_valid_p (TREE_OPERAND (value, 0));      return 0;    case PLUS_EXPR:      {	int valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0));	int valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1));	if (valid0 == 1 && valid1 == 2)	  return 2;	if (valid0 == 2 && valid1 == 1)	  return 2;	return 0;      }    case MINUS_EXPR:      {	int valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0));	int valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1));	if (valid0 == 2 && valid1 == 1)	  return 2;	return 0;      }    }  return 0;}/* Perform appropriate conversions on the initial value of a variable,   store it in the declaration DECL,   and print any error messages that are appropriate.   If the init is invalid, store an ERROR_MARK.   C++: Note that INIT might be a TREE_LIST, which would mean that it is   a base class initializer for some aggregate type, hopefully compatible   with DECL.  If INIT is a single element, and DECL is an aggregate   type, we silently convert INIT into a TREE_LIST, allowing a constructor

⌨️ 快捷键说明

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