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

📄 resolve.c

📁 gcc-fortran,linux使用fortran的编译软件。很好用的。
💻 C
📖 第 1 页 / 共 5 页
字号:
	  if (mpz_cmp (op1->shape[i], op2->shape[i]) != 0)	   {	     gfc_error ("Shapes for operands at %L and %L are not conformable",			 &op1->where, &op2->where);	     t = FAILURE;	     break;	   }	}    }  return t;}/* Resolve an operator expression node.  This can involve replacing the   operation with a user defined function call.  */static tryresolve_operator (gfc_expr * e){  gfc_expr *op1, *op2;  char msg[200];  try t;  /* Resolve all subnodes-- give them types.  */  switch (e->value.op.operator)    {    default:      if (gfc_resolve_expr (e->value.op.op2) == FAILURE)	return FAILURE;    /* Fall through...  */    case INTRINSIC_NOT:    case INTRINSIC_UPLUS:    case INTRINSIC_UMINUS:    case INTRINSIC_PARENTHESES:      if (gfc_resolve_expr (e->value.op.op1) == FAILURE)	return FAILURE;      break;    }  /* Typecheck the new node.  */  op1 = e->value.op.op1;  op2 = e->value.op.op2;  switch (e->value.op.operator)    {    case INTRINSIC_UPLUS:    case INTRINSIC_UMINUS:      if (op1->ts.type == BT_INTEGER	  || op1->ts.type == BT_REAL	  || op1->ts.type == BT_COMPLEX)	{	  e->ts = op1->ts;	  break;	}      sprintf (msg, _("Operand of unary numeric operator '%s' at %%L is %s"),	       gfc_op2string (e->value.op.operator), gfc_typename (&e->ts));      goto bad_op;    case INTRINSIC_PLUS:    case INTRINSIC_MINUS:    case INTRINSIC_TIMES:    case INTRINSIC_DIVIDE:    case INTRINSIC_POWER:      if (gfc_numeric_ts (&op1->ts) && gfc_numeric_ts (&op2->ts))	{	  gfc_type_convert_binary (e);	  break;	}      sprintf (msg,	       _("Operands of binary numeric operator '%s' at %%L are %s/%s"),	       gfc_op2string (e->value.op.operator), gfc_typename (&op1->ts),	       gfc_typename (&op2->ts));      goto bad_op;    case INTRINSIC_CONCAT:      if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER)	{	  e->ts.type = BT_CHARACTER;	  e->ts.kind = op1->ts.kind;	  break;	}      sprintf (msg,	       _("Operands of string concatenation operator at %%L are %s/%s"),	       gfc_typename (&op1->ts), gfc_typename (&op2->ts));      goto bad_op;    case INTRINSIC_AND:    case INTRINSIC_OR:    case INTRINSIC_EQV:    case INTRINSIC_NEQV:      if (op1->ts.type == BT_LOGICAL && op2->ts.type == BT_LOGICAL)	{	  e->ts.type = BT_LOGICAL;	  e->ts.kind = gfc_kind_max (op1, op2);          if (op1->ts.kind < e->ts.kind)            gfc_convert_type (op1, &e->ts, 2);          else if (op2->ts.kind < e->ts.kind)            gfc_convert_type (op2, &e->ts, 2);	  break;	}      sprintf (msg, _("Operands of logical operator '%s' at %%L are %s/%s"),	       gfc_op2string (e->value.op.operator), gfc_typename (&op1->ts),	       gfc_typename (&op2->ts));      goto bad_op;    case INTRINSIC_NOT:      if (op1->ts.type == BT_LOGICAL)	{	  e->ts.type = BT_LOGICAL;	  e->ts.kind = op1->ts.kind;	  break;	}      sprintf (msg, _("Operand of .NOT. operator at %%L is %s"),	       gfc_typename (&op1->ts));      goto bad_op;    case INTRINSIC_GT:    case INTRINSIC_GE:    case INTRINSIC_LT:    case INTRINSIC_LE:      if (op1->ts.type == BT_COMPLEX || op2->ts.type == BT_COMPLEX)	{	  strcpy (msg, _("COMPLEX quantities cannot be compared at %L"));	  goto bad_op;	}      /* Fall through...  */    case INTRINSIC_EQ:    case INTRINSIC_NE:      if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER)	{	  e->ts.type = BT_LOGICAL;	  e->ts.kind = gfc_default_logical_kind;	  break;	}      if (gfc_numeric_ts (&op1->ts) && gfc_numeric_ts (&op2->ts))	{	  gfc_type_convert_binary (e);	  e->ts.type = BT_LOGICAL;	  e->ts.kind = gfc_default_logical_kind;	  break;	}      if (op1->ts.type == BT_LOGICAL && op2->ts.type == BT_LOGICAL)	sprintf (msg,	         _("Logicals at %%L must be compared with %s instead of %s"),		 e->value.op.operator == INTRINSIC_EQ ? ".EQV." : ".NEQV.",		 gfc_op2string (e->value.op.operator));      else	sprintf (msg,	         _("Operands of comparison operator '%s' at %%L are %s/%s"),		 gfc_op2string (e->value.op.operator), gfc_typename (&op1->ts),		 gfc_typename (&op2->ts));      goto bad_op;    case INTRINSIC_USER:      if (op2 == NULL)	sprintf (msg, _("Operand of user operator '%s' at %%L is %s"),		 e->value.op.uop->name, gfc_typename (&op1->ts));      else	sprintf (msg, _("Operands of user operator '%s' at %%L are %s/%s"),		 e->value.op.uop->name, gfc_typename (&op1->ts),		 gfc_typename (&op2->ts));      goto bad_op;    case INTRINSIC_PARENTHESES:      break;    default:      gfc_internal_error ("resolve_operator(): Bad intrinsic");    }  /* Deal with arrayness of an operand through an operator.  */  t = SUCCESS;  switch (e->value.op.operator)    {    case INTRINSIC_PLUS:    case INTRINSIC_MINUS:    case INTRINSIC_TIMES:    case INTRINSIC_DIVIDE:    case INTRINSIC_POWER:    case INTRINSIC_CONCAT:    case INTRINSIC_AND:    case INTRINSIC_OR:    case INTRINSIC_EQV:    case INTRINSIC_NEQV:    case INTRINSIC_EQ:    case INTRINSIC_NE:    case INTRINSIC_GT:    case INTRINSIC_GE:    case INTRINSIC_LT:    case INTRINSIC_LE:      if (op1->rank == 0 && op2->rank == 0)	e->rank = 0;      if (op1->rank == 0 && op2->rank != 0)	{	  e->rank = op2->rank;	  if (e->shape == NULL)	    e->shape = gfc_copy_shape (op2->shape, op2->rank);	}      if (op1->rank != 0 && op2->rank == 0)	{	  e->rank = op1->rank;	  if (e->shape == NULL)	    e->shape = gfc_copy_shape (op1->shape, op1->rank);	}      if (op1->rank != 0 && op2->rank != 0)	{	  if (op1->rank == op2->rank)	    {	      e->rank = op1->rank;	      if (e->shape == NULL)		{		  t = compare_shapes(op1, op2);		  if (t == FAILURE)		    e->shape = NULL;		  else		e->shape = gfc_copy_shape (op1->shape, op1->rank);		}	    }	  else	    {	      gfc_error ("Inconsistent ranks for operator at %L and %L",			 &op1->where, &op2->where);	      t = FAILURE;              /* Allow higher level expressions to work.  */	      e->rank = 0;	    }	}      break;    case INTRINSIC_NOT:    case INTRINSIC_UPLUS:    case INTRINSIC_UMINUS:    case INTRINSIC_PARENTHESES:      e->rank = op1->rank;      if (e->shape == NULL)	e->shape = gfc_copy_shape (op1->shape, op1->rank);      /* Simply copy arrayness attribute */      break;    default:      break;    }  /* Attempt to simplify the expression.  */  if (t == SUCCESS)    t = gfc_simplify_expr (e, 0);  return t;bad_op:  if (gfc_extend_expr (e) == SUCCESS)    return SUCCESS;  gfc_error (msg, &e->where);  return FAILURE;}/************** Array resolution subroutines **************/typedef enum{ CMP_LT, CMP_EQ, CMP_GT, CMP_UNKNOWN }comparison;/* Compare two integer expressions.  */static comparisoncompare_bound (gfc_expr * a, gfc_expr * b){  int i;  if (a == NULL || a->expr_type != EXPR_CONSTANT      || b == NULL || b->expr_type != EXPR_CONSTANT)    return CMP_UNKNOWN;  if (a->ts.type != BT_INTEGER || b->ts.type != BT_INTEGER)    gfc_internal_error ("compare_bound(): Bad expression");  i = mpz_cmp (a->value.integer, b->value.integer);  if (i < 0)    return CMP_LT;  if (i > 0)    return CMP_GT;  return CMP_EQ;}/* Compare an integer expression with an integer.  */static comparisoncompare_bound_int (gfc_expr * a, int b){  int i;  if (a == NULL || a->expr_type != EXPR_CONSTANT)    return CMP_UNKNOWN;  if (a->ts.type != BT_INTEGER)    gfc_internal_error ("compare_bound_int(): Bad expression");  i = mpz_cmp_si (a->value.integer, b);  if (i < 0)    return CMP_LT;  if (i > 0)    return CMP_GT;  return CMP_EQ;}/* Compare a single dimension of an array reference to the array   specification.  */static trycheck_dimension (int i, gfc_array_ref * ar, gfc_array_spec * as){/* Given start, end and stride values, calculate the minimum and   maximum referenced indexes.  */  switch (ar->type)    {    case AR_FULL:      break;    case AR_ELEMENT:      if (compare_bound (ar->start[i], as->lower[i]) == CMP_LT)	goto bound;      if (compare_bound (ar->start[i], as->upper[i]) == CMP_GT)	goto bound;      break;    case AR_SECTION:      if (compare_bound_int (ar->stride[i], 0) == CMP_EQ)	{	  gfc_error ("Illegal stride of zero at %L", &ar->c_where[i]);	  return FAILURE;	}      if (compare_bound (ar->start[i], as->lower[i]) == CMP_LT)	goto bound;      if (compare_bound (ar->start[i], as->upper[i]) == CMP_GT)	goto bound;      /* TODO: Possibly, we could warn about end[i] being out-of-bound although         it is legal (see 6.2.2.3.1).  */      break;    default:      gfc_internal_error ("check_dimension(): Bad array reference");    }  return SUCCESS;bound:  gfc_warning ("Array reference at %L is out of bounds", &ar->c_where[i]);  return SUCCESS;}/* Compare an array reference with an array specification.  */static trycompare_spec_to_ref (gfc_array_ref * ar){  gfc_array_spec *as;  int i;  as = ar->as;  i = as->rank - 1;  /* TODO: Full array sections are only allowed as actual parameters.  */  if (as->type == AS_ASSUMED_SIZE      && (/*ar->type == AR_FULL          ||*/ (ar->type == AR_SECTION              && ar->dimen_type[i] == DIMEN_RANGE && ar->end[i] == NULL)))    {      gfc_error ("Rightmost upper bound of assumed size array section"                 " not specified at %L", &ar->where);      return FAILURE;    }  if (ar->type == AR_FULL)    return SUCCESS;  if (as->rank != ar->dimen)    {      gfc_error ("Rank mismatch in array reference at %L (%d/%d)",		 &ar->where, ar->dimen, as->rank);      return FAILURE;    }  for (i = 0; i < as->rank; i++)    if (check_dimension (i, ar, as) == FAILURE)      return FAILURE;  return SUCCESS;}/* Resolve one part of an array index.  */trygfc_resolve_index (gfc_expr * index, int check_scalar){  gfc_typespec ts;  if (index == NULL)    return SUCCESS;  if (gfc_resolve_expr (index) == FAILURE)    return FAILURE;  if (check_scalar && index->rank != 0)    {      gfc_error ("Array index at %L must be scalar", &index->where);      return FAILURE;    }  if (index->ts.type != BT_INTEGER && index->ts.type != BT_REAL)    {      gfc_error ("Array index at %L must be of INTEGER type",		 &index->where);      return FAILURE;    }  if (index->ts.type == BT_REAL)    if (gfc_notify_std (GFC_STD_GNU, "Extension: REAL array index at %L",			&index->where) == FAILURE)      return FAILURE;  if (index->ts.kind != gfc_index_integer_kind      || index->ts.type != BT_INTEGER)    {      gfc_clear_ts (&ts);      ts.type = BT_INTEGER;      ts.kind = gfc_index_integer_kind;      gfc_convert_type_warn (index, &ts, 2, 0);    }  return SUCCESS;}/* Resolve a dim argument to an intrinsic function.  */trygfc_resolve_dim_arg (gfc_expr *dim){  if (dim == NULL)    return SUCCESS;  if (gfc_resolve_expr (dim) == FAILURE)    return FAILURE;  if (dim->rank != 0)    {      gfc_error ("Argument dim at %L must be scalar", &dim->where);      return FAILURE;      }  if (dim->ts.type != BT_INTEGER)    {      gfc_error ("Argument dim at %L must be of INTEGER type", &dim->where);      return FAILURE;    }  if (dim->ts.kind != gfc_index_integer_kind)    {      gfc_typespec ts;      ts.type = BT_INTEGER;      ts.kind = gfc_index_integer_kind;      gfc_convert_type_warn (dim, &ts, 2, 0);    }  return SUCCESS;}/* Given an expression that contains array references, update those array   references to point to the right array specifications.  While this is   filled in during matching, this information is difficult to save and load   in a module, so we take care of it here.   The idea here is that the original array reference comes from the   base symbol.  We traverse the list of reference structures, setting   the stored reference to references.  Component references can   provide an additional array specification.  */static voidfind_array_spec (gfc_expr * e){  gfc_array_spec *as;  gfc_component *c;  gfc_ref *ref;  as = e->symtree->n.sym->as;  for (ref = e->ref; ref; ref = ref->next)    switch (ref->type)      {      case REF_ARRAY:	if (as == NULL)	  gfc_internal_error ("find_array_spec(): Missing spec");	ref->u.ar.as = as;	as = NULL;	break;      case REF_COMPONENT:	for (c = e->symtree->n.sym->ts.derived->components; c; c = c->next)	  if (c == ref->u.c.component)	    break;	if (c == NULL)	  gfc_internal_error ("find_array_spec(): Component not found");	if (c->dimension)

⌨️ 快捷键说明

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