Skip to content

Commit de78049

Browse files
committed
Fix behavior, add tests, add release notes
1 parent d34bdd3 commit de78049

File tree

5 files changed

+44
-5
lines changed

5 files changed

+44
-5
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ C Language Changes
140140
- Clang now allows an ``inline`` specifier on a typedef declaration of a
141141
function type in Microsoft compatibility mode. #GH124869
142142
- Clang now allows ``restrict`` qualifier for array types with pointer elements (#GH92847).
143+
- Added ``-Wimplicit-void-ptr-cast``, grouped under ``-Wc++-compat``, which
144+
diagnoses implicit conversion from ``void *`` to another pointer type as
145+
being incompatible with C++. (#GH17792)
143146

144147
C2y Feature Support
145148
^^^^^^^^^^^^^^^^^^^

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,8 @@ def C99Compat : DiagGroup<"c99-compat">;
155155
def C23Compat : DiagGroup<"c23-compat">;
156156
def : DiagGroup<"c2x-compat", [C23Compat]>;
157157

158-
def CXXCompat: DiagGroup<"c++-compat">;
158+
def ImplicitVoidPtrCast : DiagGroup<"implicit-void-ptr-cast">;
159+
def CXXCompat: DiagGroup<"c++-compat", [ImplicitVoidPtrCast]>;
159160
def ExternCCompat : DiagGroup<"extern-c-compat">;
160161
def KeywordCompat : DiagGroup<"keyword-compat">;
161162
def GNUCaseRange : DiagGroup<"gnu-case-range">;

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8687,10 +8687,17 @@ def err_typecheck_missing_return_type_incompatible : Error<
86878687
"%diff{return type $ must match previous return type $|"
86888688
"return type must match previous return type}0,1 when %select{block "
86898689
"literal|lambda expression}2 has unspecified explicit return type">;
8690-
86918690
def warn_compatible_implicit_pointer_conv : Warning<
8692-
"implicit conversion from %diff{$ to $|type to incompatible type}0,1 is not "
8693-
"permitted in C++">, InGroup<CXXCompat>, DefaultIgnore;
8691+
"implicit conversion when %select{"
8692+
"%diff{assigning to $ from type $|assigning to type from type}0,1|"
8693+
"%diff{passing $ to parameter of type $|passing type to parameter of type}0,1|"
8694+
"%diff{returning $ from a function with result type $|returning type from a function with result type}0,1|"
8695+
"<CLANG BUG IF YOU SEE THIS>|" // converting
8696+
"%diff{initializing $ with an expression of type $|initializing type with an expression of type}0,1|"
8697+
"%diff{sending $ to parameter of type $|sending type to parameter of type}0,1|"
8698+
"<CLANG BUG IF YOU SEE THIS>" // casting
8699+
"}2 is not permitted in C++">,
8700+
InGroup<ImplicitVoidPtrCast>, DefaultIgnore;
86948701
def note_incomplete_class_and_qualified_id : Note<
86958702
"conformance of forward class %0 to protocol %1 cannot be confirmed">;
86968703
def warn_incompatible_qualified_id : Warning<

clang/lib/Sema/SemaExpr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9102,7 +9102,7 @@ checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType,
91029102
// Types are compatible ignoring the sign. Qualifier incompatibility
91039103
// takes priority over sign incompatibility because the sign
91049104
// warning can be disabled.
9105-
if (S.IsAssignConvertCompatible(ConvTy))
9105+
if (!S.IsAssignConvertCompatible(ConvTy))
91069106
return ConvTy;
91079107

91089108
return Sema::IncompatiblePointerSign;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify -Wimplicit-void-ptr-cast %s
2+
// RUN: %clang_cc1 -fsyntax-only -verify -Wc++-compat %s
3+
// RUN: %clang_cc1 -fsyntax-only -verify=good %s
4+
// RUN: %clang_cc1 -fsyntax-only -verify=good -Wc++-compat -Wno-implicit-void-ptr-cast %s
5+
// good-no-diagnostics
6+
7+
typedef __typeof__(sizeof(int)) size_t;
8+
extern void *malloc(size_t);
9+
10+
void func(int *); // expected-note {{passing argument to parameter here}}
11+
12+
void test(void) {
13+
int *x = malloc(sizeof(char)); // expected-warning {{implicit conversion when initializing 'int *' with an expression of type 'void *' is not permitted in C++}}
14+
x = malloc(sizeof(char)); // expected-warning {{implicit conversion when assigning to 'int *' from type 'void *' is not permitted in C++}}
15+
func(malloc(sizeof(char))); // expected-warning {{implicit conversion when passing 'void *' to parameter of type 'int *' is not permitted in C++}}
16+
x = (int *)malloc(sizeof(char));
17+
18+
void *vp = 0;
19+
x = vp; // expected-warning {{implicit conversion when assigning to 'int *' from type 'void *' is not permitted in C++}}
20+
vp = vp;
21+
22+
x = (void *)malloc(sizeof(char)); // expected-warning {{implicit conversion when assigning to 'int *' from type 'void *' is not permitted in C++}}
23+
const int *y = vp; // expected-warning {{implicit conversion when initializing 'const int *' with an expression of type 'void *' is not permitted in C++}}
24+
}
25+
26+
int *other_func(void *ptr) {
27+
return ptr; // expected-warning {{implicit conversion when returning 'void *' from a function with result type 'int *' is not permitted in C++}}
28+
}

0 commit comments

Comments
 (0)