forked from OSchip/llvm-project
Disallow dereferencing of void* in C++.
as Discussed: https://discourse.llvm.org/t/rfc-can-we-stop-the-extension-to-allow-dereferencing-void-in-c/65708 There is no good reason to allow this when the other compilers all reject this, and it messes with SFINAE/constraint checking. Differential Revision: https://reviews.llvm.org/D135287
This commit is contained in:
parent
7915027926
commit
6685e56ced
|
@ -117,6 +117,18 @@ code bases.
|
||||||
|
|
||||||
These errors also match MSVC's behavior.
|
These errors also match MSVC's behavior.
|
||||||
|
|
||||||
|
- Clang now diagnoses indirection of ``void *`` in C++ mode as a warning which
|
||||||
|
defaults to an error. This is compatible with ISO C++, GCC, ICC, and MSVC. This
|
||||||
|
is also now a SFINAE error so constraint checking and SFINAE checking can be
|
||||||
|
compatible with other compilers. It is expected that this will be upgraded to
|
||||||
|
an error-only diagnostic in the next Clang release.
|
||||||
|
|
||||||
|
.. code-block:: c++
|
||||||
|
|
||||||
|
void func(void *p) {
|
||||||
|
*p; // Now diagnosed as a warning-as-error.
|
||||||
|
}
|
||||||
|
|
||||||
What's New in Clang |release|?
|
What's New in Clang |release|?
|
||||||
==============================
|
==============================
|
||||||
Some of the major new features and improvements to Clang are listed
|
Some of the major new features and improvements to Clang are listed
|
||||||
|
|
|
@ -961,6 +961,7 @@ def PointerToEnumCast : DiagGroup<"pointer-to-enum-cast",
|
||||||
[VoidPointerToEnumCast]>;
|
[VoidPointerToEnumCast]>;
|
||||||
def PointerToIntCast : DiagGroup<"pointer-to-int-cast",
|
def PointerToIntCast : DiagGroup<"pointer-to-int-cast",
|
||||||
[PointerToEnumCast, VoidPointerToIntCast]>;
|
[PointerToEnumCast, VoidPointerToIntCast]>;
|
||||||
|
def VoidPointerDeref : DiagGroup<"void-ptr-dereference">;
|
||||||
|
|
||||||
def FUseLdPath : DiagGroup<"fuse-ld-path">;
|
def FUseLdPath : DiagGroup<"fuse-ld-path">;
|
||||||
|
|
||||||
|
|
|
@ -6936,8 +6936,11 @@ def err_typecheck_unary_expr : Error<
|
||||||
def err_typecheck_indirection_requires_pointer : Error<
|
def err_typecheck_indirection_requires_pointer : Error<
|
||||||
"indirection requires pointer operand (%0 invalid)">;
|
"indirection requires pointer operand (%0 invalid)">;
|
||||||
def ext_typecheck_indirection_through_void_pointer : ExtWarn<
|
def ext_typecheck_indirection_through_void_pointer : ExtWarn<
|
||||||
"ISO %select{C|C++}0 does not allow indirection on operand of type %1">,
|
"ISO C does not allow indirection on operand of type %0">,
|
||||||
InGroup<DiagGroup<"void-ptr-dereference">>;
|
InGroup<VoidPointerDeref>;
|
||||||
|
def ext_typecheck_indirection_through_void_pointer_cpp
|
||||||
|
: ExtWarn<"ISO C++ does not allow indirection on operand of type %0">,
|
||||||
|
InGroup<VoidPointerDeref>, DefaultError, SFINAEFailure;
|
||||||
def warn_indirection_through_null : Warning<
|
def warn_indirection_through_null : Warning<
|
||||||
"indirection of non-volatile null pointer will be deleted, not trap">,
|
"indirection of non-volatile null pointer will be deleted, not trap">,
|
||||||
InGroup<NullDereference>;
|
InGroup<NullDereference>;
|
||||||
|
|
|
@ -14536,9 +14536,12 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
|
||||||
// [...] the expression to which [the unary * operator] is applied shall
|
// [...] the expression to which [the unary * operator] is applied shall
|
||||||
// be a pointer to an object type, or a pointer to a function type
|
// be a pointer to an object type, or a pointer to a function type
|
||||||
LangOptions LO = S.getLangOpts();
|
LangOptions LO = S.getLangOpts();
|
||||||
if (LO.CPlusPlus || (!(LO.C99 && IsAfterAmp) && !S.isUnevaluatedContext()))
|
if (LO.CPlusPlus)
|
||||||
|
S.Diag(OpLoc, diag::ext_typecheck_indirection_through_void_pointer_cpp)
|
||||||
|
<< OpTy << Op->getSourceRange();
|
||||||
|
else if (!(LO.C99 && IsAfterAmp) && !S.isUnevaluatedContext())
|
||||||
S.Diag(OpLoc, diag::ext_typecheck_indirection_through_void_pointer)
|
S.Diag(OpLoc, diag::ext_typecheck_indirection_through_void_pointer)
|
||||||
<< LO.CPlusPlus << OpTy << Op->getSourceRange();
|
<< OpTy << Op->getSourceRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dereferences are usually l-values...
|
// Dereferences are usually l-values...
|
||||||
|
|
|
@ -8,7 +8,7 @@ struct X0 {
|
||||||
|
|
||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
void X0<T, U>::f(T *t, const U &u) {
|
void X0<T, U>::f(T *t, const U &u) {
|
||||||
*t = u; // expected-warning{{indirection on operand of type 'void *'}} expected-error{{not assignable}}
|
*t = u; // expected-error{{indirection on operand of type 'void *'}} expected-error{{not assignable}}
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_f(X0<float, int> xfi, X0<void, int> xvi, float *fp, void *vp, int i) {
|
void test_f(X0<float, int> xfi, X0<void, int> xvi, float *fp, void *vp, int i) {
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
// RUN: %clang_cc1 -fsyntax-only -verify=enabled,sfinae -std=c++20 %s
|
||||||
|
// RUN: %clang_cc1 -fsyntax-only -verify=sfinae -std=c++20 -Wno-void-ptr-dereference %s
|
||||||
|
|
||||||
|
void f(void* p) {
|
||||||
|
(void)*p; // enabled-error{{ISO C++ does not allow indirection on operand of type 'void *'}}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
concept deref = requires (T& t) {
|
||||||
|
{ *t }; // #FAILED_REQ
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(deref<void*>);
|
||||||
|
// sfinae-error@-1{{static assertion failed}}
|
||||||
|
// sfinae-note@-2{{because 'void *' does not satisfy 'deref'}}
|
||||||
|
// sfinae-note@#FAILED_REQ{{because '*t' would be invalid: ISO C++ does not allow indirection on operand of type 'void *'}}
|
|
@ -214,11 +214,11 @@ void dereference_reinterpret_cast() {
|
||||||
(void)*reinterpret_cast<float*>(v_ptr);
|
(void)*reinterpret_cast<float*>(v_ptr);
|
||||||
|
|
||||||
// Casting to void pointer
|
// Casting to void pointer
|
||||||
(void)*reinterpret_cast<void*>(&a); // expected-warning {{ISO C++ does not allow}}
|
(void)*reinterpret_cast<void*>(&a); // expected-error {{ISO C++ does not allow}}
|
||||||
(void)*reinterpret_cast<void*>(&b); // expected-warning {{ISO C++ does not allow}}
|
(void)*reinterpret_cast<void*>(&b); // expected-error {{ISO C++ does not allow}}
|
||||||
(void)*reinterpret_cast<void*>(&l); // expected-warning {{ISO C++ does not allow}}
|
(void)*reinterpret_cast<void*>(&l); // expected-error {{ISO C++ does not allow}}
|
||||||
(void)*reinterpret_cast<void*>(&d); // expected-warning {{ISO C++ does not allow}}
|
(void)*reinterpret_cast<void*>(&d); // expected-error {{ISO C++ does not allow}}
|
||||||
(void)*reinterpret_cast<void*>(&f); // expected-warning {{ISO C++ does not allow}}
|
(void)*reinterpret_cast<void*>(&f); // expected-error {{ISO C++ does not allow}}
|
||||||
}
|
}
|
||||||
|
|
||||||
void reinterpret_cast_allowlist () {
|
void reinterpret_cast_allowlist () {
|
||||||
|
|
Loading…
Reference in New Issue