]> granicus.if.org Git - clang/commitdiff
Fix ASTContext::typesAreCompatible when analyzing a function type with
authorChris Lattner <sabre@nondot.org>
Mon, 14 Jan 2008 05:45:46 +0000 (05:45 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 14 Jan 2008 05:45:46 +0000 (05:45 +0000)
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

AST/ASTContext.cpp
test/Sema/function.c

index 36d9241f92d53d033b9b80b1abb648cb949d724f..28c2329058d614853f133f45f1182daf1dbaeeb7 100644 (file)
@@ -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<ReferenceType>(lcanon)->getReferenceeType();
-  if (rcanon->getTypeClass() == Type::Reference)
-    rcanon = cast<ReferenceType>(rcanon)->getReferenceeType();
+  if (ReferenceType *RT = dyn_cast<ReferenceType>(lcanon))
+    lcanon = RT->getReferenceeType();
+  if (ReferenceType *RT = dyn_cast<ReferenceType>(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...
 }
index 751339b79ab1693dd5e6d6d444eca8bd2cbb7da0..3f6ad96637cc82d95afebae9884d4cb5b3d2ace0 100644 (file)
@@ -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)()) {
+}
+