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

2023-08-29 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added a comment.

I think this is looking close to good, just had some minor nits and an extra 
test case to consider.




Comment at: clang/lib/Sema/SemaExpr.cpp:17255
+  // Check if these are compatible types according to the C rules even in C++
+  // because va_arg is defined in C in terms of C compatibile types
+  static auto IsCompatible = [&](QualType L, QualType R) {





Comment at: clang/lib/Sema/SemaExpr.cpp:17264-17268
+  QualType PromotedType = PromotedExpr.get()->getType().getUnqualifiedType();
+  QualType VAArgType = VAArg->getType().getUnqualifiedType();
+  // If these types are compatible, it was not promoted to an incompatible 
type.
+  if (IsCompatible(PromotedType, VAArgType))
+return QualType();

This code is correct, but let's add an explicit test for the subtle edge case 
with `_Atomic` types. `getUnqualifiedType()` does not strip atomic qualifiers, 
so `int` and `_Atomic int` should remain incompatible.



Comment at: clang/test/Sema/format-pointer.c:1-8
+// RUN: %clang_cc1 -xc -Wformat %s -verify
+// RUN: %clang_cc1 -xc -Wformat -std=c2x %s -verify
+// RUN: %clang_cc1 -xc++ -Wformat %s -verify
+// RUN: %clang_cc1 -xobjective-c -Wformat -fblocks %s -verify
+// RUN: %clang_cc1 -xobjective-c++ -Wformat -fblocks %s -verify
+// RUN: %clang_cc1 -xc -std=c2x -Wformat %s -pedantic -verify=expected,pedantic
+// RUN: %clang_cc1 -xc++ -Wformat %s -pedantic -verify=expected,pedantic





Comment at: clang/test/SemaCXX/varargs.cpp:34
   enum Unscoped1 { One = 0x7FFF };
-  (void)__builtin_va_arg(ap, Unscoped1); // ok
+  (void)__builtin_va_arg(ap, Unscoped1); // expected-warning {{second argument 
to 'va_arg' is of promotable type 'Unscoped1'; this va_arg has undefined 
behavior because arguments will be promoted to 'int'}}
 

