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); } }
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); }
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); }
/* 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); }
/* 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; }
PRIVATE void formal_conflict(Node *orig, Node *create) { SyntaxErrorCoord(create->coord, "formal `%s' used multiple times", VAR_NAME(orig)); }