[clang] 6685e56 - Disallow dereferencing of void* in C++.

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 10 07:11:57 PDT 2022


Author: Erich Keane
Date: 2022-10-10T07:11:46-07:00
New Revision: 6685e56ceddf7c88eb3c39e838a8164941aade05

URL: https://github.com/llvm/llvm-project/commit/6685e56ceddf7c88eb3c39e838a8164941aade05
DIFF: https://github.com/llvm/llvm-project/commit/6685e56ceddf7c88eb3c39e838a8164941aade05.diff

LOG: 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

Added: 
    clang/test/SemaCXX/disallow_void_deref.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticGroups.td
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaExpr.cpp
    clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1inst.cpp
    clang/test/SemaCXX/reinterpret-cast.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 513a5eda80801..16e6522a44273 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -117,6 +117,18 @@ code bases.
 
   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|?
 ==============================
 Some of the major new features and improvements to Clang are listed

diff  --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index ff88c8acec4c1..cddb127cae58f 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -961,6 +961,7 @@ def PointerToEnumCast : DiagGroup<"pointer-to-enum-cast",
                                   [VoidPointerToEnumCast]>;
 def PointerToIntCast : DiagGroup<"pointer-to-int-cast",
                                  [PointerToEnumCast, VoidPointerToIntCast]>;
+def VoidPointerDeref : DiagGroup<"void-ptr-dereference">;
 
 def FUseLdPath : DiagGroup<"fuse-ld-path">;
 

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8a721d45e78f0..d6fbaed126d64 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6936,8 +6936,11 @@ def err_typecheck_unary_expr : Error<
 def err_typecheck_indirection_requires_pointer : Error<
   "indirection requires pointer operand (%0 invalid)">;
 def ext_typecheck_indirection_through_void_pointer : ExtWarn<
-  "ISO %select{C|C++}0 does not allow indirection on operand of type %1">,
-  InGroup<DiagGroup<"void-ptr-dereference">>;
+  "ISO C does not allow indirection on operand of type %0">,
+  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<
   "indirection of non-volatile null pointer will be deleted, not trap">,
   InGroup<NullDereference>;

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 6d28a44952318..474f86cffd169 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -14536,9 +14536,12 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
     //   [...] the expression to which [the unary * operator] is applied shall
     //   be a pointer to an object type, or a pointer to a function type
     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)
-          << LO.CPlusPlus << OpTy << Op->getSourceRange();
+          << OpTy << Op->getSourceRange();
   }
 
   // Dereferences are usually l-values...

diff  --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1inst.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1inst.cpp
index eb11e3375e5f6..6d591457ae149 100644
--- a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1inst.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1inst.cpp
@@ -8,7 +8,7 @@ struct X0 {
 
 template<typename T, typename 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) {

diff  --git a/clang/test/SemaCXX/disallow_void_deref.cpp b/clang/test/SemaCXX/disallow_void_deref.cpp
new file mode 100644
index 0000000000000..2981e709525b2
--- /dev/null
+++ b/clang/test/SemaCXX/disallow_void_deref.cpp
@@ -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 at -1{{static assertion failed}}
+// sfinae-note at -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 *'}}

diff  --git a/clang/test/SemaCXX/reinterpret-cast.cpp b/clang/test/SemaCXX/reinterpret-cast.cpp
index 1b84df12129c7..ee856485272b2 100644
--- a/clang/test/SemaCXX/reinterpret-cast.cpp
+++ b/clang/test/SemaCXX/reinterpret-cast.cpp
@@ -214,11 +214,11 @@ void dereference_reinterpret_cast() {
   (void)*reinterpret_cast<float*>(v_ptr);
 
   // Casting to void pointer
-  (void)*reinterpret_cast<void*>(&a); // expected-warning {{ISO C++ does not allow}}
-  (void)*reinterpret_cast<void*>(&b); // expected-warning {{ISO C++ does not allow}}
-  (void)*reinterpret_cast<void*>(&l); // expected-warning {{ISO C++ does not allow}}
-  (void)*reinterpret_cast<void*>(&d); // expected-warning {{ISO C++ does not allow}}
-  (void)*reinterpret_cast<void*>(&f); // 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-error {{ISO C++ does not allow}}
+  (void)*reinterpret_cast<void*>(&l); // expected-error {{ISO C++ does not allow}}
+  (void)*reinterpret_cast<void*>(&d); // expected-error {{ISO C++ does not allow}}
+  (void)*reinterpret_cast<void*>(&f); // expected-error {{ISO C++ does not allow}}
 }
 
 void reinterpret_cast_allowlist () {


        


More information about the cfe-commits mailing list