1 /*****************************************************************************/
5 /* Type compare function for the cc65 C compiler */
9 /* (C) 1998-2003 Ullrich von Bassewitz */
10 /* Römerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
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 /*****************************************************************************/
45 /*****************************************************************************/
47 /*****************************************************************************/
51 static void SetResult (typecmp_t* Result, typecmp_t Val)
52 /* Set a new result value if it is less than the existing one */
61 static int EqualFuncParams (SymTable* Tab1, SymTable* Tab2)
62 /* Compare two function symbol tables regarding function parameters. Return 1
63 * if they are equal and 0 otherwise.
66 /* Compare the parameter lists */
67 SymEntry* Sym1 = Tab1->SymHead;
68 SymEntry* Sym2 = Tab2->SymHead;
70 /* Compare the fields */
71 while (Sym1 && (Sym1->Flags & SC_PARAM) && Sym2 && (Sym2->Flags & SC_PARAM)) {
73 /* Compare this field */
74 if (TypeCmp (Sym1->Type, Sym2->Type) < TC_EQUAL) {
75 /* Field types not equal */
79 /* Get the pointers to the next fields */
84 /* Check both pointers against NULL or a non parameter to compare the
87 return (Sym1 == 0 || (Sym1->Flags & SC_PARAM) == 0) &&
88 (Sym2 == 0 || (Sym2->Flags & SC_PARAM) == 0);
93 static int EqualSymTables (SymTable* Tab1, SymTable* Tab2)
94 /* Compare two symbol tables. Return 1 if they are equal and 0 otherwise */
96 /* Compare the parameter lists */
97 SymEntry* Sym1 = Tab1->SymHead;
98 SymEntry* Sym2 = Tab2->SymHead;
100 /* Compare the fields */
101 while (Sym1 && Sym2) {
103 /* Compare the names of this field */
104 if (!HasAnonName (Sym1) || !HasAnonName (Sym2)) {
105 if (strcmp (Sym1->Name, Sym2->Name) != 0) {
106 /* Names are not identical */
111 /* Compare the types of this field */
112 if (TypeCmp (Sym1->Type, Sym2->Type) < TC_EQUAL) {
113 /* Field types not equal */
117 /* Get the pointers to the next fields */
118 Sym1 = Sym1->NextSym;
119 Sym2 = Sym2->NextSym;
122 /* Check both pointers against NULL to compare the field count */
123 return (Sym1 == 0 && Sym2 == 0);
128 static void DoCompare (const type* lhs, const type* rhs, typecmp_t* Result)
129 /* Recursively compare two types. */
131 unsigned Indirections;
132 unsigned ElementCount;
142 /* Initialize stuff */
146 /* Compare two types. Determine, where they differ */
147 while (*lhs != T_END) {
149 type LeftType, RightType;
150 type LeftSign, RightSign;
151 type LeftQual, RightQual;
152 long LeftCount, RightCount;
154 /* Check if the end of the type string is reached */
156 /* End of comparison reached */
160 /* Get the raw left and right types, signs and qualifiers */
161 LeftType = GetType (lhs);
162 RightType = GetType (rhs);
163 LeftSign = GetSignedness (lhs);
164 RightSign = GetSignedness (rhs);
165 LeftQual = GetQualifier (lhs);
166 RightQual = GetQualifier (rhs);
168 /* If the left type is a pointer and the right is an array, both
171 if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) {
172 RightType = T_TYPE_PTR;
176 /* If the raw types are not identical, the types are incompatible */
177 if (LeftType != RightType) {
178 SetResult (Result, TC_INCOMPATIBLE);
182 /* On indirection level zero, a qualifier or sign difference is
183 * accepted. The types are no longer equal, but compatible.
185 if (LeftSign != RightSign) {
186 if (ElementCount == 0) {
187 SetResult (Result, TC_SIGN_DIFF);
189 SetResult (Result, TC_INCOMPATIBLE);
193 if (LeftQual != RightQual) {
194 /* On the first indirection level, different qualifiers mean
195 * that the types are still compatible. On the second level,
196 * this is a (maybe minor) error, so we create a special
197 * return code, since a qualifier is dropped from a pointer.
198 * Starting from the next level, the types are incompatible
199 * if the qualifiers differ.
201 switch (Indirections) {
204 SetResult (Result, TC_STRICT_COMPATIBLE);
208 /* A non const value on the right is compatible to a
209 * const one to the left, same for volatile.
211 if ((LeftQual & T_QUAL_CONST) < (RightQual & T_QUAL_CONST) ||
212 (LeftQual & T_QUAL_VOLATILE) < (RightQual & T_QUAL_VOLATILE)) {
213 SetResult (Result, TC_QUAL_DIFF);
215 SetResult (Result, TC_STRICT_COMPATIBLE);
220 SetResult (Result, TC_INCOMPATIBLE);
225 /* Check for special type elements */
233 /* Compare the function descriptors */
234 F1 = DecodePtr (lhs+1);
235 F2 = DecodePtr (rhs+1);
237 /* If one of the functions is implicitly declared, both
238 * functions are considered equal. If one of the functions is
239 * old style, and the other is empty, the functions are
242 if ((F1->Flags & FD_IMPLICIT) != 0 || (F2->Flags & FD_IMPLICIT) != 0) {
244 } else if ((F1->Flags & FD_OLDSTYLE) != 0 && (F2->Flags & FD_EMPTY) != 0) {
246 } else if ((F1->Flags & FD_EMPTY) != 0 && (F2->Flags & FD_OLDSTYLE) != 0) {
254 /* Check the remaining flags */
255 if ((F1->Flags & ~FD_IGNORE) != (F2->Flags & ~FD_IGNORE)) {
257 SetResult (Result, TC_INCOMPATIBLE);
261 /* Compare the parameter lists */
262 if (EqualFuncParams (F1->SymTab, F2->SymTab) == 0 ||
263 EqualSymTables (F1->TagTab, F2->TagTab) == 0) {
264 /* One of the tables is not identical */
265 SetResult (Result, TC_INCOMPATIBLE);
270 /* Skip the FuncDesc pointers to compare the return type */
276 /* Check member count */
277 LeftCount = GetElementCount (lhs);
278 RightCount = GetElementCount (rhs);
279 if (LeftCount != UNSPECIFIED &&
280 RightCount != UNSPECIFIED &&
281 LeftCount != RightCount) {
282 /* Member count given but different */
283 SetResult (Result, TC_INCOMPATIBLE);
292 /* Compare the fields recursively. To do that, we fetch the
293 * pointer to the struct definition from the type, and compare
296 Sym1 = DecodePtr (lhs+1);
297 Sym2 = DecodePtr (rhs+1);
299 /* If one symbol has a name, the names must be identical */
300 if (!HasAnonName (Sym1) || !HasAnonName (Sym2)) {
301 if (strcmp (Sym1->Name, Sym2->Name) != 0) {
302 /* Names are not identical */
303 SetResult (Result, TC_INCOMPATIBLE);
308 /* Get the field tables from the struct entry */
309 Tab1 = Sym1->V.S.SymTab;
310 Tab2 = Sym2->V.S.SymTab;
312 /* One or both structs may be forward definitions. In this case,
313 * the symbol tables are both non existant. Assume that the
314 * structs are equal in this case.
316 if (Tab1 != 0 && Tab2 != 0) {
318 if (EqualSymTables (Tab1, Tab2) == 0) {
319 /* Field lists are not equal */
320 SetResult (Result, TC_INCOMPATIBLE);
326 /* Structs are equal */
332 /* Next type string element */
338 /* Check if end of rhs reached */
340 SetResult (Result, TC_EQUAL);
342 SetResult (Result, TC_INCOMPATIBLE);
348 typecmp_t TypeCmp (const type* lhs, const type* rhs)
349 /* Compare two types and return the result */
351 /* Assume the types are identical */
352 typecmp_t Result = TC_IDENTICAL;
355 printf ("Left : "); PrintRawType (stdout, lhs);
356 printf ("Right: "); PrintRawType (stdout, rhs);
359 /* Recursively compare the types if they aren't identical */
361 DoCompare (lhs, rhs, &Result);
364 /* Return the result */