Made cc65 properly test variadic-function pointer assignments.

Improved some error messages.
This commit is contained in:
Greg King
2015-05-24 08:32:15 -04:00
parent 0bb3bafb3e
commit e72132c8ae
2 changed files with 13 additions and 16 deletions

View File

@@ -335,26 +335,23 @@ static void FixQualifiers (Type* DataType)
T = DataType; T = DataType;
while (T->C != T_END) { while (T->C != T_END) {
if (IsTypePtr (T)) { if (IsTypePtr (T)) {
/* Calling convention qualifier on the pointer? */ /* Calling convention qualifier on the pointer? */
if (IsQualCConv (T)) { if (IsQualCConv (T)) {
/* Pull the convention off of the pointer */ /* Pull the convention off of the pointer */
Q = T[0].C & T_QUAL_CCONV; Q = T[0].C & T_QUAL_CCONV;
T[0].C &= ~T_QUAL_CCONV; T[0].C &= ~T_QUAL_CCONV;
/* Pointer to a function which doesn't have an explicit convention? */ /* Pointer to a function which doesn't have an explicit convention? */
if (IsTypeFunc (T + 1)) { if (IsTypeFunc (T + 1)) {
if (IsQualCConv (T + 1)) { if (IsQualCConv (T + 1)) {
if (T[1].C == Q) { if ((T[1].C & T_QUAL_CCONV) == Q) {
/* TODO: The end of Declarator() catches this error.
** Try to make it let the error be caught here, instead.
*/
Warning ("Pointer duplicates function's calling convention"); Warning ("Pointer duplicates function's calling convention");
} else { } else {
Error ("Mismatch between pointer's and function's calling conventions"); Error ("Function's and pointer's calling conventions are different");
} }
} else { } else {
if (Q == T_QUAL_FASTCALL && IsVariadicFunc (T + 1)) { if (Q == T_QUAL_FASTCALL && IsVariadicFunc (T + 1)) {
Error ("Variadic-function pointers cannot be `__fastcall__'"); Error ("Variadic-function pointers cannot be __fastcall__");
} else { } else {
/* Move the qualifier from the pointer to the function. */ /* Move the qualifier from the pointer to the function. */
T[1].C |= Q; T[1].C |= Q;

View File

@@ -249,7 +249,7 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
if (LeftQual != RightQual) { if (LeftQual != RightQual) {
/* On the first indirection level, different qualifiers mean /* On the first indirection level, different qualifiers mean
** that the types still are compatible. On the second level, ** 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 ** if a qualifier is dropped from a pointer. But, different calling
** conventions are incompatible. Starting from the next level, ** conventions are incompatible. Starting from the next level,
** the types are incompatible if the qualifiers differ. ** the types are incompatible if the qualifiers differ.
@@ -272,22 +272,22 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
SetResult (Result, TC_STRICT_COMPATIBLE); SetResult (Result, TC_STRICT_COMPATIBLE);
} }
if (LeftType != T_TYPE_FUNC) {
break;
}
/* If a calling convention wasn't set explicitly, /* If a calling convention wasn't set explicitly,
** then assume the default one. ** then assume the default one.
*/ */
LeftQual &= T_QUAL_CCONV; LeftQual &= T_QUAL_CCONV;
if (LeftQual == 0) { if (LeftQual == T_QUAL_NONE) {
LeftQual = AutoCDecl ? T_QUAL_CDECL : T_QUAL_FASTCALL; LeftQual = (AutoCDecl || IsVariadicFunc (lhs)) ? T_QUAL_CDECL : T_QUAL_FASTCALL;
} }
RightQual &= T_QUAL_CCONV; RightQual &= T_QUAL_CCONV;
if (RightQual == 0) { if (RightQual == T_QUAL_NONE) {
RightQual = AutoCDecl ? T_QUAL_CDECL : T_QUAL_FASTCALL; 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) { if (LeftQual == RightQual) {
break; break;
} }