1 /*****************************************************************************/
5 /* Type compare function for the cc65 C compiler */
9 /* (C) 1998-2008 Ullrich von Bassewitz */
10 /* Roemerstrasse 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 */
55 /* printf ("SetResult = %d\n", Val); */
62 static int ParamsHaveDefaultPromotions (const FuncDesc* F)
63 /* Check if any of the parameters of function F has a default promotion. In
64 * this case, the function is not compatible with an empty parameter name list
68 /* Get the symbol table */
69 const SymTable* Tab = F->SymTab;
71 /* Get the first parameter in the list */
72 const SymEntry* Sym = Tab->SymHead;
74 /* Walk over all parameters */
75 while (Sym && (Sym->Flags & SC_PARAM)) {
77 /* If this is an integer type, check if the promoted type is equal
78 * to the original type. If not, we have a default promotion.
80 if (IsClassInt (Sym->Type)) {
81 if (IntPromotion (Sym->Type) != Sym->Type) {
86 /* Get the pointer to the next param */
90 /* No default promotions in the parameter list */
96 static int EqualFuncParams (const FuncDesc* F1, const FuncDesc* F2)
97 /* Compare two function symbol tables regarding function parameters. Return 1
98 * if they are equal and 0 otherwise.
101 /* Get the symbol tables */
102 const SymTable* Tab1 = F1->SymTab;
103 const SymTable* Tab2 = F2->SymTab;
105 /* Compare the parameter lists */
106 const SymEntry* Sym1 = Tab1->SymHead;
107 const SymEntry* Sym2 = Tab2->SymHead;
109 /* Compare the fields */
110 while (Sym1 && (Sym1->Flags & SC_PARAM) && Sym2 && (Sym2->Flags & SC_PARAM)) {
112 /* Get the symbol types */
113 Type* Type1 = Sym1->Type;
114 Type* Type2 = Sym2->Type;
116 /* If either of both functions is old style, apply the default
117 * promotions to the parameter type.
119 if (F1->Flags & FD_OLDSTYLE) {
120 if (IsClassInt (Type1)) {
121 Type1 = IntPromotion (Type1);
124 if (F2->Flags & FD_OLDSTYLE) {
125 if (IsClassInt (Type2)) {
126 Type2 = IntPromotion (Type2);
130 /* Compare this field */
131 if (TypeCmp (Type1, Type2) < TC_EQUAL) {
132 /* Field types not equal */
136 /* Get the pointers to the next fields */
137 Sym1 = Sym1->NextSym;
138 Sym2 = Sym2->NextSym;
141 /* Check both pointers against NULL or a non parameter to compare the
144 return (Sym1 == 0 || (Sym1->Flags & SC_PARAM) == 0) &&
145 (Sym2 == 0 || (Sym2->Flags & SC_PARAM) == 0);
150 static int EqualSymTables (SymTable* Tab1, SymTable* Tab2)
151 /* Compare two symbol tables. Return 1 if they are equal and 0 otherwise */
153 /* Compare the parameter lists */
154 SymEntry* Sym1 = Tab1->SymHead;
155 SymEntry* Sym2 = Tab2->SymHead;
157 /* Compare the fields */
158 while (Sym1 && Sym2) {
160 /* Compare the names of this field */
161 if (!HasAnonName (Sym1) || !HasAnonName (Sym2)) {
162 if (strcmp (Sym1->Name, Sym2->Name) != 0) {
163 /* Names are not identical */
168 /* Compare the types of this field */
169 if (TypeCmp (Sym1->Type, Sym2->Type) < TC_EQUAL) {
170 /* Field types not equal */
174 /* Get the pointers to the next fields */
175 Sym1 = Sym1->NextSym;
176 Sym2 = Sym2->NextSym;
179 /* Check both pointers against NULL to compare the field count */
180 return (Sym1 == 0 && Sym2 == 0);
185 static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
186 /* Recursively compare two types. */
188 unsigned Indirections;
189 unsigned ElementCount;
198 /* Initialize stuff */
202 /* Compare two types. Determine, where they differ */
203 while (lhs->C != T_END) {
205 TypeCode LeftType, RightType;
206 TypeCode LeftSign, RightSign;
207 TypeCode LeftQual, RightQual;
208 long LeftCount, RightCount;
210 /* Check if the end of the type string is reached */
211 if (rhs->C == T_END) {
212 /* End of comparison reached */
216 /* Get the raw left and right types, signs and qualifiers */
217 LeftType = GetType (lhs);
218 RightType = GetType (rhs);
219 LeftSign = GetSignedness (lhs);
220 RightSign = GetSignedness (rhs);
221 LeftQual = GetQualifier (lhs);
222 RightQual = GetQualifier (rhs);
224 /* If the left type is a pointer and the right is an array, both
227 if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) {
228 RightType = T_TYPE_PTR;
231 /* If the raw types are not identical, the types are incompatible */
232 if (LeftType != RightType) {
233 SetResult (Result, TC_INCOMPATIBLE);
237 /* On indirection level zero, a qualifier or sign difference is
238 * accepted. The types are no longer equal, but compatible.
240 if (LeftSign != RightSign) {
241 if (ElementCount == 0) {
242 SetResult (Result, TC_SIGN_DIFF);
244 SetResult (Result, TC_INCOMPATIBLE);
248 if (LeftQual != RightQual) {
249 /* On the first indirection level, different qualifiers mean
250 * that the types are still compatible. On the second level,
251 * this is a (maybe minor) error, so we create a special
252 * return code, since a qualifier is dropped from a pointer.
253 * Starting from the next level, the types are incompatible
254 * if the qualifiers differ.
256 /* printf ("Ind = %d %06X != %06X\n", Indirections, LeftQual, RightQual); */
257 switch (Indirections) {
260 SetResult (Result, TC_STRICT_COMPATIBLE);
264 /* A non const value on the right is compatible to a
265 * const one to the left, same for volatile.
267 if ((LeftQual & T_QUAL_CONST) < (RightQual & T_QUAL_CONST) ||
268 (LeftQual & T_QUAL_VOLATILE) < (RightQual & T_QUAL_VOLATILE)) {
269 SetResult (Result, TC_QUAL_DIFF);
271 SetResult (Result, TC_STRICT_COMPATIBLE);
276 SetResult (Result, TC_INCOMPATIBLE);
281 /* Check for special type elements */
289 /* Compare the function descriptors */
290 F1 = GetFuncDesc (lhs);
291 F2 = GetFuncDesc (rhs);
293 /* If one of both functions has an empty parameter list (which
294 * does also mean, it is not a function definition, because the
295 * flag is reset in this case), it is considered equal to any
296 * other definition, provided that the other has no default
297 * promotions in the parameter list. If none of both parameter
298 * lists is empty, we have to check the parameter lists and
301 if (F1->Flags & FD_EMPTY) {
302 if ((F2->Flags & FD_EMPTY) == 0) {
303 if (ParamsHaveDefaultPromotions (F2)) {
305 SetResult (Result, TC_INCOMPATIBLE);
309 } else if (F2->Flags & FD_EMPTY) {
310 if (ParamsHaveDefaultPromotions (F1)) {
312 SetResult (Result, TC_INCOMPATIBLE);
317 /* Check the remaining flags */
318 if ((F1->Flags & ~FD_IGNORE) != (F2->Flags & ~FD_IGNORE)) {
320 SetResult (Result, TC_INCOMPATIBLE);
324 /* Compare the parameter lists */
325 if (EqualFuncParams (F1, F2) == 0) {
326 /* Parameter list is not identical */
327 SetResult (Result, TC_INCOMPATIBLE);
332 /* Keep on and compare the return type */
336 /* Check member count */
337 LeftCount = GetElementCount (lhs);
338 RightCount = GetElementCount (rhs);
339 if (LeftCount != UNSPECIFIED &&
340 RightCount != UNSPECIFIED &&
341 LeftCount != RightCount) {
342 /* Member count given but different */
343 SetResult (Result, TC_INCOMPATIBLE);
350 /* Compare the fields recursively. To do that, we fetch the
351 * pointer to the struct definition from the type, and compare
354 Sym1 = GetSymEntry (lhs);
355 Sym2 = GetSymEntry (rhs);
357 /* If one symbol has a name, the names must be identical */
358 if (!HasAnonName (Sym1) || !HasAnonName (Sym2)) {
359 if (strcmp (Sym1->Name, Sym2->Name) != 0) {
360 /* Names are not identical */
361 SetResult (Result, TC_INCOMPATIBLE);
366 /* Get the field tables from the struct entry */
367 Tab1 = Sym1->V.S.SymTab;
368 Tab2 = Sym2->V.S.SymTab;
370 /* One or both structs may be forward definitions. In this case,
371 * the symbol tables are both non existant. Assume that the
372 * structs are equal in this case.
374 if (Tab1 != 0 && Tab2 != 0) {
376 if (EqualSymTables (Tab1, Tab2) == 0) {
377 /* Field lists are not equal */
378 SetResult (Result, TC_INCOMPATIBLE);
384 /* Structs are equal */
388 /* Next type string element */
394 /* Check if end of rhs reached */
395 if (rhs->C == T_END) {
396 SetResult (Result, TC_EQUAL);
398 SetResult (Result, TC_INCOMPATIBLE);
404 typecmp_t TypeCmp (const Type* lhs, const Type* rhs)
405 /* Compare two types and return the result */
407 /* Assume the types are identical */
408 typecmp_t Result = TC_IDENTICAL;
411 printf ("Left : "); PrintRawType (stdout, lhs);
412 printf ("Right: "); PrintRawType (stdout, rhs);
415 /* Recursively compare the types if they aren't identical */
417 DoCompare (lhs, rhs, &Result);
420 /* Return the result */