[PATCH] D156054: [Clang][Sema] DR722 (nullptr and varargs) and missing -Wvarargs diagnostics

Mital Ashok via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Sun Jul 23 08:06:53 PDT 2023


MitalAshok created this revision.
Herald added a project: All.
MitalAshok added a comment.
MitalAshok added a reviewer: aaron.ballman.
MitalAshok published this revision for review.
Herald added subscribers: cfe-commits, wangpc.
Herald added a project: clang.

There is one observable difference by explicitly casting `nullptr_t` to `void*`: prvalues of type `nullptr_t` aren't read from (which seemed unintentional):

  static void* f(int x, ...) {
      __builtin_va_list args;
      __builtin_va_start(args, x);
      void* arg = __builtin_va_arg(args, void*);
      __builtin_va_end(args);
      return arg;
  }
  
  int main() {
      int x;
      void* x_ptr = &x;
      void* result = f(0, __builtin_bit_cast(decltype(nullptr), x_ptr));
      __builtin_printf("%p\n%p\n%p\n", x_ptr, result, nullptr);
  }

https://godbolt.org/z/Pfv8Wbhxj

An object of type `nullptr_t` is passed to the function, but when it is read with `void* arg = __builtin_va_arg(args, void*);`, it is not a null pointer.



================
Comment at: clang/lib/Sema/SemaExpr.cpp:17328
+      PromoteType = Context.VoidPtrTy;
+    if (TInfo->getType()->isArrayType())
+      PromoteType = Context.getArrayDecayedType(TInfo->getType());
----------------
This warns if you call `va_arg(ap, double[2])`. However this might be valid since the actual argument only has to be a "compatible type" and I think `double _Complex` is compatible with `double[2]`. I think we should warn anyways, since array rvalues are tricky to work with, and the user probably passed a `double[2]` and should retrieve the `double*`.


================
Comment at: clang/test/Sema/format-strings-pedantic.c:21
+#elif !__is_identifier(nullptr)
+  printf("%p", nullptr); // expected-warning {{format specifies type 'void *' but the argument has type 'nullptr_t'}}
 #endif
----------------
In C2x, nullptr passed as an argument and retrieved via `va_arg(ap, void *)` is valid (See C2x 7.16.1.1p2) and this is the same as `printf("%p", (void*) nullptr)`, but this should still be fine as a "pedantic" warning


================
Comment at: clang/www/cxx_dr_status.html:4376
     <td>Can <TT>nullptr</TT> be passed to an ellipsis?</td>
-    <td class="none" align="center">Unknown</td>
+    <td class="unreleased" align="center">Clang 17</td>
   </tr>
----------------
It may be better to mark this as "Yes", since in old clang versions passing nullptr would work by virtue of it having representation of a null void* pointer, and it only affected diagnostics


nullptr passed to a variadic function in C++ now converted to void*.
va_arg on array types and half precision floats now diagnosed.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D156054

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CXX/drs/dr7xx.cpp
  clang/test/Sema/format-strings-pedantic.c
  clang/test/SemaCXX/varargs.cpp
  clang/www/cxx_dr_status.html

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D156054.543283.patch
Type: text/x-patch
Size: 6755 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230723/1afd96e3/attachment-0001.bin>


More information about the cfe-commits mailing list