Exemple #1
0
BOOLEAN assignDiscardsConst(TYPE *dest, TYPE *source)
{
    source = basetype(source);
    dest = basetype(dest);
    if (!ispointer(source) || !ispointer(dest))
        return FALSE;
    while (TRUE)
    {
        BOOLEAN destc = FALSE;
        BOOLEAN sourcc = FALSE;
        BOOLEAN done = FALSE;
        while (!done)
        {
            switch(dest->type)
            {
                case bt_const:
                    destc = TRUE;
                case bt_restrict:
                case bt_volatile:
                case bt_static:
                case bt_typedef:
                case bt_lrqual:
                case bt_rrqual:
                case bt_derivedfromtemplate:
                    dest = dest->btp;
                    break;
                default:
                    done = TRUE;
                    break;
            }
        }
        done = FALSE;
        while (!done)
        {
            switch(source->type)
            {
                case bt_const:
                    sourcc = TRUE;
                case bt_restrict:
                case bt_volatile:
                case bt_static:
                case bt_typedef:
                case bt_lrqual:
                case bt_rrqual:
                    source = source->btp;
                    break;
                default:
                    done = TRUE;
                    break;
            }
        }
        if (sourcc && !destc)
            return TRUE;
        if (source->type != bt_pointer || dest->type != bt_pointer)
            return FALSE;
        dest = dest->btp;
        source = source->btp;
    }
}
Exemple #2
0
/**
 * Used by #DNA_struct_get_compareflags (below) to recursively mark all structs
 * containing a field of type structnr as changed between old and current SDNAs.
 */
static void recurs_test_compflags(const SDNA *sdna, char *compflags, int structnr)
{
	int a, b, typenr, elems;
	const short *sp;
	const char *cp;
	
	/* check all structs, test if it's inside another struct */
	sp = sdna->structs[structnr];
	typenr = sp[0];
	
	for (a = 0; a < sdna->nr_structs; a++) {
		if ((a != structnr) && (compflags[a] == SDNA_CMP_EQUAL)) {
			sp = sdna->structs[a];
			elems = sp[1];
			sp += 2;
			for (b = 0; b < elems; b++, sp += 2) {
				if (sp[0] == typenr) {
					cp = sdna->names[sp[1]];
					if (!ispointer(cp)) {
						compflags[a] = SDNA_CMP_NOT_EQUAL;
						recurs_test_compflags(sdna, compflags, a);
					}
				}
			}
		}
	}
	
}
Exemple #3
0
/**
 * Returns the size of struct fields of the specified type and name.
 *
 * \param type  Index into sdna->types/typelens
 * \param name  Index into sdna->names,
 * needed to extract possible pointer/array information.
 */
