From f05c05d2e1a2952e6cc7c3e54366fb8d99ff579c Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Sun, 22 Mar 2009 23:59:44 +0000 Subject: [PATCH] Partial implementation of PR3342: break out pointer sign 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 | 2 ++ lib/Sema/Sema.h | 8 +++++- lib/Sema/SemaExpr.cpp | 33 ++++++++++++++++++++-- test/Sema/incompatible-sign.c | 5 ++++ 4 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 test/Sema/incompatible-sign.c diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 51fb9829db..9865e1d0a3 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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< diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 64cc088e96..8bc5a6073b 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -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, diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 3220a9e461..85d28a83c7 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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 index 0000000000..9747327364 --- /dev/null +++ b/test/Sema/incompatible-sign.c @@ -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}} + -- 2.50.1