Пример #1
0
GLOBAL Node *ArrayType(Node *array)
{
     Node *atype;

     assert(array->typ == Array);
     assert(array->u.array.name);

     atype = NodeDataType(array->u.array.name);

     if (atype->typ == Adcl) {
	  Node *btype = atype, *item;
	  ListMarker marker;

	  /* Loop down the index operations to find the type */
	  IterateList(&marker, array->u.array.dims);
	  while (NextOnList(&marker, (GenericREF) & item))
	       if (btype->typ == Adcl)
		    btype = NodeDataType(btype->u.adcl.type);
	       else if (btype->typ == Ptr)
		    btype = NodeDataType(btype->u.ptr.type);
	       else {
		    SyntaxErrorCoord(array->coord,
				"3 cannot dereference non-pointer type");
		    return PrimVoid;
	       }

	  return btype;
     } else if (atype->typ == Ptr) {
	  Node *btype = atype, *item;
	  ListMarker marker;

	  /* Loop down the index operations to find the type */
	  IterateList(&marker, array->u.array.dims);
	  while (NextOnList(&marker, (GenericREF) & item))
	       if (btype->typ == Adcl)
		    btype = NodeDataType(btype->u.adcl.type);
	       else if (btype->typ == Ptr)
		    btype = NodeDataType(btype->u.ptr.type);
	       else {
		    SyntaxErrorCoord(array->coord,
				     "cannot dereference non-pointer type");
		    return PrimVoid;
	       }

	  return btype;
     } else {
	  fprintf(stderr, "ArrayType: Node at ");
	  PRINT_COORD(stderr, array->coord);
	  fputc('\n', stderr);
	  fPrintNode(stderr, array, 0);
	  fprintf(stderr, "\n");
	  assert(FALSE);
	  return (NULL);
     }
}
Пример #2
0
GLOBAL TypeQual MergeTypeQuals(TypeQual left, TypeQual right, Coord coord)
{
     TypeQual scl, scr, dql, dqr, tql, tqr;
     TypeQual result = tq_attribute(JoinLists(left.attributes,right.attributes));

     scl = tq_storage_class(left);
     scr = tq_storage_class(right);

     if (tq_has_anything(scl) && tq_has_anything(scr)) {
	  if (tq_equal(scl, scr)) {	/* scl == scr == single storage class */
	       char name[20];
	       TQtoText(name, 20, scl);
	       name[strlen(name) - 1] = 0;
	       WarningCoord(4, coord, "redundant storage class `%s'", name);
	  } else {
	       char namel[20], namer[20];
	       TQtoText(namel, 20, scl);
	       namel[strlen(namel) - 1] = 0;
	       TQtoText(namer, 20, scr);
	       namer[strlen(namer) - 1] = 0;
	       SyntaxErrorCoord(coord, "conflicting storage classes `%s' and `%s'",
				namel, namer);
	  }
	  result = tq_union(result, scl);
     } else {
	  result = tq_union(result, tq_union(scl, scr));
     }

     dql = tq_subtract(tq_decl_quals(left), scl);
     dqr = tq_subtract(tq_decl_quals(right), scr);

     if (tq_has_anything(tq_intersection(dql, dqr))) {
	  char name[20];
	  TQtoText(name, 20, tq_intersection(dql, dqr));
	  name[strlen(name) - 1] = 0;
	  WarningCoord(4, coord, "redundant declaration qualifier `%s'", name);
     }
     result = tq_union(result, tq_union(dql, dqr));

     tql = tq_type_quals(left);
     tqr = tq_type_quals(right);

     if (tq_has_anything(tq_intersection(tql, tqr))) {
	  char name[20];
	  TQtoText(name, 20, tq_intersection(tql, tqr));
	  name[strlen(name) - 1] = 0;
	  WarningCoord(4, coord, "redundant type qualifier `%s'", name);
     }
     result = tq_union(result, tq_union(tql, tqr));

     return (result);
}
Пример #3
0
GLOBAL TypeQual MergeTypeQuals(TypeQual left, TypeQual right, Coord coord)
{
    TypeQual scl, scr, dql, dqr, tql, tqr;
    TypeQual result = 0;

    scl = STORAGE_CLASS(left);
    scr = STORAGE_CLASS(right);

    if (scl != 0 && scr != 0) {
      if (scl == scr) { /* scl == scr == single storage class */
	WarningCoord(4, coord, "redundant storage class");
      } 
      else {
	char namel[20], namer[20];
	TQtoText(namel, scl);
	TQtoText(namer, scr);
	SyntaxErrorCoord(coord,"conflicting storage classes `%s' and `%s'",
			 namel, namer);
      }
      result |= scl;
    }
    else {
      result |= scl | scr;
    }

    dql = DECL_QUALS(left) & ~scl;
    dqr = DECL_QUALS(right) & ~scr;
    result |= (dql | dqr);

    tql = TYPE_QUALS(left);
    tqr = TYPE_QUALS(right);

    if ((tql & tqr) != 0) {
	WarningCoord(4, coord, "redundant type qualifier");
    }
    result |= (tql | tqr);
    return(result);
}
Пример #4
0
/*
   requires: node and n2 be partial Prim types (created by StartPrimType and
             not yet finished with FinishPrimType).
   changes: node
*/
GLOBAL Node *MergePrimTypes(Node *node, Node *n2)
{
  ExplodedType et1, et2;

    /* note: memory leak of *n2 */

    assert(node != NULL && node->typ == Prim);
    assert(node != NULL && n2->typ == Prim);

    BASIC2EXPLODED(node->u.prim.basic, et1);
    BASIC2EXPLODED(n2->u.prim.basic,   et2);

     /*
      * First merge base type (int, char, float, double, ...).
      * At most one base type may be specified. 
      */
    if (et1.base && et2.base) 
      SyntaxErrorCoord(node->coord,
		       "conflicting type specifiers: `%s' and `%s'",
		       TypeSpecifierName(et1.base),
		       TypeSpecifierName(et2.base));
    else et1.base |= et2.base;

     /*
      * Now merge signs.  At most one sign may be specified; it appears to
      * be legal in ANSI to repeat the same sign (as in 
      * "unsigned unsigned int"), but a warning is generated.
      */
    if (et1.sign && et2.sign) {
      if (et1.sign != et2.sign)
	SyntaxErrorCoord(node->coord,
			 "conflicting type specifiers: `%s' and `%s'",
			 TypeSpecifierName(et1.sign),
			 TypeSpecifierName(et2.sign));
      else
	WarningCoord(3, node->coord,
		     "repeated type specifier: `%s'",
		     TypeSpecifierName(et1.sign));
    }
    else et1.sign |= et2.sign;
    
     /*
      * Check that the resulting sign is compatible with the resulting
      * base type.
      * Only int and char may have a sign specifier.
      */
    if (et1.sign && et1.base) {
      if (et1.base != Int_ParseOnly && et1.base != Char) {
	SyntaxErrorCoord(node->coord,
			 "conflicting type specifiers: `%s' and `%s'",
			 TypeSpecifierName(et1.base),
			 TypeSpecifierName(et1.sign));
	et1.sign = 0;
      }
    }

     /*
      * Merge lengths (short, long, long long).
      */
    if (et1.length && et2.length) {
      if (et1.length == Long && et2.length == Long
	  && !ANSIOnly)
	et1.length = Longlong;
      else
	SyntaxErrorCoord(node->coord,
			 "conflicting type specifiers: `%s' and `%s'",
			 TypeSpecifierName(et1.length),
			 TypeSpecifierName(et2.length));
    }
    else et1.length |= et2.length;
    
     /*
      * Check that the resulting length is compatible with the resulting
      * base type.
      * Only int may have any length specifier; double may have long.
      */
    if (et1.length && et1.base) {
      if (et1.base != Int_ParseOnly && !(et1.base == Double && et1.length == Long)) {
	SyntaxErrorCoord(node->coord,
			 "conflicting type specifiers: `%s' and `%s'",
			 TypeSpecifierName(et1.base),
			 TypeSpecifierName(et1.length));
	et1.length = 0;
      }
    }

    EXPLODED2BASIC(et1, node->u.prim.basic);

    return(node);
}
Пример #5
0
/* Must mutate original if changes required for consistency */
GLOBAL void FunctionConflict(Node *orig, Node *create)
{
     Node *ofdcl, *nfdcl;

     assert(orig);
     assert(create);
     assert(orig->typ == Decl);
     assert(create->typ == Decl);

     ofdcl = NodeDataType(orig);
     nfdcl = NodeDataType(create);

     if (ofdcl->typ != Fdcl || nfdcl->typ != Fdcl)
	  goto Mismatch;


     /* 
      * Check if one declaration is T_PROCEDURE and the other is not.
      * BUG: I think the whole way we treat 'cilk' and 'inlet' keywords
      * is broken.  We treat 'cilk' like 'const', but 
      *
      *  const int foo()
      *
      * is not the same as
      *
      *  cilk int foo()
      *
      * The former returns a 'const int', but the latter does not return a
      * 'cilk int' !  - athena
      *
      * BTW, the following line is a hack :-)
      *   ((ofdcl->u.fdcl.tq ^ nfdcl->u.fdcl.tq) & (T_PROCEDURE | T_INLET))
      * Bradley rewrote it has follows:
      */
     if ((tq_has_procedure(ofdcl->u.fdcl.tq) != tq_has_procedure(nfdcl->u.fdcl.tq))
	 || (tq_has_inlet(ofdcl->u.fdcl.tq) != tq_has_inlet(nfdcl->u.fdcl.tq)))
	  goto Mismatch;

     /* The Result Type must be equal */
     if (!TypeEqual(ofdcl->u.fdcl.returns, nfdcl->u.fdcl.returns))
	  goto Mismatch;

     /* Inspect the parameter lists */
     {
	  List *optr = ofdcl->u.fdcl.args, *nptr = nfdcl->u.fdcl.args;

	  /* Are both definitions in prototype form? */
	  if (optr && nptr) {

	       /* Then every parameter must be compatible */
	       for (; optr && nptr; optr = Rest(optr), nptr = Rest(nptr)) {
		    Node *oitem = FirstItem(optr), *otype = NodeDataType(oitem),
		    *nitem = FirstItem(nptr), *ntype = NodeDataType(nitem);

		    if (!TypeEqualFormals(otype, ntype)) {
			 SetItem(optr, nitem);
			 goto Mismatch;
		    }

	       }

	       /* And the parameter lists must be of the same length */
	       if (optr || nptr)
		    goto Mismatch;
	  }
	  /* Check for <Type> f(void)  vs  <Type> f() */
	  else if (IsVoidArglist(optr));

	  /* Check for <Type> f()  vs  <Type> f(void) */
	  else if (IsVoidArglist(nptr))
	       ofdcl->u.fdcl.args = MakeNewList(PrimVoid);

	  /* Else the provided types must be the "usual unary conversions" */
	  else {

	       /* Either this loop will run */
	       for (; optr; optr = Rest(optr)) {
		    Node *oitem = FirstItem(optr), *otype = NodeDataType(oitem);
		    if (!TypeEqual(otype, UsualUnaryConversionType(otype)) ||
			IsEllipsis(otype))
			 goto Mismatch;
	       }

	       /* Or this one will */
	       for (; nptr; nptr = Rest(nptr)) {
		    Node *nitem = FirstItem(nptr), *ntype = NodeDataType(nitem);
		    if (!TypeEqual(ntype, UsualUnaryConversionType(ntype)) ||
			IsEllipsis(ntype))
			 goto Mismatch;
	       }
	  }
     }

     return;

   Mismatch:
     SyntaxErrorCoord(create->coord,
		      "identifier `%s' redeclared", VAR_NAME(orig));
     fprintf(stderr, "\tPrevious declaration: ");
     PRINT_COORD(stderr, orig->coord);
     fputc('\n', stderr);
     return;
}
Пример #6
0
PRIVATE void formal_conflict(Node *orig, Node *create)
{
     SyntaxErrorCoord(create->coord,
		      "formal `%s' used multiple times", VAR_NAME(orig));
}