static int elementsize(const SDNA *sdna, short type, short name)
{
	int mul, namelen, len;
	const char *cp;
	
	cp = sdna->names[name];
	len = 0;
	
	namelen = strlen(cp);
	/* is it a pointer or function pointer? */
	if (ispointer(cp)) {
		/* has the name an extra length? (array) */
		mul = 1;
		if (cp[namelen - 1] == ']') {
			mul = DNA_elem_array_size(cp);
		}
		
		len = sdna->pointerlen * mul;
	}
	else if (sdna->typelens[type]) {
		/* has the name an extra length? (array) */
		mul = 1;
		if (cp[namelen - 1] == ']') {
			mul = DNA_elem_array_size(cp);
		}
		
		len = mul * sdna->typelens[type];
		
	}
	
	return len;
}
Exemple #4
0
BOOLEAN matchingCharTypes(TYPE *typ1, TYPE *typ2)
{
    if (isref(typ1))
        typ1 = basetype(typ1)->btp;
    if (isref(typ2))
        typ2 = basetype(typ2)->btp;
        
    while (ispointer(typ1) && ispointer(typ2))
    {
        typ1 = basetype(typ1)->btp;
        typ2 = basetype(typ2)->btp;
    }
    typ1 = basetype(typ1);
    typ2 = basetype(typ2);
    if (typ1->type == bt_char)
    {
        if (cparams.prm_charisunsigned)
        {
            if (typ2->type == bt_unsigned_char)
                return TRUE;
        }
        else
        {
            if (typ2->type == bt_signed_char)
                return TRUE;
        }
    }
    else if (typ2->type == bt_char)
    {   
        if (cparams.prm_charisunsigned)
        {
            if (typ1->type == bt_unsigned_char)
                return TRUE;
        }
        else
        {
            if (typ1->type == bt_signed_char)
                return TRUE;
        }
    }
    return FALSE;
}
Exemple #5
0
void typenumptr(char *buf, TYPE *tp)
{
    char bf[256], *p = bf;
    p = putpointer(p, tp);
    tp = enumConst(buf, tp->btp);
    while (ispointer(tp))
    {
        p = putpointer(p, tp);
        tp = enumConst(buf, tp->btp);
//		tp = tp->btp;
    }
    typenum(buf, tp);
    strcat(buf, bf);
}
Exemple #6
0
BOOLEAN ispointer(TYPE *tp)
{
    tp = basetype(tp);
    switch(tp->type)
    {
        case bt_far:
        case bt_pointer:
        case bt_seg:
            return TRUE;
        case bt_templateparam:
            if (tp->templateParam->p->type == kw_int)
                return ispointer(tp->templateParam->p->byNonType.tp);
            return FALSE;
        default:
            return FALSE;
    }
}
Exemple #7
0
SYMBOL *getFunctionSP(TYPE **tp)
{
    TYPE *btp = basetype(*tp);
    BOOLEAN pointer = ispointer(btp);
    if (pointer)
    {
        btp = basetype(btp)->btp;
    }
    if (isfunction(btp))
    {
        *tp = btp;
        return basetype(btp)->sp;
    }
    else if (btp->type == bt_aggregate)
    {
        return btp->sp;
    }
    return NULL;
}
Exemple #8
0
BOOL comparetypes(TYPE *typ1, TYPE *typ2, int exact)
{
    if (typ1->type == bt_any || typ2->type == bt_any)
        return TRUE;
    if (typ1->type == bt_typedef)
        typ1 = basetype(typ1);
    if (typ2->type == bt_typedef)
        typ2 = basetype(typ2);
    if (isref(typ1))
        typ1 = basetype(typ1)->btp;
    if (isref(typ2))
        typ2 = basetype(typ2)->btp;
    if (ispointer(typ1) && ispointer(typ2))
        if (exact)
        {
            int arr = FALSE;
            int first = TRUE;
            while (ispointer(typ1) && ispointer(typ2))
            {
                if (!first && (exact == 1))
                    if (isconst(typ2) && !isconst(typ1) || isvolatile(typ2) && !isvolatile(typ1))
                        return FALSE;
                first = FALSE;
                typ1 = basetype(typ1);
                typ2 = basetype(typ2);
                if (typ1->type != typ2->type)
                    return FALSE;
                if (arr && typ1->array != typ2->array)	
                    return FALSE;
                if (arr && typ1->size != typ2->size)
                    return FALSE;
                arr |= typ1->array | typ2->array;
                typ1 = typ1->btp;
                typ2 = typ2->btp;				
            }
            if ((exact == 1) && (isconst(typ2) && !isconst(typ1) || isvolatile(typ2) && !isvolatile(typ1)))
                return FALSE;
            return comparetypes(typ1, typ2, TRUE);
        }
            
        else
            return TRUE;
    
    typ1 = basetype(typ1);
    typ2 = basetype(typ2);
    if (exact && (isfunction(typ1) || isfuncptr(typ1)) && (isfunction(typ2) || isfuncptr(typ2)))
    {
        HASHREC *hr1;
        HASHREC *hr2;
        typ1 = basetype(typ1);
        typ2 = basetype(typ2);
        if (ispointer(typ1))
            typ1 = basetype(typ1->btp);
        if (ispointer(typ2))
            typ2 = basetype(typ2->btp);
        if (!comparetypes(typ1->btp, typ2->btp, exact))
            return FALSE;
        hr1 = typ1->syms->table[0];
        hr2 = typ2->syms->table[0];
        while (hr1 && hr2)
        {
            SYMBOL *sp1 = (SYMBOL *)hr1->p;
            SYMBOL *sp2 = (SYMBOL *)hr2->p;
            if (!comparetypes(sp1->tp, sp2->tp, exact))
                return FALSE;
            hr1 = hr1->next;
            hr2 = hr2->next;
        }
        if (hr1 || hr2)
            return FALSE;
        return TRUE;
    }
    if (cparams.prm_cplusplus)
    {
        if (typ1->scoped != typ2->scoped)
            return FALSE;
        if (typ1->type == bt_enum)
        {
            if (typ2->type == bt_enum)
                return typ1->sp == typ2->sp;
            else
                return isint(typ2);
        }
        else if (typ2->type == bt_enum)
        {
            return isint(typ1);
        }
        if (typ1->type == typ2->type && typ1->type == bt_memberptr)
        {
            if (typ1->sp != typ2->sp)
            {
                if (classRefCount(typ2->sp, typ1->sp) != 1)
                    return FALSE;
            }
            return comparetypes(typ1->btp, typ2->btp, exact);
        }
    }
    if (typ1->type == typ2->type && (isstructured(typ1) || exact && typ1->type == bt_enum))
        return typ1->sp == typ2->sp;
    if (typ1->type == typ2->type || !exact && isarithmetic(typ2) && isarithmetic(typ1))
        return TRUE;
    if (isfunction(typ1) && isfunction(typ2) && 
        typ1->sp->linkage == typ2->sp->linkage)
        return TRUE;
    else if (!exact && (ispointer(typ1) && (isfuncptr(typ2) || isfunction(typ2) || isint(typ2))
             || ispointer(typ2) && (isfuncptr(typ1) || isfunction(typ1) || isint(typ1))))
            return (TRUE);
    else if (typ1->type == bt_enum && isint(typ2))
    {
        return TRUE;
    }
    else if (typ2->type == bt_enum && isint(typ1))
    {
        return TRUE;
    }
    return FALSE;
}
Exemple #9
0
BOOLEAN isarray(TYPE *tp)
{
    tp = basetype(tp);
    return ispointer(tp) && tp->array;		
}
Exemple #10
0
BOOLEAN isfuncptr(TYPE *tp)
{
    tp = basetype(tp);
    return ispointer(tp) && tp->btp && isfunction(tp->btp);
}
Exemple #11
0
BOOLEAN isvoidptr(TYPE *tp)
{
    tp = basetype(tp);
    return ispointer(tp) && isvoid(tp->btp);
}
Exemple #12
0
TYPE *destSize(TYPE *tp1, TYPE *tp2, EXPRESSION **exp1, EXPRESSION **exp2, BOOLEAN minimizeInt, TYPE *atp)
/*
 * compare two types and determine if they are compatible for purposes
 * of the current operation.  Return an appropriate type.  Also checks for
 * dangerous pointer conversions...
 */
{
    int isctp1, isctp2;
    if (tp1->type == bt_any)
        return tp1;
    if (tp2->type == bt_any)
        return tp2;
    if (isvoid(tp1) || isvoid(tp2))
    {
        error(ERR_NOT_AN_ALLOWED_TYPE);
        return tp1;
    }
    if (isref(tp1))
        tp1 = basetype(tp1)->btp;
    if (isref(tp2))
        tp2 = basetype(tp2)->btp;
    tp1 = basetype(tp1);
    tp2 = basetype(tp2);
    isctp1 = isarithmetic(tp1);
    isctp2 = isarithmetic(tp2);
    
/*    if (isctp1 && isctp2 && tp1->type == tp2->type)
        return tp1 ;
*/
    if (tp1->type >= bt_float || tp2->type >= bt_float) {
    
        int isim1 = tp1->type >= bt_float_imaginary && tp1->type <= bt_long_double_imaginary;
        int isim2 = tp2->type >= bt_float_imaginary && tp2->type <= bt_long_double_imaginary;
        if (isim1 && !isim2 && tp2->type < bt_float_imaginary)
        {
            TYPE *tp ;
            if (tp1->type == bt_long_double_imaginary || tp2->type == bt_long_double)
                tp = &stdlongdoublecomplex;
            else if (tp1->type == bt_double_imaginary || tp2->type == bt_double
                || tp1->type == bt_long_long || tp1->type == bt_unsigned_long_long)
                tp = &stddoublecomplex;
            else
                tp = &stdfloatcomplex;
            if (exp1)
                 cast(tp, exp1);
            if (exp2)
                 cast(tp, exp2);
            return tp;
        }
        else if (isim2 && !isim1 && tp1->type < bt_float_imaginary)
        {
            TYPE *tp ;
            if (tp2->type == bt_long_double_imaginary || tp1->type == bt_long_double)
                tp = &stdlongdoublecomplex;
            else if (tp2->type == bt_double_imaginary || tp1->type == bt_double 
                || tp1->type == bt_long_long || tp1->type == bt_unsigned_long_long)
                tp = &stddoublecomplex;
            else
                tp = &stdfloatcomplex;
            if (exp1)
                 cast(tp, exp1);
            if (exp2)
                 cast(tp, exp2);
            return tp;
        }
        else if (tp1->type > tp2->type)
        {
            if (exp2)
                   cast(tp1, exp2);
        }
        else if (tp1->type < tp2->type)
        {
            if (exp1)
                cast(tp2, exp1);
        }

        if (tp1->type == bt_long_double_complex && isctp2)
            return tp1;
        if (tp2->type == bt_long_double_complex && isctp1)
            return tp2;
        
        if (tp1->type == bt_long_double_imaginary && isim2)
            return tp1;
        if (tp2->type == bt_long_double_imaginary && isim1)
            return tp2;
        if (tp1->type == bt_long_double && isctp2)
            return tp1;
        if (tp2->type == bt_long_double && isctp1)
            return tp2;
        if (tp1->type == bt_double_complex && isctp2)
            return tp1;
        if (tp2->type == bt_double_complex && isctp1)
            return tp2;
        if (tp1->type == bt_double_imaginary && isim2)
            return tp1;
        if (tp2->type == bt_double_imaginary && isim1)
            return tp2;
        if (tp1->type == bt_double && isctp2)
            return tp1;
        if (tp2->type == bt_double && isctp1)
            return tp2;
        if (tp1->type == bt_float_complex && isctp2)
            return tp1;
        if (tp2->type == bt_float_complex && isctp1)
            return tp2;
        if (tp1->type == bt_float_imaginary && isim2)
            return tp1;
        if (tp2->type == bt_float_imaginary && isim1)
            return tp2;
        if (tp1->type == bt_float && isctp2)
            return tp1;
        if (tp2->type == bt_float && isctp1)
            return tp2;
    }
    if (isctp1 && isctp2) {
        TYPE *rv ;
       enum e_bt t1, t2;
       t1 = tp1->type;
       t2 = tp2->type;
       /*
       if (cparams.prm_cplusplus && (t1 == bt_enum || t2 == bt_enum))
       {
           if (t1 == t2)
        {
            if (tp1->sp->mainsym == tp2->sp->mainsym)
            {
                return tp1;
            }
            genmismatcherror(ERR_ENUMMISMATCH, tp1, tp2);
        }			
       }
       */
        if (t1 == bt_enum)
            t1= bt_int;
        if (t2 == bt_enum)
            t2= bt_int;
        if (t1 == bt_wchar_t)
            t1 = bt_unsigned;
        if (t2 == bt_wchar_t)
            t2 = bt_unsigned;
        if (t1 < bt_int)
            t1= bt_int;
        if (t2 < bt_int)
            t2= bt_int;
        t1 = imax(t1, t2);
       rv = inttype(t1);
       if (rv->type != tp1->type && exp1)
         cast(rv, exp1);
       if (rv->type != tp2->type && exp2)
         cast(rv,exp2);
       return rv;
    } else { /* have a pointer or other exceptional case*/
        if (tp1->type == bt_void && tp2->type == bt_void)
            return tp1;
        if (tp1->type <= bt_unsigned_long_long && ispointer(tp2))
        {
            if (!ispointer(tp1))
                cast(tp2, exp1);
            return tp2;
        }
        if (tp2->type <= bt_unsigned_long_long && ispointer(tp1))
        {
            if (!ispointer(tp2))
                cast(tp1, exp2);
            return tp1;
        }
        if (isstructured(tp1)) {
            return tp2;
/*
            if (comparetypes(tp1, tp2, FALSE))
                return tp1;
            if (cparams.prm_cplusplus) {
                cppcast(tp2, tp1, exp1, FALSE, ERR_CPPMISMATCH);
            } else

                error(ERR_ILL_STRUCTURE_OPERATION);
            return tp2;
*/
        }
        if (isstructured(tp2)) {
            return tp1;
/*			
            if (comparetypes(tp1, tp2, FALSE))
                return tp2;
            if (cparams.prm_cplusplus) {
                cppcast(tp1, tp2, exp1, FALSE, ERR_CPPMISMATCH);
            } else

                error(ERR_ILL_STRUCTURE_OPERATION);
            return tp1;
*/
        }

        if (isfunction(tp1))
            if (isfunction(tp2) || ispointer(tp2))
                return tp1;
        if (isfunction(tp2))
            if (isfunction(tp1) || ispointer(tp1))
                return tp2;
        if (ispointer(tp1))
            if (ispointer(tp2))
            {
/*				if (tp1->type != tp2->type || !comparetypes(tp1->btp, tp2->btp, TRUE))
                    generror(ERR_SUSPICIOUS, 0, 0);
*/
                 return tp1;
            }
    }
    return tp1;
}
Exemple #13
0
static BOOLEAN is_constructible(LEXEME **lex, SYMBOL *funcsp, SYMBOL *sym, TYPE **tp, EXPRESSION **exp)
{
    INITLIST *lst;
    BOOLEAN rv = FALSE;
    FUNCTIONCALL funcparams;
    memset(&funcparams, 0, sizeof(funcparams));
    funcparams.sp = sym;
    *lex = getTypeList(*lex, funcsp, &funcparams.arguments);
    lst = funcparams.arguments;
    while (lst)
    {
        lst->tp = PerformDeferredInitialization(lst->tp, NULL);
        lst = lst->next;
        
    }
    if (funcparams.arguments)        
    {
        TYPE *tp2 = funcparams.arguments->tp;
        if (isarray(tp2))
        {
            while (isarray(tp2) && tp2->size != 0)
                tp2 = tp2->btp;
                
            if (isarray(tp2))
            {
                tp2 = FALSE;
            }
        }
        if (tp2)
        {
            if (isarithmetic(tp2) || ispointer(tp2) || basetype(tp2)->type == bt_enum)
            {
                if (!funcparams.arguments->next)
                {
                    rv = TRUE;
                }
                else if (!funcparams.arguments->next->next)
                {
                    rv = comparetypes(tp2, funcparams.arguments->next->tp, TRUE);
                }
            }
            else if (isref(tp2))
            {
                if (funcparams.arguments->next && !funcparams.arguments->next->next)
                {
                    rv = comparetypes(tp2, funcparams.arguments->next->tp, TRUE);
                }
            }
            else if (isstructured(tp2))
            {
                TYPE *ctp = tp2;
                EXPRESSION *cexp = NULL;
                SYMBOL *cons = search(overloadNameTab[CI_CONSTRUCTOR], basetype(tp2)->syms);
                funcparams.thisptr = intNode(en_c_i, 0);
                funcparams.thistp = Alloc(sizeof(TYPE));
                funcparams.thistp->type = bt_pointer;
                funcparams.thistp->btp = basetype(tp2);
                funcparams.thistp->size = getSize(bt_pointer);
                funcparams.ascall = TRUE;
                funcparams.arguments = funcparams.arguments->next;
                rv = GetOverloadedFunction(tp, &funcparams.fcall, cons, &funcparams, NULL, FALSE, 
                              FALSE, FALSE, _F_SIZEOF) != NULL;
            }
        }
    }
    *exp = intNode(en_c_i, rv);
    *tp = &stdint;
    return TRUE;
}
Exemple #14
0
/**
 * Constructs and returns an array of byte flags with one element for each struct in oldsdna,
 * indicating how it compares to newsdna:
 */
