diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 7db6b1dfe923b..f03dcf05411df 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -1093,9 +1093,10 @@ static bool argTypeIsABIEquivalent(QualType SrcType, QualType DestType, return true; // Allow integral type mismatch if their size are equal. - if (SrcType->isIntegralType(Context) && DestType->isIntegralType(Context)) - if (Context.getTypeInfoInChars(SrcType).Width == - Context.getTypeInfoInChars(DestType).Width) + if ((SrcType->isIntegralType(Context) || SrcType->isEnumeralType()) && + (DestType->isIntegralType(Context) || DestType->isEnumeralType())) + if (Context.getTypeSizeInChars(SrcType) == + Context.getTypeSizeInChars(DestType)) return true; return Context.hasSameUnqualifiedType(SrcType, DestType); diff --git a/clang/test/Sema/warn-cast-function-type-strict.c b/clang/test/Sema/warn-cast-function-type-strict.c index b0a70cf324b71..c43e0f2fcbc63 100644 --- a/clang/test/Sema/warn-cast-function-type-strict.c +++ b/clang/test/Sema/warn-cast-function-type-strict.c @@ -29,8 +29,17 @@ f8 *h; f9 *i; f10 *j; +enum E : long; +int efunc(enum E); + +// Produce the underlying `long` type implicitly. +enum E2 { big = __LONG_MAX__ }; +int e2func(enum E2); + void foo(void) { a = (f1 *)x; + a = (f1 *)efunc; // strict-warning {{cast from 'int (*)(enum E)' to 'f1 *' (aka 'int (*)(long)') converts to incompatible function type}} + a = (f1 *)e2func; // strict-warning {{cast from 'int (*)(enum E2)' to 'f1 *' (aka 'int (*)(long)') converts to incompatible function type}} b = (f2 *)x; /* expected-warning {{cast from 'int (*)(long)' to 'f2 *' (aka 'int (*)(void *)') converts to incompatible function type}} */ c = (f3 *)x; /* strict-warning {{cast from 'int (*)(long)' to 'f3 *' (aka 'int (*)()') converts to incompatible function type}} */ d = (f4 *)x; /* expected-warning {{cast from 'int (*)(long)' to 'f4 *' (aka 'void (*)()') converts to incompatible function type}} */ diff --git a/clang/test/Sema/warn-cast-function-type.c b/clang/test/Sema/warn-cast-function-type.c index 09d169026b1c8..d474dbf48b897 100644 --- a/clang/test/Sema/warn-cast-function-type.c +++ b/clang/test/Sema/warn-cast-function-type.c @@ -19,8 +19,17 @@ f5 *e; f6 *f; f7 *g; +enum E : long; +int efunc(enum E); + +// Produce the underlying `long` type implicitly. +enum E2 { big = __LONG_MAX__ }; +int e2func(enum E2); + void foo(void) { a = (f1 *)x; + a = (f1 *)efunc; // enum is just type system sugar, still passed as a long. + a = (f1 *)e2func; // enum is just type system sugar, still passed as a long. b = (f2 *)x; /* expected-warning {{cast from 'int (*)(long)' to 'f2 *' (aka 'int (*)(void *)') converts to incompatible function type}} */ c = (f3 *)x; d = (f4 *)x; /* expected-warning {{cast from 'int (*)(long)' to 'f4 *' (aka 'void (*)()') converts to incompatible function type}} */ diff --git a/clang/test/SemaCXX/warn-cast-function-type-strict.cpp b/clang/test/SemaCXX/warn-cast-function-type-strict.cpp index 8887b3c4c5d53..9203c1aae8c90 100644 --- a/clang/test/SemaCXX/warn-cast-function-type-strict.cpp +++ b/clang/test/SemaCXX/warn-cast-function-type-strict.cpp @@ -29,8 +29,17 @@ struct S typedef void (S::*mf)(int); +enum E : long; +int efunc(E); + +// Produce the underlying `long` type implicitly. +enum E2 { big = __LONG_MAX__ }; +int e2func(E2); + void foo() { a = (f1 *)x; + a = (f1 *)efunc; // strict-warning {{cast from 'int (*)(E)' to 'f1 *' (aka 'int (*)(long)') converts to incompatible function type}} + a = (f1 *)e2func; // strict-warning {{cast from 'int (*)(E2)' to 'f1 *' (aka 'int (*)(long)') converts to incompatible function type}} b = (f2 *)x; // expected-warning {{cast from 'int (*)(long)' to 'f2 *' (aka 'int (*)(void *)') converts to incompatible function type}} b = reinterpret_cast(x); // expected-warning {{cast from 'int (*)(long)' to 'f2 *' (aka 'int (*)(void *)') converts to incompatible function type}} c = (f3 *)x; // strict-warning {{cast from 'int (*)(long)' to 'f3 *' (aka 'int (*)(...)') converts to incompatible function type}} diff --git a/clang/test/SemaCXX/warn-cast-function-type.cpp b/clang/test/SemaCXX/warn-cast-function-type.cpp index db2ee030fcbfc..5f450f25f3f68 100644 --- a/clang/test/SemaCXX/warn-cast-function-type.cpp +++ b/clang/test/SemaCXX/warn-cast-function-type.cpp @@ -28,8 +28,17 @@ struct S typedef void (S::*mf)(int); +enum E : long; +int efunc(E); + +// Produce the underlying `long` type implicitly. +enum E2 { big = __LONG_MAX__ }; +int e2func(E2); + void foo() { a = (f1 *)x; + a = (f1 *)efunc; // enum is just type system sugar, still passed as a long. + a = (f1 *)e2func; // enum is just type system sugar, still passed as a long. b = (f2 *)x; // expected-warning {{cast from 'int (*)(long)' to 'f2 *' (aka 'int (*)(void *)') converts to incompatible function type}} b = reinterpret_cast(x); // expected-warning {{cast from 'int (*)(long)' to 'f2 *' (aka 'int (*)(void *)') converts to incompatible function type}} c = (f3 *)x;