MitalAshok wrote:
> aaron.ballman wrote:
> > MitalAshok wrote:
> > > MitalAshok wrote:
> > > > Unscoped1 is promoted to int when passed to a variadic function.
> > > > 
> > > > The underlying type for Unscoped1 is unsigned int, so only Unscoped1 
> > > > and unsigned int are compatible, not Unscoped1 and int. An Unscoped1 
> > > > passed to a variadic function must be retrieved via va_arg(ap, int).
> > > > 
> > > Although I guess the warning is now wrong because even though `void f(int 
> > > x, ...) { std::va_list ap; va_start(ap, x); va_arg(ap, Unscoped1); }` 
> > > `f(0, Unscoped1{2})` would be UB, `f(0, 2u)` would not be UB.
> > > 
> > > The user still should be warned about it, so I could create a new warning 
> > > "second argument to 'va_arg' is of promotable enumeration type 
> > > 'Unscoped1'; this va_arg may have undefined behavior because arguments of 
> > > this enumeration type will be promoted to 'int', not the underlying type 
> > > 'unsigned int'", and maybe suggest a fix `Unscoped1{va_arg(ap, 
> > > unsigned)}`.
> > > 
> > > Or we could ignore it and pretend that int and enums with underlying 
> > > types unsigned are compatible for the purposes of va_arg
> > I think we shouldn't warn in this case because of C23 7.16.1.1p2:
> > 
> > >  If type is not compatible with the type of the actual next argument (as 
> > > promoted according to
> > > the default argument promotions), the behavior is undefined, except for 
> > > the following cases:
> > > ...
> > > one type is compatible with a signed integer type, the other type is 
> > > compatible with the
> > > corresponding unsigned integer type, and the value is representable in 
> > > both types;
> > 
> > Coupled with C23 6.7.2.2p13: 
> > 
> > > For all enumerations without a fixed underlying type, each enumerated 
> > > type shall be compatible
> > > with char or a signed or an unsigned integer type that is not bool or a 
> > > bit-precise integer type. The
> > > choice of type is implementation-defined., but shall be capable of 
> > > representing the values of all
> > > the members of the enumeration.
> > 
> > WDYT?
> This seems to have changed very recently between [[ 
> https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf | N3096 ]] (April 
> C23 draft) and [[ https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3149.zip 
> | N3149 ]] (July C23 draft) by [[ 
> https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3112.pdf | N3112 ]].
> 
> For reference, the old wording (also in C17) read:
> 
> > one type is a signed integer type, the other type is the corresponding 
> > unsigned integer type,
> > and the value is representable in both types;
> 
> So with the current rules, yes they would be compatible and this shouldn't 
> warn. I've changed it so it checks types with corresponding signedness.
> This seems to have changed very recently between N3096 (April C23 draft) and 
> N3149 (July C23 draft) by N3112

Yes, this changed during ballot comment resolution at the June 2023 meeting; it 
was US-127 (see https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3148.doc 

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

2023-08-24 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok added inline comments.



Comment at: clang/test/SemaCXX/varargs.cpp:34
   enum Unscoped1 { One = 0x7FFF };
-  (void)__builtin_va_arg(ap, Unscoped1); // ok
+  (void)__builtin_va_arg(ap, Unscoped1); // expected-warning {{second argument 
to 'va_arg' is of promotable type 'Unscoped1'; this va_arg has undefined 
behavior because arguments will be promoted to 'int'}}
 

aaron.ballman wrote:
> MitalAshok wrote:
> > MitalAshok wrote:
> > > Unscoped1 is promoted to int when passed to a variadic function.
> > > 
> > > The underlying type for Unscoped1 is unsigned int, so only Unscoped1 and 
> > > unsigned int are compatible, not Unscoped1 and int. An Unscoped1 passed 
> > > to a variadic function must be retrieved via va_arg(ap, int).
> > > 
> > Although I guess the warning is now wrong because even though `void f(int 
> > x, ...) { std::va_list ap; va_start(ap, x); va_arg(ap, Unscoped1); }` `f(0, 
> > Unscoped1{2})` would be UB, `f(0, 2u)` would not be UB.
> > 
> > The user still should be warned about it, so I could create a new warning 
> > "second argument to 'va_arg' is of promotable enumeration type 'Unscoped1'; 
> > this va_arg may have undefined behavior because arguments of this 
> > enumeration type will be promoted to 'int', not the underlying type 
> > 'unsigned int'", and maybe suggest a fix `Unscoped1{va_arg(ap, unsigned)}`.
> > 
> > Or we could ignore it and pretend that int and enums with underlying types 
> > unsigned are compatible for the purposes of va_arg
> I think we shouldn't warn in this case because of C23 7.16.1.1p2:
> 
> >  If type is not compatible with the type of the actual next argument (as 
> > promoted according to
> > the default argument promotions), the behavior is undefined, except for the 
> > following cases:
> > ...
> > one type is compatible with a signed integer type, the other type is 
> > compatible with the
> > corresponding unsigned integer type, and the value is representable in both 
> > types;
> 
> Coupled with C23 6.7.2.2p13: 
> 
> > For all enumerations without a fixed underlying type, each enumerated type 
> > shall be compatible
> > with char or a signed or an unsigned integer type that is not bool or a 
> > bit-precise integer type. The
> > choice of type is implementation-defined., but shall be capable of 
> > representing the values of all
> > the members of the enumeration.
> 
> WDYT?
This seems to have changed very recently between [[ 
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf | N3096 ]] (April 
C23 draft) and [[ https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3149.zip | 
N3149 ]] (July C23 draft) by [[ 
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3112.pdf | N3112 ]].

For reference, the old wording (also in C17) read:

> one type is a signed integer type, the other type is the corresponding 
> unsigned integer type,
> and the value is representable in both types;

So with the current rules, yes they would be compatible and this shouldn't 
warn. I've changed it so it checks types with corresponding signedness.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2023-08-24 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok updated this revision to Diff 553056.
MitalAshok added a comment.

clang-format


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/AST/FormatString.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CXX/drs/dr7xx.cpp
  clang/test/CodeGen/xcore-abi.c
  clang/test/Sema/format-pointer.c
  clang/test/Sema/format-strings-pedantic.c
  clang/test/Sema/varargs.c
  clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
  clang/test/SemaCXX/varargs.cpp
  clang/www/cxx_dr_status.html

Index: clang/www/cxx_dr_status.html
===
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -4373,7 +4373,7 @@
 https://cplusplus.github.io/CWG/issues/722.html;>722
 CD2
 Can nullptr be passed to an ellipsis?
-Unknown
+Clang 18
   
   
 https://cplusplus.github.io/CWG/issues/726.html;>726
Index: clang/test/SemaCXX/varargs.cpp
===
--- clang/test/SemaCXX/varargs.cpp
+++ clang/test/SemaCXX/varargs.cpp
@@ -30,22 +30,28 @@
 
 // Ensure the correct behavior for promotable type UB checking.
 void promotable(int a, ...) {
-  enum Unscoped1 { One = 0x7FFF };
+  enum Unscoped1 { U = 0x7FFF };
   (void)__builtin_va_arg(ap, Unscoped1); // ok
 
-  enum Unscoped2 { Two = 0x };
+  enum Unscoped2 { I = 0x };
   (void)__builtin_va_arg(ap, Unscoped2); // ok
 
-  enum class Scoped { Three };
+  enum Unscoped3 { UL = 0x7FFF };
+  (void)__builtin_va_arg(ap, Unscoped3); // ok
+
+  enum Unscoped4 { L = 0xu };
+  (void)__builtin_va_arg(ap, Unscoped4); // ok
+
+  enum class Scoped { One };
   (void)__builtin_va_arg(ap, Scoped); // ok
 
-  enum Fixed : int { Four };
+  enum Fixed : int { Two };
   (void)__builtin_va_arg(ap, Fixed); // ok
 
-  enum FixedSmall : char { Five };
+  enum FixedSmall : char { Three };
   (void)__builtin_va_arg(ap, FixedSmall); // expected-warning {{second argument to 'va_arg' is of promotable type 'FixedSmall'; this va_arg has undefined behavior because arguments will be promoted to 'int'}}
 
-  enum FixedLarge : long long { Six };
+  enum FixedLarge : long long { Four };
   (void)__builtin_va_arg(ap, FixedLarge); // ok
 
   // Ensure that qualifiers are ignored.
@@ -55,6 +61,24 @@
   (void)__builtin_va_arg(ap, unsigned int);
 
   (void)__builtin_va_arg(ap, bool); // expected-warning {{second argument to 'va_arg' is of promotable type 'bool'; this va_arg has undefined behavior because arguments will be promoted to 'int'}}
+
+  (void)__builtin_va_arg(ap, float); // expected-warning {{second argument to 'va_arg' is of promotable type 'float'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+  (void)__builtin_va_arg(ap, __fp16); // expected-warning {{second argument to 'va_arg' is of promotable type '__fp16'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+
+#if __cplusplus >= 201103L
+  (void)__builtin_va_arg(ap, decltype(nullptr)); // expected-warning {{second argument to 'va_arg' is of promotable type 'decltype(nullptr)' (aka 'std::nullptr_t'); this va_arg has undefined behavior because arguments will be promoted to 'void *'}}
+#endif
+
+  (void)__builtin_va_arg(ap, int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'int *'}}
+  (void)__builtin_va_arg(ap, const int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'const int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'const int *'}}
+
+  // _BitInts aren't promoted
+  (void)__builtin_va_arg(ap, _BitInt(7));
+  (void)__builtin_va_arg(ap, unsigned _BitInt(7));
+  (void)__builtin_va_arg(ap, _BitInt(32));
+  (void)__builtin_va_arg(ap, unsigned _BitInt(32));
+  (void)__builtin_va_arg(ap, _BitInt(33));
+  (void)__builtin_va_arg(ap, unsigned _BitInt(33));
 }
 
 #if __cplusplus >= 201103L
Index: clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
===
--- clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
+++ clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
@@ -5,6 +5,7 @@
 extern int printf(const char *restrict, ...);
 }
 
-void f(char *c) {
+void f(char *c, int *q) {
   printf("%p", c);
+  printf("%p", q);
 }
Index: clang/test/Sema/varargs.c
===
--- clang/test/Sema/varargs.c
+++ clang/test/Sema/varargs.c
@@ -75,6 +75,14 @@
 (void)__builtin_va_arg(args, enum E); // Don't warn here in C
 (void)__builtin_va_arg(args, short); // expected-warning {{second argument to 'va_arg' is of promotable type 'short'}}
 (void)__builtin_va_arg(args, char); // 

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

2023-08-24 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok updated this revision to Diff 553055.
MitalAshok added a comment.

enums now considered compatible with unsigned/signed versions of their 
underlying type for the purposes of -Wvarargs


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/AST/FormatString.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CXX/drs/dr7xx.cpp
  clang/test/CodeGen/xcore-abi.c
  clang/test/Sema/format-pointer.c
  clang/test/Sema/format-strings-pedantic.c
  clang/test/Sema/varargs.c
  clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
  clang/test/SemaCXX/varargs.cpp
  clang/www/cxx_dr_status.html

Index: clang/www/cxx_dr_status.html
===
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -4373,7 +4373,7 @@
 https://cplusplus.github.io/CWG/issues/722.html;>722
 CD2
 Can nullptr be passed to an ellipsis?
-Unknown
+Clang 18
   
   
 https://cplusplus.github.io/CWG/issues/726.html;>726
Index: clang/test/SemaCXX/varargs.cpp
===
--- clang/test/SemaCXX/varargs.cpp
+++ clang/test/SemaCXX/varargs.cpp
@@ -30,22 +30,28 @@
 
 // Ensure the correct behavior for promotable type UB checking.
 void promotable(int a, ...) {
-  enum Unscoped1 { One = 0x7FFF };
+  enum Unscoped1 { U = 0x7FFF };
   (void)__builtin_va_arg(ap, Unscoped1); // ok
 
-  enum Unscoped2 { Two = 0x };
+  enum Unscoped2 { I = 0x };
   (void)__builtin_va_arg(ap, Unscoped2); // ok
 
-  enum class Scoped { Three };
+  enum Unscoped3 { UL = 0x7FFF };
+  (void)__builtin_va_arg(ap, Unscoped3); // ok
+
+  enum Unscoped4 { L = 0xu };
+  (void)__builtin_va_arg(ap, Unscoped4); // ok
+
+  enum class Scoped { One };
   (void)__builtin_va_arg(ap, Scoped); // ok
 
-  enum Fixed : int { Four };
+  enum Fixed : int { Two };
   (void)__builtin_va_arg(ap, Fixed); // ok
 
-  enum FixedSmall : char { Five };
+  enum FixedSmall : char { Three };
   (void)__builtin_va_arg(ap, FixedSmall); // expected-warning {{second argument to 'va_arg' is of promotable type 'FixedSmall'; this va_arg has undefined behavior because arguments will be promoted to 'int'}}
 
-  enum FixedLarge : long long { Six };
+  enum FixedLarge : long long { Four };
   (void)__builtin_va_arg(ap, FixedLarge); // ok
 
   // Ensure that qualifiers are ignored.
@@ -55,6 +61,24 @@
   (void)__builtin_va_arg(ap, unsigned int);
 
   (void)__builtin_va_arg(ap, bool); // expected-warning {{second argument to 'va_arg' is of promotable type 'bool'; this va_arg has undefined behavior because arguments will be promoted to 'int'}}
+
+  (void)__builtin_va_arg(ap, float); // expected-warning {{second argument to 'va_arg' is of promotable type 'float'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+  (void)__builtin_va_arg(ap, __fp16); // expected-warning {{second argument to 'va_arg' is of promotable type '__fp16'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+
+#if __cplusplus >= 201103L
+  (void)__builtin_va_arg(ap, decltype(nullptr)); // expected-warning {{second argument to 'va_arg' is of promotable type 'decltype(nullptr)' (aka 'std::nullptr_t'); this va_arg has undefined behavior because arguments will be promoted to 'void *'}}
+#endif
+
+  (void)__builtin_va_arg(ap, int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'int *'}}
+  (void)__builtin_va_arg(ap, const int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'const int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'const int *'}}
+
+  // _BitInts aren't promoted
+  (void)__builtin_va_arg(ap, _BitInt(7));
+  (void)__builtin_va_arg(ap, unsigned _BitInt(7));
+  (void)__builtin_va_arg(ap, _BitInt(32));
+  (void)__builtin_va_arg(ap, unsigned _BitInt(32));
+  (void)__builtin_va_arg(ap, _BitInt(33));
+  (void)__builtin_va_arg(ap, unsigned _BitInt(33));
 }
 
 #if __cplusplus >= 201103L
Index: clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
===
--- clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
+++ clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
@@ -5,6 +5,7 @@
 extern int printf(const char *restrict, ...);
 }
 
-void f(char *c) {
+void f(char *c, int *q) {
   printf("%p", c);
+  printf("%p", q);
 }
Index: clang/test/Sema/varargs.c
===
--- clang/test/Sema/varargs.c
+++ clang/test/Sema/varargs.c
@@ -75,6 +75,14 @@
 (void)__builtin_va_arg(args, enum E); // Don't warn here in C
 (void)__builtin_va_arg(args, short); // expected-warning {{second 

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

2023-08-23 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added inline comments.



Comment at: clang/test/SemaCXX/varargs.cpp:34
   enum Unscoped1 { One = 0x7FFF };
-  (void)__builtin_va_arg(ap, Unscoped1); // ok
+  (void)__builtin_va_arg(ap, Unscoped1); // expected-warning {{second argument 
to 'va_arg' is of promotable type 'Unscoped1'; this va_arg has undefined 
behavior because arguments will be promoted to 'int'}}
 

MitalAshok wrote:
> MitalAshok wrote:
> > Unscoped1 is promoted to int when passed to a variadic function.
> > 
> > The underlying type for Unscoped1 is unsigned int, so only Unscoped1 and 
> > unsigned int are compatible, not Unscoped1 and int. An Unscoped1 passed to 
> > a variadic function must be retrieved via va_arg(ap, int).
> > 
> Although I guess the warning is now wrong because even though `void f(int x, 
> ...) { std::va_list ap; va_start(ap, x); va_arg(ap, Unscoped1); }` `f(0, 
> Unscoped1{2})` would be UB, `f(0, 2u)` would not be UB.
> 
> The user still should be warned about it, so I could create a new warning 
> "second argument to 'va_arg' is of promotable enumeration type 'Unscoped1'; 
> this va_arg may have undefined behavior because arguments of this enumeration 
> type will be promoted to 'int', not the underlying type 'unsigned int'", and 
> maybe suggest a fix `Unscoped1{va_arg(ap, unsigned)}`.
> 
> Or we could ignore it and pretend that int and enums with underlying types 
> unsigned are compatible for the purposes of va_arg
I think we shouldn't warn in this case because of C23 7.16.1.1p2:

>  If type is not compatible with the type of the actual next argument (as 
> promoted according to
> the default argument promotions), the behavior is undefined, except for the 
> following cases:
> ...
> one type is compatible with a signed integer type, the other type is 
> compatible with the
> corresponding unsigned integer type, and the value is representable in both 
> types;

Coupled with C23 6.7.2.2p13: 

> For all enumerations without a fixed underlying type, each enumerated type 
> shall be compatible
> with char or a signed or an unsigned integer type that is not bool or a 
> bit-precise integer type. The
> choice of type is implementation-defined., but shall be capable of 
> representing the values of all
> the members of the enumeration.

WDYT?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2023-08-23 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok marked an inline comment as not done.
MitalAshok added inline comments.



Comment at: clang/test/SemaCXX/varargs.cpp:34
   enum Unscoped1 { One = 0x7FFF };
-  (void)__builtin_va_arg(ap, Unscoped1); // ok
+  (void)__builtin_va_arg(ap, Unscoped1); // expected-warning {{second argument 
to 'va_arg' is of promotable type 'Unscoped1'; this va_arg has undefined 
behavior because arguments will be promoted to 'int'}}
 

MitalAshok wrote:
> Unscoped1 is promoted to int when passed to a variadic function.
> 
> The underlying type for Unscoped1 is unsigned int, so only Unscoped1 and 
> unsigned int are compatible, not Unscoped1 and int. An Unscoped1 passed to a 
> variadic function must be retrieved via va_arg(ap, int).
> 
Although I guess the warning is now wrong because even though `void f(int x, 
...) { std::va_list ap; va_start(ap, x); va_arg(ap, Unscoped1); }` `f(0, 
Unscoped1{2})` would be UB, `f(0, 2u)` would not be UB.

The user still should be warned about it, so I could create a new warning 
"second argument to 'va_arg' is of promotable enumeration type 'Unscoped1'; 
this va_arg may have undefined behavior because arguments of this enumeration 
type will be promoted to 'int', not the underlying type 'unsigned int'", and 
maybe suggest a fix `Unscoped1{va_arg(ap, unsigned)}`.

Or we could ignore it and pretend that int and enums with underlying types 
unsigned are compatible for the purposes of va_arg


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2023-08-22 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok marked an inline comment as done.
MitalAshok added inline comments.



Comment at: clang/test/SemaCXX/varargs.cpp:34
   enum Unscoped1 { One = 0x7FFF };
-  (void)__builtin_va_arg(ap, Unscoped1); // ok
+  (void)__builtin_va_arg(ap, Unscoped1); // expected-warning {{second argument 
to 'va_arg' is of promotable type 'Unscoped1'; this va_arg has undefined 
behavior because arguments will be promoted to 'int'}}
 

Unscoped1 is promoted to int when passed to a variadic function.

The underlying type for Unscoped1 is unsigned int, so only Unscoped1 and 
unsigned int are compatible, not Unscoped1 and int. An Unscoped1 passed to a 
variadic function must be retrieved via va_arg(ap, int).



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2023-08-22 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok updated this revision to Diff 552357.
MitalAshok added a comment.

clang-format


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/AST/ASTContext.cpp
  clang/lib/AST/FormatString.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CXX/drs/dr7xx.cpp
  clang/test/CodeGen/xcore-abi.c
  clang/test/Sema/format-pointer.c
  clang/test/Sema/format-strings-pedantic.c
  clang/test/Sema/varargs.c
  clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
  clang/test/SemaCXX/varargs.cpp
  clang/www/cxx_dr_status.html

Index: clang/www/cxx_dr_status.html
===
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -4373,7 +4373,7 @@
 https://cplusplus.github.io/CWG/issues/722.html;>722
 CD2
 Can nullptr be passed to an ellipsis?
-Unknown
+Clang 18
   
   
 https://cplusplus.github.io/CWG/issues/726.html;>726
Index: clang/test/SemaCXX/varargs.cpp
===
--- clang/test/SemaCXX/varargs.cpp
+++ clang/test/SemaCXX/varargs.cpp
@@ -31,7 +31,7 @@
 // Ensure the correct behavior for promotable type UB checking.
 void promotable(int a, ...) {
   enum Unscoped1 { One = 0x7FFF };
-  (void)__builtin_va_arg(ap, Unscoped1); // ok
+  (void)__builtin_va_arg(ap, Unscoped1); // expected-warning {{second argument to 'va_arg' is of promotable type 'Unscoped1'; this va_arg has undefined behavior because arguments will be promoted to 'int'}}
 
   enum Unscoped2 { Two = 0x };
   (void)__builtin_va_arg(ap, Unscoped2); // ok
@@ -55,6 +55,24 @@
   (void)__builtin_va_arg(ap, unsigned int);
 
   (void)__builtin_va_arg(ap, bool); // expected-warning {{second argument to 'va_arg' is of promotable type 'bool'; this va_arg has undefined behavior because arguments will be promoted to 'int'}}
+
+  (void)__builtin_va_arg(ap, float); // expected-warning {{second argument to 'va_arg' is of promotable type 'float'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+  (void)__builtin_va_arg(ap, __fp16); // expected-warning {{second argument to 'va_arg' is of promotable type '__fp16'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+
+#if __cplusplus >= 201103L
+  (void)__builtin_va_arg(ap, decltype(nullptr)); // expected-warning {{second argument to 'va_arg' is of promotable type 'decltype(nullptr)' (aka 'std::nullptr_t'); this va_arg has undefined behavior because arguments will be promoted to 'void *'}}
+#endif
+
+  (void)__builtin_va_arg(ap, int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'int *'}}
+  (void)__builtin_va_arg(ap, const int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'const int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'const int *'}}
+
+  // _BitInts aren't promoted
+  (void)__builtin_va_arg(ap, _BitInt(7));
+  (void)__builtin_va_arg(ap, unsigned _BitInt(7));
+  (void)__builtin_va_arg(ap, _BitInt(32));
+  (void)__builtin_va_arg(ap, unsigned _BitInt(32));
+  (void)__builtin_va_arg(ap, _BitInt(33));
+  (void)__builtin_va_arg(ap, unsigned _BitInt(33));
 }
 
 #if __cplusplus >= 201103L
Index: clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
===
--- clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
+++ clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
@@ -5,6 +5,7 @@
 extern int printf(const char *restrict, ...);
 }
 
-void f(char *c) {
+void f(char *c, int *q) {
   printf("%p", c);
+  printf("%p", q);
 }
Index: clang/test/Sema/varargs.c
===
--- clang/test/Sema/varargs.c
+++ clang/test/Sema/varargs.c
@@ -75,6 +75,14 @@
 (void)__builtin_va_arg(args, enum E); // Don't warn here in C
 (void)__builtin_va_arg(args, short); // expected-warning {{second argument to 'va_arg' is of promotable type 'short'}}
 (void)__builtin_va_arg(args, char); // expected-warning {{second argument to 'va_arg' is of promotable type 'char'}}
+
+// _BitInts aren't promoted
+(void)__builtin_va_arg(args, _BitInt(7));
+(void)__builtin_va_arg(args, unsigned _BitInt(7));
+(void)__builtin_va_arg(args, _BitInt(32)); // OK
+(void)__builtin_va_arg(args, unsigned _BitInt(32)); // OK
+(void)__builtin_va_arg(args, _BitInt(33)); // OK
+(void)__builtin_va_arg(args, unsigned _BitInt(33)); // OK
 }
 
 void f10(int a, ...) {
@@ -121,3 +129,18 @@
   __builtin_va_list va;
   va_start(va, e);
 }
+
+void f15(__builtin_va_list args) {
+  (void)__builtin_va_arg(args, const int);
+  (void)__builtin_va_arg(args, const volatile int);
+  (void)__builtin_va_arg(args, 

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

2023-08-22 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok updated this revision to Diff 552356.
MitalAshok added a comment.

Use C's definition of type compatibility even in C++ mode (to not warn about 
enums promoted to their underlying types)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/AST/ASTContext.cpp
  clang/lib/AST/FormatString.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CXX/drs/dr7xx.cpp
  clang/test/CodeGen/xcore-abi.c
  clang/test/Sema/format-pointer.c
  clang/test/Sema/format-strings-pedantic.c
  clang/test/Sema/varargs.c
  clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
  clang/test/SemaCXX/varargs.cpp
  clang/www/cxx_dr_status.html

Index: clang/www/cxx_dr_status.html
===
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -4373,7 +4373,7 @@
 https://cplusplus.github.io/CWG/issues/722.html;>722
 CD2
 Can nullptr be passed to an ellipsis?
-Unknown
+Clang 18
   
   
 https://cplusplus.github.io/CWG/issues/726.html;>726
Index: clang/test/SemaCXX/varargs.cpp
===
--- clang/test/SemaCXX/varargs.cpp
+++ clang/test/SemaCXX/varargs.cpp
@@ -31,7 +31,7 @@
 // Ensure the correct behavior for promotable type UB checking.
 void promotable(int a, ...) {
   enum Unscoped1 { One = 0x7FFF };
-  (void)__builtin_va_arg(ap, Unscoped1); // ok
+  (void)__builtin_va_arg(ap, Unscoped1); // expected-warning {{second argument to 'va_arg' is of promotable type 'Unscoped1'; this va_arg has undefined behavior because arguments will be promoted to 'int'}}
 
   enum Unscoped2 { Two = 0x };
   (void)__builtin_va_arg(ap, Unscoped2); // ok
@@ -55,6 +55,24 @@
   (void)__builtin_va_arg(ap, unsigned int);
 
   (void)__builtin_va_arg(ap, bool); // expected-warning {{second argument to 'va_arg' is of promotable type 'bool'; this va_arg has undefined behavior because arguments will be promoted to 'int'}}
+
+  (void)__builtin_va_arg(ap, float); // expected-warning {{second argument to 'va_arg' is of promotable type 'float'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+  (void)__builtin_va_arg(ap, __fp16); // expected-warning {{second argument to 'va_arg' is of promotable type '__fp16'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+
+#if __cplusplus >= 201103L
+  (void)__builtin_va_arg(ap, decltype(nullptr)); // expected-warning {{second argument to 'va_arg' is of promotable type 'decltype(nullptr)' (aka 'std::nullptr_t'); this va_arg has undefined behavior because arguments will be promoted to 'void *'}}
+#endif
+
+  (void)__builtin_va_arg(ap, int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'int *'}}
+  (void)__builtin_va_arg(ap, const int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'const int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'const int *'}}
+
+  // _BitInts aren't promoted
+  (void)__builtin_va_arg(ap, _BitInt(7));
+  (void)__builtin_va_arg(ap, unsigned _BitInt(7));
+  (void)__builtin_va_arg(ap, _BitInt(32));
+  (void)__builtin_va_arg(ap, unsigned _BitInt(32));
+  (void)__builtin_va_arg(ap, _BitInt(33));
+  (void)__builtin_va_arg(ap, unsigned _BitInt(33));
 }
 
 #if __cplusplus >= 201103L
Index: clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
===
--- clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
+++ clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
@@ -5,6 +5,7 @@
 extern int printf(const char *restrict, ...);
 }
 
-void f(char *c) {
+void f(char *c, int *q) {
   printf("%p", c);
+  printf("%p", q);
 }
Index: clang/test/Sema/varargs.c
===
--- clang/test/Sema/varargs.c
+++ clang/test/Sema/varargs.c
@@ -75,6 +75,14 @@
 (void)__builtin_va_arg(args, enum E); // Don't warn here in C
 (void)__builtin_va_arg(args, short); // expected-warning {{second argument to 'va_arg' is of promotable type 'short'}}
 (void)__builtin_va_arg(args, char); // expected-warning {{second argument to 'va_arg' is of promotable type 'char'}}
+
+// _BitInts aren't promoted
+(void)__builtin_va_arg(args, _BitInt(7));
+(void)__builtin_va_arg(args, unsigned _BitInt(7));
+(void)__builtin_va_arg(args, _BitInt(32)); // OK
+(void)__builtin_va_arg(args, unsigned _BitInt(32)); // OK
+(void)__builtin_va_arg(args, _BitInt(33)); // OK
+(void)__builtin_va_arg(args, unsigned _BitInt(33)); // OK
 }
 
 void f10(int a, ...) {
@@ -121,3 +129,18 @@
   __builtin_va_list va;
   va_start(va, e);
 }
+
+void f15(__builtin_va_list args) {
+  

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

2023-08-17 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added a comment.

Precommit CI still has a related failure, it seems.




Comment at: clang/lib/Sema/SemaExpr.cpp:17317-17319
+if (TInfo->getType()->isSpecificBuiltinType(BuiltinType::Float) ||
+TInfo->getType()->isSpecificBuiltinType(BuiltinType::Half))
   PromoteType = Context.DoubleTy;

jcranmer-intel wrote:
> aaron.ballman wrote:
> > Hmmm... the existing code seems wrong to me because it's not paying any 
> > attention to `FLT_EVAL_METHOD`, but I think it probably should? CC 
> > @jcranmer-intel @zahiraam for opinions.
> > 
> > Actually, I wonder if the correct approach here is to split 
> > `Sema::DefaultArgumentPromotion()` up so that we can calculate what the 
> > default argument promoted type is of the expression independent of 
> > performing the actual promotion, and call the promotion type calculation 
> > logic here?
> C23 6.5.2.2p6 [draft N3096] says "trailing arguments that have type `float` 
> are promoted to `double`". `FLT_EVAL_METHOD` shouldn't need to apply here, 
> since it's largely about reflecting that things like x87 using 80-bit 
> precision internally, and not actual argument passing.
Ah that's good to know, thank you!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2023-08-16 Thread Joshua Cranmer via Phabricator via cfe-commits
jcranmer-intel added inline comments.



Comment at: clang/lib/Sema/SemaExpr.cpp:17317-17319
+if (TInfo->getType()->isSpecificBuiltinType(BuiltinType::Float) ||
+TInfo->getType()->isSpecificBuiltinType(BuiltinType::Half))
   PromoteType = Context.DoubleTy;

aaron.ballman wrote:
> Hmmm... the existing code seems wrong to me because it's not paying any 
> attention to `FLT_EVAL_METHOD`, but I think it probably should? CC 
> @jcranmer-intel @zahiraam for opinions.
> 
> Actually, I wonder if the correct approach here is to split 
> `Sema::DefaultArgumentPromotion()` up so that we can calculate what the 
> default argument promoted type is of the expression independent of performing 
> the actual promotion, and call the promotion type calculation logic here?
C23 6.5.2.2p6 [draft N3096] says "trailing arguments that have type `float` are 
promoted to `double`". `FLT_EVAL_METHOD` shouldn't need to apply here, since 
it's largely about reflecting that things like x87 using 80-bit precision 
internally, and not actual argument passing.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2023-08-10 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok updated this revision to Diff 549177.
MitalAshok added a comment.

clang-format


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/AST/FormatString.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CXX/drs/dr7xx.cpp
  clang/test/CodeGen/xcore-abi.c
  clang/test/Sema/format-pointer.c
  clang/test/Sema/format-strings-pedantic.c
  clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
  clang/test/SemaCXX/varargs.cpp
  clang/www/cxx_dr_status.html

Index: clang/www/cxx_dr_status.html
===
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -4373,7 +4373,7 @@
 https://cplusplus.github.io/CWG/issues/722.html;>722
 CD2
 Can nullptr be passed to an ellipsis?
-Unknown
+Clang 18
   
   
 https://cplusplus.github.io/CWG/issues/726.html;>726
Index: clang/test/SemaCXX/varargs.cpp
===
--- clang/test/SemaCXX/varargs.cpp
+++ clang/test/SemaCXX/varargs.cpp
@@ -55,6 +55,16 @@
   (void)__builtin_va_arg(ap, unsigned int);
 
   (void)__builtin_va_arg(ap, bool); // expected-warning {{second argument to 'va_arg' is of promotable type 'bool'; this va_arg has undefined behavior because arguments will be promoted to 'int'}}
+
+  (void)__builtin_va_arg(ap, float); // expected-warning {{second argument to 'va_arg' is of promotable type 'float'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+  (void)__builtin_va_arg(ap, __fp16); // expected-warning {{second argument to 'va_arg' is of promotable type '__fp16'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+
+#if __cplusplus >= 201103L
+  (void)__builtin_va_arg(ap, decltype(nullptr)); // expected-warning {{second argument to 'va_arg' is of promotable type 'decltype(nullptr)' (aka 'std::nullptr_t'); this va_arg has undefined behavior because arguments will be promoted to 'void *'}}
+#endif
+
+  (void)__builtin_va_arg(ap, int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'int *'}}
+  (void)__builtin_va_arg(ap, const int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'const int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'const int *'}}
 }
 
 #if __cplusplus >= 201103L
Index: clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
===
--- clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
+++ clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
@@ -5,6 +5,7 @@
 extern int printf(const char *restrict, ...);
 }
 
-void f(char *c) {
+void f(char *c, int *q) {
   printf("%p", c);
+  printf("%p", q);
 }
Index: clang/test/Sema/format-strings-pedantic.c
===
--- clang/test/Sema/format-strings-pedantic.c
+++ clang/test/Sema/format-strings-pedantic.c
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
 // RUN: %clang_cc1 -xobjective-c -fblocks -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
 // RUN: %clang_cc1 -xc++ -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
+// RUN: %clang_cc1 -std=c2x -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
 
 __attribute__((format(printf, 1, 2)))
 int printf(const char *restrict, ...);
@@ -14,7 +15,7 @@
   printf("%p", (id)0); // expected-warning {{format specifies type 'void *' but the argument has type 'id'}}
 #endif
 
-#ifdef __cplusplus
-  printf("%p", nullptr); // expected-warning {{format specifies type 'void *' but the argument has type 'std::nullptr_t'}}
+#if !__is_identifier(nullptr)
+  printf("%p", nullptr);
 #endif
 }
Index: clang/test/Sema/format-pointer.c
===
--- /dev/null
+++ clang/test/Sema/format-pointer.c
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -xc -Wformat %s -verify
+// RUN: %clang_cc1 -xc -Wformat -std=c2x %s -verify
+// RUN: %clang_cc1 -xc++ -Wformat %s -verify
+// RUN: %clang_cc1 -xobjective-c -Wformat -fblocks %s -verify
+// RUN: %clang_cc1 -xobjective-c++ -Wformat -fblocks %s -verify
+// RUN: %clang_cc1 -xc -std=c2x -Wformat %s -pedantic -verify=expected,pedantic
+// RUN: %clang_cc1 -xc++ -Wformat %s -pedantic -verify=expected,pedantic
+// RUN: %clang_cc1 -xobjective-c -Wformat -fblocks -pedantic %s -verify=expected,pedantic
+
+__attribute__((__format__(__printf__, 1, 2)))
+int printf(const char *, ...);
+__attribute__((__format__(__scanf__, 1, 2)))
+int scanf(const char *, ...);
+
+void f(void *vp, const void *cvp, char *cp, signed char *scp, int *ip) {
+  int arr[2];
+
+  printf("%p", cp);
+  printf("%p", cvp);
+  printf("%p", vp);
+  

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

2023-08-10 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok updated this revision to Diff 549176.
MitalAshok added a comment.

Address feedback; Reuse DefaultArgumentPromotion instead of duplicating its 
functionality when building VaArgExpr

There is the added bonus for it working with dependent types somewhat 
(`template __builtin_va_arg(ap, T[2]);` will warn in the template 
instead of waiting for it to be instantiated).
I can add the check for dependent types back if this is unwanted.

I don't think there are any edge cases where this will give a false warning.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/AST/FormatString.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CXX/drs/dr7xx.cpp
  clang/test/CodeGen/xcore-abi.c
  clang/test/Sema/format-pointer.c
  clang/test/Sema/format-strings-pedantic.c
  clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
  clang/test/SemaCXX/varargs.cpp
  clang/www/cxx_dr_status.html

Index: clang/www/cxx_dr_status.html
===
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -4373,7 +4373,7 @@
 https://cplusplus.github.io/CWG/issues/722.html;>722
 CD2
 Can nullptr be passed to an ellipsis?
-Unknown
+Clang 18
   
   
 https://cplusplus.github.io/CWG/issues/726.html;>726
Index: clang/test/SemaCXX/varargs.cpp
===
--- clang/test/SemaCXX/varargs.cpp
+++ clang/test/SemaCXX/varargs.cpp
@@ -55,6 +55,16 @@
   (void)__builtin_va_arg(ap, unsigned int);
 
   (void)__builtin_va_arg(ap, bool); // expected-warning {{second argument to 'va_arg' is of promotable type 'bool'; this va_arg has undefined behavior because arguments will be promoted to 'int'}}
+
+  (void)__builtin_va_arg(ap, float); // expected-warning {{second argument to 'va_arg' is of promotable type 'float'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+  (void)__builtin_va_arg(ap, __fp16); // expected-warning {{second argument to 'va_arg' is of promotable type '__fp16'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+
+#if __cplusplus >= 201103L
+  (void)__builtin_va_arg(ap, decltype(nullptr)); // expected-warning {{second argument to 'va_arg' is of promotable type 'decltype(nullptr)' (aka 'std::nullptr_t'); this va_arg has undefined behavior because arguments will be promoted to 'void *'}}
+#endif
+
+  (void)__builtin_va_arg(ap, int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'int *'}}
+  (void)__builtin_va_arg(ap, const int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'const int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'const int *'}}
 }
 
 #if __cplusplus >= 201103L
Index: clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
===
--- clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
+++ clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
@@ -5,6 +5,7 @@
 extern int printf(const char *restrict, ...);
 }
 
-void f(char *c) {
+void f(char *c, int *q) {
   printf("%p", c);
+  printf("%p", q);
 }
Index: clang/test/Sema/format-strings-pedantic.c
===
--- clang/test/Sema/format-strings-pedantic.c
+++ clang/test/Sema/format-strings-pedantic.c
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
 // RUN: %clang_cc1 -xobjective-c -fblocks -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
 // RUN: %clang_cc1 -xc++ -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
+// RUN: %clang_cc1 -std=c2x -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
 
 __attribute__((format(printf, 1, 2)))
 int printf(const char *restrict, ...);
@@ -14,7 +15,7 @@
   printf("%p", (id)0); // expected-warning {{format specifies type 'void *' but the argument has type 'id'}}
 #endif
 
-#ifdef __cplusplus
-  printf("%p", nullptr); // expected-warning {{format specifies type 'void *' but the argument has type 'std::nullptr_t'}}
+#if !__is_identifier(nullptr)
+  printf("%p", nullptr);
 #endif
 }
Index: clang/test/Sema/format-pointer.c
===
--- /dev/null
+++ clang/test/Sema/format-pointer.c
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -xc -Wformat %s -verify
+// RUN: %clang_cc1 -xc -Wformat -std=c2x %s -verify
+// RUN: %clang_cc1 -xc++ -Wformat %s -verify
+// RUN: %clang_cc1 -xobjective-c -Wformat -fblocks %s -verify
+// RUN: %clang_cc1 -xobjective-c++ -Wformat -fblocks %s -verify
+// RUN: %clang_cc1 -xc -std=c2x -Wformat %s -pedantic -verify=expected,pedantic
+// RUN: %clang_cc1 -xc++ -Wformat %s -pedantic 

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

2023-08-08 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added subscribers: jcranmer-intel, zahiraam.
aaron.ballman added inline comments.



Comment at: clang/lib/AST/FormatString.cpp:484-487
+  if (const auto *PT = argTy->getAs()) {
+if (PT->getPointeeType()->isCharType())
+  return Match;
+  }

We can simplify a bit further these days.



Comment at: clang/lib/AST/FormatString.cpp:522-534
+  if (const auto *PT = argTy->getAs()) {
+QualType pointeeTy = PT->getPointeeType();
+if (pointeeTy->isVoidType() || (!Ptr && pointeeTy->isCharType()))
+  return Match;
+return NoMatchPedantic;
+  } else if (argTy->isNullPtrType()) {
+return MatchPromotion;

Fixes to match the usual coding style rules.

Wow, Phab's diff engine struggles with that edit. Basically: no `else` after a 
`return`, remove braces on single-line `if`, renamed to `PointeeTy`.



Comment at: clang/lib/Sema/SemaExpr.cpp:1062-1072
+  // C2x 6.5.2.2p6:
+  //   The integer promotions are performed on each trailing argument, and
+  //   trailing arguments that have type float are promoted to double. These 
are
+  //   called the default argument promotions. No other conversions are
+  //   performed implicitly.
+
+  // C++ [expr.call]p7, per DR722:

I think this code should live in `Sema::DefaultArgumentPromotion()` because 
it's related specifically to default argument promotions: 
https://eel.is/c++draft/expr#call-11.sentence-5



Comment at: clang/lib/Sema/SemaExpr.cpp:17317-17319
+if (TInfo->getType()->isSpecificBuiltinType(BuiltinType::Float) ||
+TInfo->getType()->isSpecificBuiltinType(BuiltinType::Half))
   PromoteType = Context.DoubleTy;

Hmmm... the existing code seems wrong to me because it's not paying any 
attention to `FLT_EVAL_METHOD`, but I think it probably should? CC 
@jcranmer-intel @zahiraam for opinions.

Actually, I wonder if the correct approach here is to split 
`Sema::DefaultArgumentPromotion()` up so that we can calculate what the default 
argument promoted type is of the expression independent of performing the 
actual promotion, and call the promotion type calculation logic here?



Comment at: clang/test/Sema/format-pointer.c:39
+  printf("%p", np);
+  scanf("%p", );  // expected-warning {{format specifies type 'void **' but 
the argument has type 'nullptr_t *'}}
+  scanf("%p", );  // pedantic-warning {{format specifies type 'void **' 
but the argument has type 'nullptr_t **'}}

MitalAshok wrote:
> Should this be a pedantic warning?
> 
> If this reads a non-null pointer, the bit pattern of `np` will be messed up 
> but `np` will still read as a nullptr.
> If it reads a null pointer, it should be fine.
> 
That's a fun scenario, good test case!

C23 7.26.6.2p10:  Except in the case of a % specifier, the input item (or, in 
the case of a %n directive, the count of input characters) is converted to a 
type appropriate to the conversion specifier. If the input item is not a 
matching sequence, the execution of the directive fails: this condition is a 
matching failure. Unless assignment suppression was indicated by a *, the 
result of the conversion is placed in the object pointed to by the first 
argument following the format argument that has not already received a 
conversion result. If this object does not have an appropriate type, or if the 
result of the conversion cannot be represented in the object, the behavior is 
undefined.

p12, the p specifier: Matches an implementation-defined set of sequences, which 
should be the same as the set of sequences that may be produced by the %p 
conversion of the fprintf function. The corresponding argument shall be a 
pointer to a pointer of void. The input item is converted to a pointer value in 
an implementation-defined manner. If the input item is a value converted 
earlier during the same program execution, the pointer that results shall 
compare equal to that value; otherwise the behavior of the %p conversion is 
undefined.

The corresponding argument is not a pointer to a pointer of void, so it's UB, 
not just pedantically so.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2023-08-07 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok added inline comments.



Comment at: clang/test/Sema/format-pointer.c:39
+  printf("%p", np);
+  scanf("%p", );  // expected-warning {{format specifies type 'void **' but 
the argument has type 'nullptr_t *'}}
+  scanf("%p", );  // pedantic-warning {{format specifies type 'void **' 
but the argument has type 'nullptr_t **'}}

Should this be a pedantic warning?

If this reads a non-null pointer, the bit pattern of `np` will be messed up but 
`np` will still read as a nullptr.
If it reads a null pointer, it should be fine.



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2023-08-07 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok updated this revision to Diff 547874.
MitalAshok marked an inline comment as done.
MitalAshok added a comment.

Fix scanf("%p", (char**)ptr) for -Wformat-pedantic

Also added more tests for %p and -Wformat


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/AST/FormatString.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CXX/drs/dr7xx.cpp
  clang/test/CodeGen/xcore-abi.c
  clang/test/Sema/format-pointer.c
  clang/test/Sema/format-strings-pedantic.c
  clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
  clang/test/SemaCXX/varargs.cpp
  clang/www/cxx_dr_status.html

Index: clang/www/cxx_dr_status.html
===
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -4373,7 +4373,7 @@
 https://cplusplus.github.io/CWG/issues/722.html;>722
 CD2
 Can nullptr be passed to an ellipsis?
-Unknown
+Clang 18
   
   
 https://cplusplus.github.io/CWG/issues/726.html;>726
Index: clang/test/SemaCXX/varargs.cpp
===
--- clang/test/SemaCXX/varargs.cpp
+++ clang/test/SemaCXX/varargs.cpp
@@ -55,6 +55,16 @@
   (void)__builtin_va_arg(ap, unsigned int);
 
   (void)__builtin_va_arg(ap, bool); // expected-warning {{second argument to 'va_arg' is of promotable type 'bool'; this va_arg has undefined behavior because arguments will be promoted to 'int'}}
+
+  (void)__builtin_va_arg(ap, float); // expected-warning {{second argument to 'va_arg' is of promotable type 'float'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+  (void)__builtin_va_arg(ap, __fp16); // expected-warning {{second argument to 'va_arg' is of promotable type '__fp16'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+
+#if __cplusplus >= 201103L
+  (void)__builtin_va_arg(ap, decltype(nullptr)); // expected-warning {{second argument to 'va_arg' is of promotable type 'decltype(nullptr)' (aka 'std::nullptr_t'); this va_arg has undefined behavior because arguments will be promoted to 'void *'}}
+#endif
+
+  (void)__builtin_va_arg(ap, int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'int *'}}
+  (void)__builtin_va_arg(ap, const int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'const int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'const int *'}}
 }
 
 #if __cplusplus >= 201103L
Index: clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
===
--- clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
+++ clang/test/SemaCXX/format-strings-0x-nopedantic.cpp
@@ -5,6 +5,7 @@
 extern int printf(const char *restrict, ...);
 }
 
-void f(char *c) {
+void f(char *c, int *q) {
   printf("%p", c);
+  printf("%p", q);
 }
Index: clang/test/Sema/format-strings-pedantic.c
===
--- clang/test/Sema/format-strings-pedantic.c
+++ clang/test/Sema/format-strings-pedantic.c
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
 // RUN: %clang_cc1 -xobjective-c -fblocks -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
 // RUN: %clang_cc1 -xc++ -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
+// RUN: %clang_cc1 -std=c2x -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
 
 __attribute__((format(printf, 1, 2)))
 int printf(const char *restrict, ...);
@@ -14,7 +15,7 @@
   printf("%p", (id)0); // expected-warning {{format specifies type 'void *' but the argument has type 'id'}}
 #endif
 
-#ifdef __cplusplus
-  printf("%p", nullptr); // expected-warning {{format specifies type 'void *' but the argument has type 'std::nullptr_t'}}
+#if !__is_identifier(nullptr)
+  printf("%p", nullptr);
 #endif
 }
Index: clang/test/Sema/format-pointer.c
===
--- /dev/null
+++ clang/test/Sema/format-pointer.c
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -xc -Wformat %s -verify
+// RUN: %clang_cc1 -xc -Wformat -std=c2x %s -verify
+// RUN: %clang_cc1 -xc++ -Wformat %s -verify
+// RUN: %clang_cc1 -xobjective-c -Wformat -fblocks %s -verify
+// RUN: %clang_cc1 -xobjective-c++ -Wformat -fblocks %s -verify
+// RUN: %clang_cc1 -xc -std=c2x -Wformat %s -pedantic -verify=expected,pedantic
+// RUN: %clang_cc1 -xc++ -Wformat %s -pedantic -verify=expected,pedantic
+// RUN: %clang_cc1 -xobjective-c -Wformat -fblocks -pedantic %s -verify=expected,pedantic
+
+__attribute__((__format__(__printf__, 1, 2)))
+int printf(const char *, ...);
+__attribute__((__format__(__scanf__, 1, 2)))
+int scanf(const char *, ...);
+
+void f(void *vp, const void *cvp, char 

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

2023-08-07 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added a comment.

Precommit CI found a related issue that should be addressed.




Comment at: clang/www/cxx_dr_status.html:4376
 Can nullptr be passed to an ellipsis?
-Unknown
+Clang 17
   

MitalAshok wrote:
> 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
I think it's better to use Clang 18, otherwise people will think there's a 
diagnostic bug with earlier versions. We usually use "Yes" to mean "we've 
always supported this correctly, as best we can tell".


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2023-08-04 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok updated this revision to Diff 547353.
MitalAshok added a comment.

C99 7.15.1.1p2 explicitly allows a char* to be retrieved as a void* with 
va_arg, so the -Wformat-pedantic warning was incorrect.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

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

Index: clang/www/cxx_dr_status.html
===
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -4373,7 +4373,7 @@
 https://cplusplus.github.io/CWG/issues/722.html;>722
 CD2
 Can nullptr be passed to an ellipsis?
-Unknown
+Clang 18
   
   
 https://cplusplus.github.io/CWG/issues/726.html;>726
Index: clang/test/SemaCXX/varargs.cpp
===
--- clang/test/SemaCXX/varargs.cpp
+++ clang/test/SemaCXX/varargs.cpp
@@ -55,6 +55,16 @@
   (void)__builtin_va_arg(ap, unsigned int);
 
   (void)__builtin_va_arg(ap, bool); // expected-warning {{second argument to 'va_arg' is of promotable type 'bool'; this va_arg has undefined behavior because arguments will be promoted to 'int'}}
+
+  (void)__builtin_va_arg(ap, float); // expected-warning {{second argument to 'va_arg' is of promotable type 'float'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+  (void)__builtin_va_arg(ap, __fp16); // expected-warning {{second argument to 'va_arg' is of promotable type '__fp16'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+
+#if __cplusplus >= 201103L
+  (void)__builtin_va_arg(ap, decltype(nullptr)); // expected-warning {{second argument to 'va_arg' is of promotable type 'decltype(nullptr)' (aka 'std::nullptr_t'); this va_arg has undefined behavior because arguments will be promoted to 'void *'}}
+#endif
+
+  (void)__builtin_va_arg(ap, int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'int *'}}
+  (void)__builtin_va_arg(ap, const int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'const int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'const int *'}}
 }
 
 #if __cplusplus >= 201103L
Index: clang/test/Sema/format-strings-pedantic.c
===
--- clang/test/Sema/format-strings-pedantic.c
+++ clang/test/Sema/format-strings-pedantic.c
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
 // RUN: %clang_cc1 -xobjective-c -fblocks -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
 // RUN: %clang_cc1 -xc++ -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
+// RUN: %clang_cc1 -std=c2x -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
 
 __attribute__((format(printf, 1, 2)))
 int printf(const char *restrict, ...);
@@ -14,7 +15,7 @@
   printf("%p", (id)0); // expected-warning {{format specifies type 'void *' but the argument has type 'id'}}
 #endif
 
-#ifdef __cplusplus
-  printf("%p", nullptr); // expected-warning {{format specifies type 'void *' but the argument has type 'std::nullptr_t'}}
+#if !__is_identifier(nullptr)
+  printf("%p", nullptr);
 #endif
 }
Index: clang/test/CodeGen/xcore-abi.c
===
--- clang/test/CodeGen/xcore-abi.c
+++ clang/test/CodeGen/xcore-abi.c
@@ -76,7 +76,8 @@
   // CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[V5]], ptr align 4 [[P]], i32 20, i1 false)
   // CHECK: call void @f(ptr noundef [[V5]])
 
-  int* v6 = va_arg (ap, int[4]);  // an unusual aggregate type
+  // an unusual aggregate type
+  int* v6 = va_arg (ap, int[4]);  // expected-warning{{second argument to 'va_arg' is of promotable type 'int[4]'}}
   f(v6);
   // CHECK: [[I:%[a-z0-9]+]] = load ptr, ptr [[AP]]
   // CHECK: [[P:%[a-z0-9]+]] = load ptr, ptr [[I]]
Index: clang/test/CXX/drs/dr7xx.cpp
===
--- clang/test/CXX/drs/dr7xx.cpp
+++ clang/test/CXX/drs/dr7xx.cpp
@@ -53,6 +53,15 @@
 #endif
 }
 
+namespace dr722 { // dr722: 18
+#if __cplusplus >= 201103L
+  int x = __builtin_printf("%p", nullptr);
+  void f(__builtin_va_list args) {
+__builtin_va_arg(args, decltype(nullptr)); // expected-warning {{second argument to 'va_arg' is of promotable type 'decltype(nullptr)' (aka 'std::nullptr_t'); this va_arg has undefined behavior because arguments will be promoted to 'void *'}}
+  }
+#endif
+}
+
 namespace dr727 { // dr727: partial
   struct A {
 template struct C; // expected-note 6{{here}}

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

2023-08-04 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok updated this revision to Diff 547311.
MitalAshok added a comment.

No longer warn on printf("%p", nullptr)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

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

Index: clang/www/cxx_dr_status.html
===
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -4373,7 +4373,7 @@
 https://cplusplus.github.io/CWG/issues/722.html;>722
 CD2
 Can nullptr be passed to an ellipsis?
-Unknown
+Clang 18
   
   
 https://cplusplus.github.io/CWG/issues/726.html;>726
Index: clang/test/SemaCXX/varargs.cpp
===
--- clang/test/SemaCXX/varargs.cpp
+++ clang/test/SemaCXX/varargs.cpp
@@ -55,6 +55,16 @@
   (void)__builtin_va_arg(ap, unsigned int);
 
   (void)__builtin_va_arg(ap, bool); // expected-warning {{second argument to 'va_arg' is of promotable type 'bool'; this va_arg has undefined behavior because arguments will be promoted to 'int'}}
+
+  (void)__builtin_va_arg(ap, float); // expected-warning {{second argument to 'va_arg' is of promotable type 'float'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+  (void)__builtin_va_arg(ap, __fp16); // expected-warning {{second argument to 'va_arg' is of promotable type '__fp16'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+
+#if __cplusplus >= 201103L
+  (void)__builtin_va_arg(ap, decltype(nullptr)); // expected-warning {{second argument to 'va_arg' is of promotable type 'decltype(nullptr)' (aka 'std::nullptr_t'); this va_arg has undefined behavior because arguments will be promoted to 'void *'}}
+#endif
+
+  (void)__builtin_va_arg(ap, int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'int *'}}
+  (void)__builtin_va_arg(ap, const int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'const int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'const int *'}}
 }
 
 #if __cplusplus >= 201103L
Index: clang/test/Sema/format-strings-pedantic.c
===
--- clang/test/Sema/format-strings-pedantic.c
+++ clang/test/Sema/format-strings-pedantic.c
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
 // RUN: %clang_cc1 -xobjective-c -fblocks -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
 // RUN: %clang_cc1 -xc++ -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
+// RUN: %clang_cc1 -std=c2x -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
 
 __attribute__((format(printf, 1, 2)))
 int printf(const char *restrict, ...);
@@ -14,7 +15,7 @@
   printf("%p", (id)0); // expected-warning {{format specifies type 'void *' but the argument has type 'id'}}
 #endif
 
-#ifdef __cplusplus
-  printf("%p", nullptr); // expected-warning {{format specifies type 'void *' but the argument has type 'std::nullptr_t'}}
+#if !__is_identifier(nullptr)
+  printf("%p", nullptr);
 #endif
 }
Index: clang/test/CodeGen/xcore-abi.c
===
--- clang/test/CodeGen/xcore-abi.c
+++ clang/test/CodeGen/xcore-abi.c
@@ -76,7 +76,8 @@
   // CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[V5]], ptr align 4 [[P]], i32 20, i1 false)
   // CHECK: call void @f(ptr noundef [[V5]])
 
-  int* v6 = va_arg (ap, int[4]);  // an unusual aggregate type
+  // an unusual aggregate type
+  int* v6 = va_arg (ap, int[4]);  // expected-warning{{second argument to 'va_arg' is of promotable type 'int[4]'}}
   f(v6);
   // CHECK: [[I:%[a-z0-9]+]] = load ptr, ptr [[AP]]
   // CHECK: [[P:%[a-z0-9]+]] = load ptr, ptr [[I]]
Index: clang/test/CXX/drs/dr7xx.cpp
===
--- clang/test/CXX/drs/dr7xx.cpp
+++ clang/test/CXX/drs/dr7xx.cpp
@@ -53,6 +53,15 @@
 #endif
 }
 
+namespace dr722 { // dr722: 18
+#if __cplusplus >= 201103L
+  int x = __builtin_printf("%p", nullptr);
+  void f(__builtin_va_list args) {
+__builtin_va_arg(args, decltype(nullptr)); // expected-warning {{second argument to 'va_arg' is of promotable type 'decltype(nullptr)' (aka 'std::nullptr_t'); this va_arg has undefined behavior because arguments will be promoted to 'void *'}}
+  }
+#endif
+}
+
 namespace dr727 { // dr727: partial
   struct A {
 template struct C; // expected-note 6{{here}}
Index: clang/lib/Sema/SemaExpr.cpp

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

2023-08-03 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added a comment.

Thank you for working on this! FWIW, precommit Ci found a relevant test failure 
that should also be addressed.




Comment at: clang/lib/Sema/SemaExpr.cpp:1062-1073
+  // C2x 6.5.2.2p6:
+  //   The integer promotions are performed on each trailing argument, and
+  //   trailing arguments that have type float are promoted to double. These 
are
+  //   called the default argument promotions. No other conversions are
+  //   performed implicitly.
+
+  // C++ [expr.call]p7, per DR722:

Oh fun, C and C++ solved this issue differently. In C++, there's an implicit 
conversion so the nullptr_t is converted to void * on the call, and in C 
there's an allowance for va_arg to handle nullptr_t as a void *.

And without further changes, C++ picks that rule up automatically once it 
rebases onto C23: http://eel.is/c++draft/support#cstdarg.syn-1



Comment at: clang/lib/Sema/SemaExpr.cpp:17328
+  PromoteType = Context.VoidPtrTy;
+if (TInfo->getType()->isArrayType())
+  PromoteType = Context.getArrayDecayedType(TInfo->getType());

MitalAshok wrote:
> 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*`.
`_Complex double` and `double[2]` are not compatible types in C.