const char *DNA_struct_get_compareflags(const SDNA *oldsdna, const SDNA *newsdna)
{
	int a, b;
	const short *sp_old, *sp_new;
	const char *str1, *str2;
	char *compflags;
	
	if (oldsdna->nr_structs == 0) {
		printf("error: file without SDNA\n");
		return NULL;
	}

	compflags = MEM_callocN(oldsdna->nr_structs, "compflags");

	/* we check all structs in 'oldsdna' and compare them with 
	 * the structs in 'newsdna'
	 */
	unsigned int newsdna_index_last = 0;
	
	for (a = 0; a < oldsdna->nr_structs; a++) {
		sp_old = oldsdna->structs[a];
		
		/* search for type in cur */
		int sp_new_index = DNA_struct_find_nr_ex(newsdna, oldsdna->types[sp_old[0]], &newsdna_index_last);

		/* The next indices will almost always match */
		newsdna_index_last++;

		if (sp_new_index != -1) {
			sp_new = newsdna->structs[sp_new_index];
			/* initial assumption */
			compflags[a] = SDNA_CMP_NOT_EQUAL;
			
			/* compare length and amount of elems */
			if (sp_new[1] == sp_old[1]) {
				if (newsdna->typelens[sp_new[0]] == oldsdna->typelens[sp_old[0]]) {

					/* same length, same amount of elems, now per type and name */
					b = sp_old[1];
					sp_old += 2;
					sp_new += 2;
					while (b > 0) {
						str1 = newsdna->types[sp_new[0]];
						str2 = oldsdna->types[sp_old[0]];
						if (strcmp(str1, str2) != 0) break;

						str1 = newsdna->names[sp_new[1]];
						str2 = oldsdna->names[sp_old[1]];
						if (strcmp(str1, str2) != 0) break;

						/* same type and same name, now pointersize */
						if (ispointer(str1)) {
							if (oldsdna->pointerlen != newsdna->pointerlen) break;
						}

						b--;
						sp_old += 2;
						sp_new += 2;
					}
					if (b == 0) {
						/* no differences found */
						compflags[a] = SDNA_CMP_EQUAL;
					}

				}
			}
			
		}
	}

	/* first struct in util.h is struct Link, this is skipped in compflags (als # 0).
	 * was a bug, and this way dirty patched! Solve this later....
	 */
	compflags[0] = SDNA_CMP_EQUAL;

	/* Because structs can be inside structs, we recursively
	 * set flags when a struct is altered
	 */
	for (a = 0; a < oldsdna->nr_structs; a++) {
		if (compflags[a] == SDNA_CMP_NOT_EQUAL) {
			recurs_test_compflags(oldsdna, compflags, a);
		}
	}
	
#if 0
	for (a = 0; a < oldsdna->nr_structs; a++) {
		if (compflags[a] == SDNA_CMP_NOT_EQUAL) {
			spold = oldsdna->structs[a];
			printf("changed: %s\n", oldsdna->types[spold[0]]);
		}
	}
#endif

	return compflags;
}
Exemple #15
0
BOOLEAN comparetypes(TYPE *typ1, TYPE *typ2, int exact)
{
    if (typ1->type == bt_any || typ2->type == bt_any)
        return TRUE;
    while (typ1->type == bt_typedef)
        typ1 = basetype(typ1);
    while (typ2->type == bt_typedef)
        typ2 = basetype(typ2);
    typ1 = replaceTemplateSelector(typ1);
    typ2 = replaceTemplateSelector(typ2);
    if (isDerivedFromTemplate(typ1))
        typ1 = typ1->btp;
    if (isDerivedFromTemplate(typ2))
        typ2 = typ2->btp;
    while (isref(typ1))
        typ1 = basetype(typ1)->btp;
    while (isref(typ2))
        typ2 = basetype(typ2)->btp;
    while (typ1->type == bt_typedef)
        typ1 = basetype(typ1);
    while (typ2->type == bt_typedef)
        typ2 = basetype(typ2);
    if (typ1->type == bt_templateselector && typ2->type == bt_templateselector)
        return templateselectorcompare(typ1->sp->templateSelector, typ2->sp->templateSelector);
    if (typ1->type == bt_templatedecltype && typ2->type == bt_templatedecltype)
        return templatecompareexpressions(typ1->templateDeclType, typ2->templateDeclType);
    if (ispointer(typ1) && ispointer(typ2))
    {
        if (exact)
        {
            int arr = FALSE;
            int first = TRUE;
            while (ispointer(typ1) && ispointer(typ2))
            {
                if (!first && (exact == 1))
                    if ((isconst(typ2) && !isconst(typ1)) || (isvolatile(typ2) && !isvolatile(typ1)))
                        return FALSE;
                first = FALSE;
                typ1 = basetype(typ1);
                typ2 = basetype(typ2);
                if (typ1->type != typ2->type)
                    return FALSE;
                if (arr && typ1->array != typ2->array)	
                    return FALSE;
                if (arr && typ1->size != typ2->size)
                    return FALSE;
                arr |= typ1->array | typ2->array;
                typ1 = typ1->btp;
                typ2 = typ2->btp;				
            }
            if (exact == 1 && ((isconst(typ2) && !isconst(typ1)) || (isvolatile(typ2) && !isvolatile(typ1))))
                return FALSE;
            return comparetypes(typ1, typ2, TRUE);
        }
            
        else
            return TRUE;
    }
    typ1 = basetype(typ1);
    typ2 = basetype(typ2);
    if (exact && (isfunction(typ1) || isfuncptr(typ1)) && (isfunction(typ2) || isfuncptr(typ2)))
    {
        HASHREC *hr1;
        HASHREC *hr2;
        typ1 = basetype(typ1);
        typ2 = basetype(typ2);
        if (ispointer(typ1))
            typ1 = basetype(typ1)->btp;
        if (ispointer(typ2))
            typ2 = basetype(typ2)->btp;
        if (!comparetypes(typ1->btp, typ2->btp, exact))
            return FALSE;
        if (!matchOverload(typ1, typ2, TRUE))
            return FALSE;
        return TRUE;
    }
    if (cparams.prm_cplusplus)
    {
        if (typ1->scoped != typ2->scoped)
            return FALSE;
        if (typ1->type == bt_enum)
        {
            if (typ2->type == bt_enum)
                return typ1->sp == typ2->sp;
            else
                return isint(typ2);
        }
        else if (typ2->type == bt_enum)
        {
            return isint(typ1);
        }
        if (typ1->type == typ2->type && typ1->type == bt_memberptr)
        {
            if (typ1->sp != typ2->sp)
            {
                if (classRefCount(typ1->sp, typ2->sp) != 1)
                    return FALSE;
            }
            return comparetypes(typ1->btp, typ2->btp, exact);
        }
    }
    if (typ1->type == typ2->type && (isstructured(typ1) || (exact && typ1->type == bt_enum)))
        return typ1->sp == typ2->sp;
    if (typ1->type == typ2->type || (!exact && isarithmetic(typ2) && isarithmetic(typ1)))
        return TRUE;
    if (isfunction(typ1) && isfunction(typ2) && 
        typ1->sp->linkage == typ2->sp->linkage)
        return TRUE;
    else if (!exact && ((ispointer(typ1) && (isfuncptr(typ2) || isfunction(typ2) || isint(typ2)))
             || (ispointer(typ2) && (isfuncptr(typ1) || isfunction(typ1) || isint(typ1)))))
            return (TRUE);
    else if (typ1->type == bt_enum && isint(typ2))
    {
        return TRUE;
    }
    else if (typ2->type == bt_enum && isint(typ1))
    {
        return TRUE;
    }
    return FALSE;
}