]> granicus.if.org Git - clang/commitdiff
Partial implementation of PR3342: break out pointer sign
authorEli Friedman <eli.friedman@gmail.com>
Sun, 22 Mar 2009 23:59:44 +0000 (23:59 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Sun, 22 Mar 2009 23:59:44 +0000 (23:59 +0000)
incompatibilities in assignments from other pointer incompatibilities.
Based off of the patch in PR3342.  (This doesn't implement -Wno-pointer-sign,
but I don't know the driver code very well.)

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67494 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/Sema.h
lib/Sema/SemaExpr.cpp
test/Sema/incompatible-sign.c [new file with mode: 0644]

index 51fb9829db485fdcac7d1b334fe5e97cfd11138b..9865e1d0a3eb691e8a73a1930d49d6279865c2e2 100644 (file)
@@ -1092,6 +1092,8 @@ def ext_typecheck_convert_int_pointer : ExtWarn<
   "incompatible integer to pointer conversion %2 %1, expected %0">;
 def ext_typecheck_convert_pointer_void_func : Extension<
   "%2 %1 converts between void* and function pointer, expected %0">;
+def ext_typecheck_convert_incompatible_pointer_sign : ExtWarn<
+  "pointer types point to integer types with different sign %2 %1, expected %0">;
 def ext_typecheck_convert_incompatible_pointer : ExtWarn<
   "incompatible pointer types %2 %1, expected %0">;
 def ext_typecheck_convert_discards_qualifiers : ExtWarn<
index 64cc088e9679c547881d3a8987ef8ac5780167c0..8bc5a6073b94a2220b53d64fca4bd994ef21a655 100644 (file)
@@ -2146,7 +2146,13 @@ public:
     /// IncompatiblePointer - The assignment is between two pointers types that
     /// are not compatible, but we accept them as an extension.
     IncompatiblePointer,
-    
+
+    /// IncompatiblePointer - The assignment is between two pointers types which
+    /// point to integers which have a different sign, but are otherwise identical.
+    /// This is a subset of the above, but broken out because it's by far the most
+    /// common case of incompatible pointers.
+    IncompatiblePointerSign,
+
     /// CompatiblePointerDiscardsQualifiers - The assignment discards
     /// c/v/r qualifiers, which we accept as an extension.
     CompatiblePointerDiscardsQualifiers,
index 3220a9e46191f83657cb646ae0b94245b9e4ca10..85d28a83c734ffb1f77f95a4f4c4b791cb479fcf 100644 (file)
@@ -2792,9 +2792,33 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
   }
   // C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or
   // unqualified versions of compatible types, ...
-  if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
-                                  rhptee.getUnqualifiedType()))
-    return IncompatiblePointer; // this "trumps" PointerAssignDiscardsQualifiers
+  lhptee = lhptee.getUnqualifiedType();
+  rhptee = rhptee.getUnqualifiedType();
+  if (!Context.typesAreCompatible(lhptee, rhptee)) {
+    // Check if the pointee types are compatible ignoring the sign.
+    // We explicitly check for char so that we catch "char" vs
+    // "unsigned char" on systems where "char" is unsigned.
+    if (lhptee->isCharType()) {
+      lhptee = Context.UnsignedCharTy;
+    } else if (lhptee->isSignedIntegerType()) {
+      lhptee = Context.getCorrespondingUnsignedType(lhptee);
+    }
+    if (rhptee->isCharType()) {
+      rhptee = Context.UnsignedCharTy;
+    } else if (rhptee->isSignedIntegerType()) {
+      rhptee = Context.getCorrespondingUnsignedType(rhptee);
+    }
+    if (lhptee == rhptee) {
+      // Types are compatible ignoring the sign. Qualifier incompatibility
+      // takes priority over sign incompatibility because the sign
+      // warning can be disabled.
+      if (ConvTy != Compatible)
+        return ConvTy;
+      return IncompatiblePointerSign;
+    }
+    // General pointer incompatibility takes priority over qualifiers.
+    return IncompatiblePointer; 
+  }
   return ConvTy;
 }
 
@@ -4629,6 +4653,9 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
   case IncompatiblePointer:
     DiagKind = diag::ext_typecheck_convert_incompatible_pointer;
     break;
+  case IncompatiblePointerSign:
+    DiagKind = diag::ext_typecheck_convert_incompatible_pointer_sign;
+    break;
   case FunctionVoidPointer:
     DiagKind = diag::ext_typecheck_convert_pointer_void_func;
     break;
diff --git a/test/Sema/incompatible-sign.c b/test/Sema/incompatible-sign.c
new file mode 100644 (file)
index 0000000..9747327
--- /dev/null
@@ -0,0 +1,5 @@
+// RUN: clang %s -verify -fsyntax-only
+
+int a(int* x);
+int b(unsigned* y) { return a(y); } // expected-warning {{pointer types point to integer types with different sign}}
+