C2x 6.2.7p1: Two types are compatible types if they are the same. Additional 
rules for determining whether two types are compatible are described in 6.7.2 
for type specifiers, in 6.7.3 for type qualifiers, and in 6.7.6 for 
declarators. ... (The rest is talking about structures, enumerations, and 
unions).

`_Complex` is a type specifier, so

C2x 6.7.2p7: Each of the comma-separated multisets designates the same type, 
except that for bit-fields, it is implementation-defined whether the specifier 
int designates the same type as signed int or the same type as unsigned int.

(The multisets it describes do not include any array types.)



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

MitalAshok wrote:
> 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
I don't think this should be diagnosed pedantically; the code is correct.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

https://reviews.llvm.org/D156054

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2023-07-25 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok updated this revision to Diff 544073.
MitalAshok added a comment.

Target clang 18 instead


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156054/new/

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

Index: clang/www/cxx_dr_status.html
===
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -4373,7 +4373,7 @@
 https://cplusplus.github.io/CWG/issues/722.html;>722
 CD2
 Can nullptr be passed to an ellipsis?
-Unknown
+Clang 18
   
   
 https://cplusplus.github.io/CWG/issues/726.html;>726
Index: clang/test/SemaCXX/varargs.cpp
===
--- clang/test/SemaCXX/varargs.cpp
+++ clang/test/SemaCXX/varargs.cpp
@@ -55,6 +55,16 @@
   (void)__builtin_va_arg(ap, unsigned int);
 
   (void)__builtin_va_arg(ap, bool); // expected-warning {{second argument to 'va_arg' is of promotable type 'bool'; this va_arg has undefined behavior because arguments will be promoted to 'int'}}
