From: Chris Lattner Date: Mon, 14 Jan 2008 05:45:46 +0000 (+0000) Subject: Fix ASTContext::typesAreCompatible when analyzing a function type with X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1adb88370beab45af2f065afe86b51ccd59ec50d;p=clang Fix ASTContext::typesAreCompatible when analyzing a function type with proto and function type without proto. It would never call 'functionTypesAreCompatible' because they have different type classes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45952 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/ASTContext.cpp b/AST/ASTContext.cpp index 36d9241f92..28c2329058 100644 --- a/AST/ASTContext.cpp +++ b/AST/ASTContext.cpp @@ -1613,51 +1613,59 @@ bool ASTContext::typesAreCompatible(QualType lhs, QualType rhs) { // type is adjusted to "T" prior to any further analysis, the expression // designates the object or function denoted by the reference, and the // expression is an lvalue. - if (lcanon->getTypeClass() == Type::Reference) - lcanon = cast(lcanon)->getReferenceeType(); - if (rcanon->getTypeClass() == Type::Reference) - rcanon = cast(rcanon)->getReferenceeType(); + if (ReferenceType *RT = dyn_cast(lcanon)) + lcanon = RT->getReferenceeType(); + if (ReferenceType *RT = dyn_cast(rcanon)) + rcanon = RT->getReferenceeType(); + + Type::TypeClass LHSClass = lcanon->getTypeClass(); + Type::TypeClass RHSClass = rcanon->getTypeClass(); + + // We want to consider the two function types to be the same for these + // comparisons, just force one to the other. + if (LHSClass == Type::FunctionProto) LHSClass = Type::FunctionNoProto; + if (RHSClass == Type::FunctionProto) RHSClass = Type::FunctionNoProto; // If the canonical type classes don't match... - if (lcanon->getTypeClass() != rcanon->getTypeClass()) { + if (LHSClass != RHSClass) { // For Objective-C, it is possible for two types to be compatible // when their classes don't match (when dealing with "id"). If either type // is an interface, we defer to objcTypesAreCompatible(). if (lcanon->isObjCInterfaceType() || rcanon->isObjCInterfaceType()) return objcTypesAreCompatible(lcanon, rcanon); - // C99 6.7.2.2p4: Each enumerated type shall be compatible with char, - // a signed integer type, or an unsigned integer type. - // FIXME: need to check the size and ensure it's the same. - if ((lcanon->isEnumeralType() && rcanon->isIntegralType()) || - (rcanon->isEnumeralType() && lcanon->isIntegralType())) - return true; - + // C99 6.7.2.2p4: Each enumerated type shall be compatible with char, + // a signed integer type, or an unsigned integer type. + // FIXME: need to check the size and ensure it's the same. + if ((lcanon->isEnumeralType() && rcanon->isIntegralType()) || + (rcanon->isEnumeralType() && lcanon->isIntegralType())) + return true; + return false; } // The canonical type classes match. - switch (lcanon->getTypeClass()) { - case Type::Pointer: - return pointerTypesAreCompatible(lcanon, rcanon); - case Type::ConstantArray: - case Type::VariableArray: - return arrayTypesAreCompatible(lcanon, rcanon); - case Type::FunctionNoProto: - case Type::FunctionProto: - return functionTypesAreCompatible(lcanon, rcanon); - case Type::Tagged: // handle structures, unions - return tagTypesAreCompatible(lcanon, rcanon); - case Type::Builtin: - return builtinTypesAreCompatible(lcanon, rcanon); - case Type::ObjCInterface: - return interfaceTypesAreCompatible(lcanon, rcanon); - case Type::Vector: - case Type::OCUVector: - return vectorTypesAreCompatible(lcanon, rcanon); - case Type::ObjCQualifiedInterface: - return QualifiedInterfaceTypesAreCompatible(lcanon, rcanon); - default: - assert(0 && "unexpected type"); + switch (LHSClass) { + case Type::FunctionProto: assert(0 && "Canonicalized away above"); + case Type::Pointer: + return pointerTypesAreCompatible(lcanon, rcanon); + case Type::ConstantArray: + case Type::VariableArray: + return arrayTypesAreCompatible(lcanon, rcanon); + case Type::FunctionNoProto: + return functionTypesAreCompatible(lcanon, rcanon); + case Type::Tagged: // handle structures, unions + return tagTypesAreCompatible(lcanon, rcanon); + case Type::Builtin: + return builtinTypesAreCompatible(lcanon, rcanon); + case Type::ObjCInterface: + return interfaceTypesAreCompatible(lcanon, rcanon); + case Type::Vector: + case Type::OCUVector: + return vectorTypesAreCompatible(lcanon, rcanon); + case Type::ObjCQualifiedInterface: + return QualifiedInterfaceTypesAreCompatible(lcanon, rcanon); + default: + assert(0 && "unexpected type"); } return true; // should never get here... } diff --git a/test/Sema/function.c b/test/Sema/function.c index 751339b79a..3f6ad96637 100644 --- a/test/Sema/function.c +++ b/test/Sema/function.c @@ -3,3 +3,7 @@ void f(double a[restrict][5]); // should promote to restrict ptr. void f(double (* restrict a)[5]); +void g(int (*)(const void **, const void **)); +void g(int (*compar)()) { +} +