Skip to content

Commit c6ffe4d

Browse files
[clang] Fix message text for -Wpointer-sign to account for plain char
The `-Wpointer-sign` warning text is inappropriate for describing the incompatible pointer conversion between plain `char` and explicitly `signed`/`unsigned` `char` (whichever plain `char` has the same range as) and vice versa. Specifically, in part, it reads "converts between pointers to integer types with different sign". This patch changes that portion to read instead as "converts between pointers to integer types where one is of the unique plain 'char' type and the other is not" when one of the types is plain `char`. C17 subclause 6.5.16.1 indicates that the conversions resulting in `-Wpointer-sign` warnings in assignment-like contexts are constraint violations. This means that strict conformance requires a diagnostic for the case where the message text is wrong before this patch. The lack of an even more specialized warning group is consistent with GCC. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D93999
1 parent f635bcd commit c6ffe4d

File tree

5 files changed

+27
-27
lines changed

5 files changed

+27
-27
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7814,21 +7814,11 @@ def ext_typecheck_convert_incompatible_pointer_sign : ExtWarn<
78147814
"|%diff{sending $ to parameter of type $|"
78157815
"sending to parameter of different type}0,1"
78167816
"|%diff{casting $ to type $|casting between types}0,1}2"
7817-
" converts between pointers to integer types with different sign">,
7817+
" converts between pointers to integer types %select{with different sign|"
7818+
"where one is of the unique plain 'char' type and the other is not}3">,
78187819
InGroup<DiagGroup<"pointer-sign">>;
7819-
def err_typecheck_convert_incompatible_pointer_sign : Error<
7820-
"%select{%diff{assigning to $ from $|assigning to different types}0,1"
7821-
"|%diff{passing $ to parameter of type $|"
7822-
"passing to parameter of different type}0,1"
7823-
"|%diff{returning $ from a function with result type $|"
7824-
"returning from function with different return type}0,1"
7825-
"|%diff{converting $ to type $|converting between types}0,1"
7826-
"|%diff{initializing $ with an expression of type $|"
7827-
"initializing with expression of different type}0,1"
7828-
"|%diff{sending $ to parameter of type $|"
7829-
"sending to parameter of different type}0,1"
7830-
"|%diff{casting $ to type $|casting between types}0,1}2"
7831-
" converts between pointers to integer types with different sign">;
7820+
def err_typecheck_convert_incompatible_pointer_sign :
7821+
Error<ext_typecheck_convert_incompatible_pointer_sign.Text>;
78327822
def ext_typecheck_convert_incompatible_pointer : ExtWarn<
78337823
"incompatible pointer types "
78347824
"%select{%diff{assigning to $ from $|assigning to different types}0,1"

clang/lib/Sema/SemaExpr.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15962,6 +15962,16 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
1596215962
else
1596315963
FDiag << FirstType << SecondType << Action << SrcExpr->getSourceRange();
1596415964

15965+
if (DiagKind == diag::ext_typecheck_convert_incompatible_pointer_sign ||
15966+
DiagKind == diag::err_typecheck_convert_incompatible_pointer_sign) {
15967+
auto isPlainChar = [](const clang::Type *Type) {
15968+
return Type->isSpecificBuiltinType(BuiltinType::Char_S) ||
15969+
Type->isSpecificBuiltinType(BuiltinType::Char_U);
15970+
};
15971+
FDiag << (isPlainChar(FirstType->getPointeeOrArrayElementType()) ||
15972+
isPlainChar(SecondType->getPointeeOrArrayElementType()));
15973+
}
15974+
1596515975
// If we can fix the conversion, suggest the FixIts.
1596615976
if (!ConvHints.isNull()) {
1596715977
for (FixItHint &H : ConvHints.Hints)

clang/test/Sema/incompatible-sign.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@ int b(unsigned* y) { return a(y); } // expected-warning {{passing 'unsigned int
66

77
signed char *plainCharToSignedChar(signed char *arg) { // expected-note{{passing argument to parameter}}
88
extern char c;
9-
signed char *p = &c; // expected-warning {{converts between pointers to integer types with different sign}}
10-
struct { signed char *p; } s = { &c }; // expected-warning {{converts between pointers to integer types with different sign}}
11-
p = &c; // expected-warning {{converts between pointers to integer types with different sign}}
12-
plainCharToSignedChar(&c); // expected-warning {{converts between pointers to integer types with different sign}}
13-
return &c; // expected-warning {{converts between pointers to integer types with different sign}}
9+
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}}
10+
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}}
11+
p = &c; // expected-warning {{converts between pointers to integer types where one is of the unique plain 'char' type and the other is not}}
12+
plainCharToSignedChar(&c); // expected-warning {{converts between pointers to integer types where one is of the unique plain 'char' type and the other is not}}
13+
return &c; // expected-warning {{converts between pointers to integer types where one is of the unique plain 'char' type and the other is not}}
1414
}
1515

1616
char *unsignedCharToPlainChar(char *arg) { // expected-note{{passing argument to parameter}}
1717
extern unsigned char uc[];
18-
char *p = uc; // expected-warning {{converts between pointers to integer types with different sign}}
19-
(void) (char *[]){ [42] = uc }; // expected-warning {{converts between pointers to integer types with different sign}}
20-
p = uc; // expected-warning {{converts between pointers to integer types with different sign}}
21-
unsignedCharToPlainChar(uc); // expected-warning {{converts between pointers to integer types with different sign}}
22-
return uc; // expected-warning {{converts between pointers to integer types with different sign}}
18+
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}}
19+
(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}}
20+
p = uc; // expected-warning {{converts between pointers to integer types where one is of the unique plain 'char' type and the other is not}}
21+
unsignedCharToPlainChar(uc); // expected-warning {{converts between pointers to integer types where one is of the unique plain 'char' type and the other is not}}
22+
return uc; // expected-warning {{converts between pointers to integer types where one is of the unique plain 'char' type and the other is not}}
2323
}

clang/test/Sema/incompatible-sign.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
void plainToSigned() {
55
extern char c;
66
signed char *p;
7-
p = &c; // expected-error {{converts between pointers to integer types with different sign}}
7+
p = &c; // expected-error {{converts between pointers to integer types where one is of the unique plain 'char' type and the other is not}}
88
}
99

1010
void unsignedToPlain() {
1111
extern unsigned char uc;
1212
char *p;
13-
p = &uc; // expected-error {{converts between pointers to integer types with different sign}}
13+
p = &uc; // expected-error {{converts between pointers to integer types where one is of the unique plain 'char' type and the other is not}}
1414
}

clang/test/SemaObjC/objc-cf-audited-warning.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@
2020

2121
void saveImageToJPG(const char *filename)
2222
{
23-
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}}
23+
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}}
2424
}

0 commit comments

Comments
 (0)