+
+  (void)__builtin_va_arg(ap, float); // expected-warning {{second argument to 'va_arg' is of promotable type 'float'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+  (void)__builtin_va_arg(ap, __fp16); // expected-warning {{second argument to 'va_arg' is of promotable type '__fp16'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+
+#if __cplusplus >= 201103L
+  (void)__builtin_va_arg(ap, decltype(nullptr)); // expected-warning {{second argument to 'va_arg' is of promotable type 'decltype(nullptr)' (aka 'std::nullptr_t'); this va_arg has undefined behavior because arguments will be promoted to 'void *'}}
+#endif
+
+  (void)__builtin_va_arg(ap, int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'int *'}}
+  (void)__builtin_va_arg(ap, const int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'const int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'const int *'}}
 }
 
 #if __cplusplus >= 201103L
Index: clang/test/Sema/format-strings-pedantic.c
===
--- clang/test/Sema/format-strings-pedantic.c
+++ clang/test/Sema/format-strings-pedantic.c
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
 // RUN: %clang_cc1 -xobjective-c -fblocks -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
 // RUN: %clang_cc1 -xc++ -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
+// RUN: %clang_cc1 -std=c2x -fsyntax-only -verify -Wno-format -Wformat-pedantic %s
 
 __attribute__((format(printf, 1, 2)))
 int printf(const char *restrict, ...);
