diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7780,21 +7780,11 @@ "|%diff{sending $ to parameter of type $|" "sending to parameter of different type}0,1" "|%diff{casting $ to type $|casting between types}0,1}2" - " converts between pointers to integer types with different sign">, + " converts between pointers to integer types %select{with different sign|" + "where one is of the unique plain char type and the other is not}3">, InGroup>; -def err_typecheck_convert_incompatible_pointer_sign : Error< - "%select{%diff{assigning to $ from $|assigning to different types}0,1" - "|%diff{passing $ to parameter of type $|" - "passing to parameter of different type}0,1" - "|%diff{returning $ from a function with result type $|" - "returning from function with different return type}0,1" - "|%diff{converting $ to type $|converting between types}0,1" - "|%diff{initializing $ with an expression of type $|" - "initializing with expression of different type}0,1" - "|%diff{sending $ to parameter of type $|" - "sending to parameter of different type}0,1" - "|%diff{casting $ to type $|casting between types}0,1}2" - " converts between pointers to integer types with different sign">; +def err_typecheck_convert_incompatible_pointer_sign : + Error; def ext_typecheck_convert_incompatible_pointer : ExtWarn< "incompatible pointer types " "%select{%diff{assigning to $ from $|assigning to different types}0,1" diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -15962,6 +15962,16 @@ else FDiag << FirstType << SecondType << Action << SrcExpr->getSourceRange(); + if (DiagKind == diag::ext_typecheck_convert_incompatible_pointer_sign || + DiagKind == diag::err_typecheck_convert_incompatible_pointer_sign) { + const auto isPlainChar = [](const clang::Type *Type) { + return Type->isSpecificBuiltinType(BuiltinType::Char_S) || + Type->isSpecificBuiltinType(BuiltinType::Char_U); + }; + FDiag << (isPlainChar(FirstType->getPointeeOrArrayElementType()) || + isPlainChar(SecondType->getPointeeOrArrayElementType())); + } + // If we can fix the conversion, suggest the FixIts. if (!ConvHints.isNull()) { for (FixItHint &H : ConvHints.Hints) diff --git a/clang/test/Sema/incompatible-sign.c b/clang/test/Sema/incompatible-sign.c --- a/clang/test/Sema/incompatible-sign.c +++ b/clang/test/Sema/incompatible-sign.c @@ -1,5 +1,23 @@ // RUN: %clang_cc1 %s -verify -fsyntax-only +// RUN: %clang_cc1 %s -verify -fsyntax-only -fno-signed-char int a(int* x); // expected-note{{passing argument to parameter 'x' here}} int b(unsigned* y) { return a(y); } // expected-warning {{passing 'unsigned int *' to parameter of type 'int *' converts between pointers to integer types with different sign}} +signed char *plainCharToSignedChar(signed char *arg) { // expected-note{{passing argument to parameter}} + extern char c; + signed char *p = &c; // expected-warning {{converts between pointers to integer types where one is of the unique plain char type and the other is not}} + struct { signed char *p; } s = { &c }; // expected-warning {{converts between pointers to integer types where one is of the unique plain char type and the other is not}} + p = &c; // expected-warning {{converts between pointers to integer types where one is of the unique plain char type and the other is not}} + plainCharToSignedChar(&c); // expected-warning {{converts between pointers to integer types where one is of the unique plain char type and the other is not}} + return &c; // expected-warning {{converts between pointers to integer types where one is of the unique plain char type and the other is not}} +} + +char *unsignedCharToPlainChar(char *arg) { // expected-note{{passing argument to parameter}} + extern unsigned char uc[]; + char *p = uc; // expected-warning {{converts between pointers to integer types where one is of the unique plain char type and the other is not}} + (void) (char *[]){ [42] = uc }; // expected-warning {{converts between pointers to integer types where one is of the unique plain char type and the other is not}} + p = uc; // expected-warning {{converts between pointers to integer types where one is of the unique plain char type and the other is not}} + unsignedCharToPlainChar(uc); // expected-warning {{converts between pointers to integer types where one is of the unique plain char type and the other is not}} + return uc; // expected-warning {{converts between pointers to integer types where one is of the unique plain char type and the other is not}} +} diff --git a/clang/test/Sema/incompatible-sign.cpp b/clang/test/Sema/incompatible-sign.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Sema/incompatible-sign.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only +// RUN: %clang_cc1 %s -verify -fsyntax-only -fno-signed-char + +void plainToSigned() { + extern char c; + signed char *p; + p = &c; // expected-error {{converts between pointers to integer types where one is of the unique plain char type and the other is not}} +} + +void unsignedToPlain() { + extern unsigned char uc; + char *p; + p = &uc; // expected-error {{converts between pointers to integer types where one is of the unique plain char type and the other is not}} +} diff --git a/clang/test/SemaObjC/objc-cf-audited-warning.m b/clang/test/SemaObjC/objc-cf-audited-warning.m --- a/clang/test/SemaObjC/objc-cf-audited-warning.m +++ b/clang/test/SemaObjC/objc-cf-audited-warning.m @@ -20,5 +20,5 @@ void saveImageToJPG(const char *filename) { - CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, filename, 10, 0); // expected-warning {{passing 'const char *' to parameter of type 'const UInt8 *' (aka 'const unsigned char *') converts between pointers to integer types with different sign}} + CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, filename, 10, 0); // expected-warning {{passing 'const char *' to parameter of type 'const UInt8 *' (aka 'const unsigned char *') converts between pointers to integer types where one is of the unique plain char type and the other is not}} }