1 /*****************************************************************************/
5 /* Type compare function for the cc65 C compiler */
9 /* (C) 1998-2000 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@musoftware.de */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
42 /*****************************************************************************/
44 /*****************************************************************************/
48 static void SetResult (typecmp_t* Result, typecmp_t Val)
49 /* Set a new result value if it is less than the existing one */
58 static int EqualSymTables (SymTable* Tab1, SymTable* Tab2)
59 /* Compare two symbol tables. Return 1 if they are equal and 0 otherwise */
61 /* Compare the parameter lists */
62 SymEntry* Sym1 = Tab1->SymHead;
63 SymEntry* Sym2 = Tab2->SymHead;
65 /* Compare the fields */
66 while (Sym1 && Sym2) {
68 /* Compare this field */
69 if (TypeCmp (Sym1->Type, Sym2->Type) < TC_EQUAL) {
70 /* Field types not equal */
74 /* Get the pointers to the next fields */
79 /* Check both pointers against NULL to compare the field count */
80 return (Sym1 == 0 && Sym2 == 0);
85 static void DoCompare (const type* lhs, const type* rhs, typecmp_t* Result)
86 /* Recursively compare two types. */
88 unsigned Indirections;
89 unsigned ElementCount;
99 /* Initialize stuff */
103 /* Compare two types. Determine, where they differ */
104 while (*lhs != T_END) {
106 type LeftType, RightType;
107 type LeftSign, RightSign;
108 type LeftQual, RightQual;
109 unsigned LeftCount, RightCount;
111 /* Check if the end of the type string is reached */
113 /* End of comparison reached */
117 /* Get the raw left and right types, signs and qualifiers */
118 LeftType = GetType (lhs);
119 RightType = GetType (rhs);
120 LeftSign = GetSignedness (lhs);
121 RightSign = GetSignedness (rhs);
122 LeftQual = GetQualifier (lhs);
123 RightQual = GetQualifier (rhs);
125 /* If the left type is a pointer and the right is an array, both
128 if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) {
129 RightType = T_TYPE_PTR;
133 /* If the raw types are not identical, the types are incompatible */
134 if (LeftType != RightType) {
135 SetResult (Result, TC_INCOMPATIBLE);
139 /* On indirection level zero, a qualifier or sign difference is
140 * accepted. The types are no longer equal, but compatible.
142 if (LeftSign != RightSign) {
143 if (ElementCount == 0) {
144 SetResult (Result, TC_SIGN_DIFF);
146 SetResult (Result, TC_INCOMPATIBLE);
150 if (LeftQual != RightQual) {
151 /* On the first indirection level, different qualifiers mean
152 * that the types are still compatible. On the second level,
153 * this is a (maybe minor) error, so we create a special
154 * return code, since a qualifier is dropped from a pointer.
155 * Starting from the next level, the types are incompatible
156 * if the qualifiers differ.
158 switch (Indirections) {
161 SetResult (Result, TC_STRICT_COMPATIBLE);
165 /* A non const value on the right is compatible to a
166 * const one to the left, same for volatile.
168 if ((LeftQual & T_QUAL_CONST) < (RightQual & T_QUAL_CONST) ||
169 (LeftQual & T_QUAL_VOLATILE) < (RightQual & T_QUAL_VOLATILE)) {
170 SetResult (Result, TC_QUAL_DIFF);
172 SetResult (Result, TC_STRICT_COMPATIBLE);
177 SetResult (Result, TC_INCOMPATIBLE);
182 /* Check for special type elements */
190 /* Compare the function descriptors */
191 F1 = DecodePtr (lhs+1);
192 F2 = DecodePtr (rhs+1);
194 /* If one of the functions is implicitly declared, both
195 * functions are considered equal. If one of the functions is
196 * old style, and the other is empty, the functions are
199 if ((F1->Flags & FD_IMPLICIT) != 0 || (F2->Flags & FD_IMPLICIT) != 0) {
201 } else if ((F1->Flags & FD_OLDSTYLE) != 0 && (F2->Flags & FD_EMPTY) != 0) {
203 } else if ((F1->Flags & FD_EMPTY) != 0 && (F2->Flags & FD_OLDSTYLE) != 0) {
211 /* Check the remaining flags */
212 if ((F1->Flags & ~FD_IGNORE) != (F2->Flags & ~FD_IGNORE)) {
214 SetResult (Result, TC_INCOMPATIBLE);
218 /* Compare the parameter lists */
219 if (EqualSymTables (F1->SymTab, F2->SymTab) == 0 ||
220 EqualSymTables (F1->TagTab, F2->TagTab) == 0) {
221 /* One of the tables is not identical */
222 SetResult (Result, TC_INCOMPATIBLE);
227 /* Skip the FuncDesc pointers to compare the return type */
233 /* Check member count */
234 LeftCount = Decode (lhs+1);
235 RightCount = Decode (rhs+1);
236 if (LeftCount != 0 && RightCount != 0 && LeftCount != RightCount) {
237 /* Member count given but different */
238 SetResult (Result, TC_INCOMPATIBLE);
247 /* Compare the fields recursively. To do that, we fetch the
248 * pointer to the struct definition from the type, and compare
251 Sym1 = DecodePtr (lhs+1);
252 Sym2 = DecodePtr (rhs+1);
254 /* Get the field tables from the struct entry */
255 Tab1 = Sym1->V.S.SymTab;
256 Tab2 = Sym2->V.S.SymTab;
258 /* One or both structs may be forward definitions. In this case,
259 * the symbol tables are both non existant. Assume that the
260 * structs are equal in this case.
262 if (Tab1 != 0 && Tab2 != 0) {
264 if (EqualSymTables (Tab1, Tab2) == 0) {
265 /* Field lists are not equal */
266 SetResult (Result, TC_INCOMPATIBLE);
272 /* Structs are equal */
278 /* Next type string element */
284 /* Check if end of rhs reached */
286 SetResult (Result, TC_EQUAL);
288 SetResult (Result, TC_INCOMPATIBLE);
294 typecmp_t TypeCmp (const type* lhs, const type* rhs)
295 /* Compare two types and return the result */
297 /* Assume the types are identical */
298 typecmp_t Result = TC_IDENTICAL;
301 printf ("Left : "); PrintRawType (stdout, lhs);
302 printf ("Right: "); PrintRawType (stdout, rhs);
305 /* Recursively compare the types if they aren't identical */
307 DoCompare (lhs, rhs, &Result);
310 /* Return the result */