@@ -15,6 +16,8 @@
 #endif
 
 #ifdef __cplusplus
-  printf("%p", nullptr); // expected-warning {{format specifies type 'void *' but the argument has type 'std::nullptr_t'}}
+  printf("%p", nullptr);
+#elif !__is_identifier(nullptr)
+  printf("%p", nullptr); // expected-warning {{format specifies type 'void *' but the argument has type 'nullptr_t'}}
 #endif
 }
Index: clang/test/CXX/drs/dr7xx.cpp
===
--- clang/test/CXX/drs/dr7xx.cpp
+++ clang/test/CXX/drs/dr7xx.cpp
@@ -53,6 +53,15 @@
 #endif
 }
 
+namespace dr722 { // dr722: 18
+#if __cplusplus >= 201103L
+  int x = __builtin_printf("%p", nullptr);
+  void f(__builtin_va_list args) {
+__builtin_va_arg(args, decltype(nullptr)); // expected-warning {{second argument to 'va_arg' is of promotable type 'decltype(nullptr)' (aka 'std::nullptr_t'); this va_arg has undefined behavior because arguments will be promoted to 'void *'}}
+  }
+#endif
+}
+
 namespace dr727 { // dr727: partial
   struct A {
 template struct C; // expected-note 6{{here}}
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -936,9 +936,9 @@
 //   enumeration, pointer, pointer to member, or class type, the program
 //   is ill-formed.
 //
-// Since we've already performed array-to-pointer and function-to-pointer
-// decay, the only such type in C++ is cv void. This also handles
-// initializer lists as variadic arguments.
+// Since we've already performed null pointer conversion, array-to-pointer
+// decay and function-to-pointer decay, the only such type in C++ is cv
+// void. This also handles initializer lists as variadic arguments.
 if (Ty->isVoidType())
   return VAK_Invalid;
 
@@ -1059,6 +1059,19 @@
 
   E = ExprRes.get();
 
+  // 

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

2023-07-23 Thread Mital Ashok via Phabricator via cfe-commits
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 = 
  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
 Can nullptr be passed to an ellipsis?
-Unknown
+Clang 17
   

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

Index: clang/www/cxx_dr_status.html
===
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -4373,7 +4373,7 @@
 https://cplusplus.github.io/CWG/issues/722.html;>722
 CD2
 Can nullptr be passed to an ellipsis?
-Unknown
+Clang 17
   
   
 https://cplusplus.github.io/CWG/issues/726.html;>726
Index: clang/test/SemaCXX/varargs.cpp
===
--- clang/test/SemaCXX/varargs.cpp
+++ clang/test/SemaCXX/varargs.cpp
@@ -55,6 +55,16 @@
   (void)__builtin_va_arg(ap, unsigned int);
 
   (void)__builtin_va_arg(ap, bool); // expected-warning {{second argument to 'va_arg' is of promotable type 'bool'; this va_arg has undefined behavior because arguments will be promoted to 'int'}}
+
+  (void)__builtin_va_arg(ap, float); // expected-warning {{second argument to 'va_arg' is of promotable type 'float'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+  (void)__builtin_va_arg(ap, __fp16); // expected-warning {{second argument to 'va_arg' is of promotable type '__fp16'; this va_arg has undefined behavior because arguments will be promoted to 'double'}}
+
+#if __cplusplus >= 201103L
+  (void)__builtin_va_arg(ap, decltype(nullptr)); // expected-warning {{second argument to 'va_arg' is of promotable type 'decltype(nullptr)' (aka 'std::nullptr_t'); this va_arg has undefined behavior because arguments will be promoted to 'void *'}}
+#endif
+
+  (void)__builtin_va_arg(ap, int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'int *'}}
+  (void)__builtin_va_arg(ap, const int[3]); // expected-warning {{second argument to 'va_arg' is of promotable type 'const int[3]'; this va_arg has undefined behavior because arguments will be promoted to 'const int *'}}
 }
 
 #if __cplusplus >= 201103L
Index: clang/test/Sema/format-strings-pedantic.c
===
--- clang/test/Sema/format-strings-pedantic.c
+++