T = DataType;
while (T->C != T_END) {
if (IsTypePtr (T)) {
-
/* Calling convention qualifier on the pointer? */
if (IsQualCConv (T)) {
/* Pull the convention off of the pointer */
Q = T[0].C & T_QUAL_CCONV;
T[0].C &= ~T_QUAL_CCONV;
+
/* Pointer to a function which doesn't have an explicit convention? */
if (IsTypeFunc (T + 1)) {
if (IsQualCConv (T + 1)) {
- if (T[1].C == Q) {
- /* TODO: The end of Declarator() catches this error.
- ** Try to make it let the error be caught here, instead.
- */
+ if ((T[1].C & T_QUAL_CCONV) == Q) {
Warning ("Pointer duplicates function's calling convention");
} else {
- Error ("Mismatch between pointer's and function's calling conventions");
+ Error ("Function's and pointer's calling conventions are different");
}
} else {
if (Q == T_QUAL_FASTCALL && IsVariadicFunc (T + 1)) {
- Error ("Variadic-function pointers cannot be `__fastcall__'");
+ Error ("Variadic-function pointers cannot be __fastcall__");
} else {
/* Move the qualifier from the pointer to the function. */
T[1].C |= Q;
if (LeftQual != RightQual) {
/* On the first indirection level, different qualifiers mean
** that the types still are compatible. On the second level,
- ** that is a (maybe minor) error. We create a special return code
+ ** that is a (maybe minor) error. We create a special return-code
** if a qualifier is dropped from a pointer. But, different calling
** conventions are incompatible. Starting from the next level,
** the types are incompatible if the qualifiers differ.
SetResult (Result, TC_STRICT_COMPATIBLE);
}
+ if (LeftType != T_TYPE_FUNC) {
+ break;
+ }
+
/* If a calling convention wasn't set explicitly,
** then assume the default one.
*/
LeftQual &= T_QUAL_CCONV;
- if (LeftQual == 0) {
- LeftQual = AutoCDecl ? T_QUAL_CDECL : T_QUAL_FASTCALL;
+ if (LeftQual == T_QUAL_NONE) {
+ LeftQual = (AutoCDecl || IsVariadicFunc (lhs)) ? T_QUAL_CDECL : T_QUAL_FASTCALL;
}
RightQual &= T_QUAL_CCONV;
- if (RightQual == 0) {
- RightQual = AutoCDecl ? T_QUAL_CDECL : T_QUAL_FASTCALL;
+ if (RightQual == T_QUAL_NONE) {
+ RightQual = (AutoCDecl || IsVariadicFunc (rhs)) ? T_QUAL_CDECL : T_QUAL_FASTCALL;
}
- /* (If the objects actually aren't pointers to functions,
- ** then this test will pass anyway; and, more appropriate
- ** tests will be performed.)
- */
if (LeftQual == RightQual) {
break;
}