[PATCH] D125802: Fix std::has_unique_object_representations for _BitInt types with padding bits

2022-05-17 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok created this revision.
Herald added a project: All.
MitalAshok retitled this revision from "Fix 
std::has_unique_object_representations for _BitInt types with padding" to "Fix 
std::has_unique_object_representations for _BitInt types with padding bits".
MitalAshok edited the summary of this revision.
MitalAshok added reviewers: erichkeane, aaron.ballman.
MitalAshok added a reviewer: rsmith.
MitalAshok edited projects, added clang; removed All.
Herald added a project: All.
MitalAshok published this revision for review.
Herald added a subscriber: cfe-commits.

"std::has_unique_object_representations<_BitInt(N)>" was always true, even if 
the type has padding bits (since the trait assumes all integer types have no 
padding bits). The standard has an explicit note that this should not hold for 
types with padding bits.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D125802

Files:
  clang/lib/AST/ASTContext.cpp
  clang/test/SemaCXX/has_unique_object_reps_bitint.cpp

Index: clang/test/SemaCXX/has_unique_object_reps_bitint.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/has_unique_object_reps_bitint.cpp
@@ -0,0 +1,76 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify -std=c++17 -Wno-bitfield-width %s
+//  expected-no-diagnostics
+
+static_assert(__has_unique_object_representations(_BitInt(8)));
+static_assert(__has_unique_object_representations(unsigned _BitInt(8)));
+static_assert(__has_unique_object_representations(_BitInt(sizeof(int) * 8u)));
+static_assert(sizeof(_BitInt(24)) != 4 || !__has_unique_object_representations(_BitInt(24)));
+
+static_assert(!__has_unique_object_representations(_BitInt(7)));
+static_assert(!__has_unique_object_representations(unsigned _BitInt(7)));
+static_assert(!__has_unique_object_representations(_BitInt(2)));
+static_assert(!__has_unique_object_representations(unsigned _BitInt(1)));
+
+template 
+constexpr bool check() {
+  if constexpr (N <= __BITINT_MAXWIDTH__) {
+static_assert(__has_unique_object_representations(_BitInt(N)) == (sizeof(_BitInt(N)) * 8u == N));
+static_assert(__has_unique_object_representations(unsigned _BitInt(N)) == (sizeof(unsigned _BitInt(N)) * 8u == N));
+  }
+  return true;
+}
+
+template 
+constexpr bool do_check = (check() && ...);
+
+static_assert(do_check<2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18>);
+static_assert(do_check<15, 16, 17, 23, 24, 25, 31, 32, 33>);
+static_assert(do_check<39, 40, 41, 47, 48, 49>);
+static_assert(do_check<127, 128, 129, 255, 256, 257, 383, 384, 385>);
+
+template 
+struct in_struct {
+  _BitInt(N) x;
+  static constexpr bool check() {
+return __has_unique_object_representations(in_struct) == __has_unique_object_representations(_BitInt(N));
+  }
+};
+
+static_assert(in_struct<8>::check());
+static_assert(in_struct<7>::check());
+
+struct bit_fields_1 {
+  _BitInt(7) x : 7;
+  unsigned _BitInt(1) y : 1;
+};
+
+static_assert(__has_unique_object_representations(bit_fields_1) == (sizeof(bit_fields_1) == 1));
+
+struct bit_fields_2 {
+  _BitInt(8) x : 7;
+};
+
+static_assert(!__has_unique_object_representations(bit_fields_2));
+
+struct bit_fields_3 {
+  _BitInt(15) x : 8;
+};
+
+static_assert(__has_unique_object_representations(bit_fields_3) == (sizeof(bit_fields_3) == 1));
+
+#if __BITINT_MAXWIDTH__ >= 129
+struct bit_fields_4 {
+  _BitInt(129) x : 128;
+};
+
+static_assert(__has_unique_object_representations(bit_fields_4) == (sizeof(bit_fields_4) == 128 / 8));
+#endif
+
+struct bit_fields_5 {
+  _BitInt(2) x : 8;
+};
+
+static_assert(!__has_unique_object_representations(bit_fields_5));
+
+static_assert(__has_unique_object_representations(_BitInt(7)&) == __has_unique_object_representations(_BitInt(8)&));
+static_assert(__has_unique_object_representations(_BitInt(8)&) == __has_unique_object_representations(int&));
Index: clang/lib/AST/ASTContext.cpp
===
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -2684,7 +2684,12 @@
 if (!RD->isUnion())
   return structHasUniqueObjectRepresentations(Context, RD);
   }
-  if (!Field->getType()->isReferenceType() &&
+
+  // A _BitInt type may not be unique if it has padding bits
+  // but if it is a bitfield the padding bits are not used
+  bool IsBitIntType =
+  !Field->getType()->isReferenceType() && Field->getType()->isBitIntType();
+  if (!Field->getType()->isReferenceType() && !IsBitIntType &&
   !Context.hasUniqueObjectRepresentations(Field->getType()))
 return llvm::None;
 
@@ -2692,9 +2697,17 @@
   Context.toBits(Context.getTypeSizeInChars(Field->getType()));
   if (Field->isBitField()) {
 int64_t BitfieldSize = Field->getBitWidthValue(Context);
-if (BitfieldSize > FieldSizeInBits)
+if (IsBitIntType) {
+  if ((unsigned)BitfieldSize >
+  cast(Field->getType())->getNumBits())
+return llvm::None;
+} els

[PATCH] D125802: Fix std::has_unique_object_representations for _BitInt types with padding bits

2022-05-17 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok added inline comments.



Comment at: clang/lib/AST/ASTContext.cpp:2697
   int64_t FieldSizeInBits =
   Context.toBits(Context.getTypeSizeInChars(Field->getType()));
   if (Field->isBitField()) {

erichkeane wrote:
> This answer ends up being wrong in the case of _BitInt, consider _BitInt(7).  
> Its field-size would be 7, yet this would result in 8.  I'm not sure of the 
> fallout of this though.
The field size should be 8 for _BitInt(7), since it takes 8 bits in the struct 
(including the padding bit). It is filtered out later with 
"hasUniqueObjectRepresentations" on line 2709 if it wasn't in a bit field



Comment at: clang/test/SemaCXX/has_unique_object_reps_bitint.cpp:7
+static_assert(__has_unique_object_representations(_BitInt(sizeof(int) * 8u)));
+static_assert(sizeof(_BitInt(24)) != 4 || 
!__has_unique_object_representations(_BitInt(24)));
+

erichkeane wrote:
> Whats going on here?  I don't particularly get the condition.
sizeof(_BitInt(24)) == sizeof(int32_t) (4) since we align to the next larger 
builtin integer type. But if that weren't the case for some reason (i.e., that 
changes in the future, I don't know if _BitInt is ABI stable), this wouldn't 
start failing for unrelated reasons


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D125802

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


[PATCH] D125802: Fix std::has_unique_object_representations for _BitInt types with padding bits

2022-05-17 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok updated this revision to Diff 430186.
MitalAshok edited the summary of this revision.
MitalAshok added a comment.

Added release note and missing test for struct with reference member


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D125802

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/AST/ASTContext.cpp
  clang/test/SemaCXX/has_unique_object_reps_bitint.cpp

Index: clang/test/SemaCXX/has_unique_object_reps_bitint.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/has_unique_object_reps_bitint.cpp
@@ -0,0 +1,88 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify -std=c++17 -Wno-bitfield-width %s
+//  expected-no-diagnostics
+
+static_assert(__has_unique_object_representations(_BitInt(8)));
+static_assert(__has_unique_object_representations(unsigned _BitInt(8)));
+static_assert(__has_unique_object_representations(_BitInt(sizeof(int) * 8u)));
+// sizeof(_BitInt(24)) may be 4 to align it to the next greater integer type, in which case it would have 8 padding bits
+static_assert(__has_unique_object_representations(_BitInt(24)) == (sizeof(_BitInt(24)) == 3));
+
+static_assert(!__has_unique_object_representations(_BitInt(7)));
+static_assert(!__has_unique_object_representations(unsigned _BitInt(7)));
+static_assert(!__has_unique_object_representations(_BitInt(2)));
+static_assert(!__has_unique_object_representations(unsigned _BitInt(1)));
+
+template 
+constexpr bool check() {
+  if constexpr (N <= __BITINT_MAXWIDTH__) {
+static_assert(__has_unique_object_representations(_BitInt(N)) == (sizeof(_BitInt(N)) * 8u == N));
+static_assert(__has_unique_object_representations(unsigned _BitInt(N)) == (sizeof(unsigned _BitInt(N)) * 8u == N));
+  }
+  return true;
+}
+
+template 
+constexpr bool do_check = (check() && ...);
+
+static_assert(do_check<2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18>);
+static_assert(do_check<15, 16, 17, 23, 24, 25, 31, 32, 33>);
+static_assert(do_check<39, 40, 41, 47, 48, 49>);
+static_assert(do_check<127, 128, 129, 255, 256, 257, 383, 384, 385>);
+
+template 
+struct in_struct {
+  _BitInt(N) x;
+  static constexpr bool check() {
+return __has_unique_object_representations(in_struct) == __has_unique_object_representations(_BitInt(N));
+  }
+};
+
+static_assert(in_struct<8>::check());
+static_assert(in_struct<7>::check());
+
+struct bit_fields_1 {
+  _BitInt(7) x : 7;
+  unsigned _BitInt(1) y : 1;
+};
+
+static_assert(__has_unique_object_representations(bit_fields_1) == (sizeof(bit_fields_1) == 1));
+
+struct bit_fields_2 {
+  _BitInt(8) x : 7;
+};
+
+static_assert(!__has_unique_object_representations(bit_fields_2));
+
+struct bit_fields_3 {
+  _BitInt(15) x : 8;
+};
+
+static_assert(__has_unique_object_representations(bit_fields_3) == (sizeof(bit_fields_3) == 1));
+
+#if __BITINT_MAXWIDTH__ >= 129
+struct bit_fields_4 {
+  _BitInt(129) x : 128;
+};
+
+static_assert(__has_unique_object_representations(bit_fields_4) == (sizeof(bit_fields_4) == 128 / 8));
+#endif
+
+struct bit_fields_5 {
+  _BitInt(2) x : 8;
+};
+
+static_assert(!__has_unique_object_representations(bit_fields_5));
+
+template 
+struct ref_member {
+  _BitInt(N) & x;
+};
+
+struct int_ref_member {
+  int &x;
+};
+
+static_assert(__has_unique_object_representations(ref_member<7>));
+static_assert(__has_unique_object_representations(ref_member<8>));
+static_assert(__has_unique_object_representations(ref_member<7>) == __has_unique_object_representations(ref_member<8>));
+static_assert(__has_unique_object_representations(ref_member<8>) == __has_unique_object_representations(int_ref_member));
Index: clang/lib/AST/ASTContext.cpp
===
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -2684,7 +2684,12 @@
 if (!RD->isUnion())
   return structHasUniqueObjectRepresentations(Context, RD);
   }
-  if (!Field->getType()->isReferenceType() &&
+
+  // A _BitInt type may not be unique if it has padding bits
+  // but if it is a bitfield the padding bits are not used
+  bool IsBitIntType =
+  !Field->getType()->isReferenceType() && Field->getType()->isBitIntType();
+  if (!Field->getType()->isReferenceType() && !IsBitIntType &&
   !Context.hasUniqueObjectRepresentations(Field->getType()))
 return llvm::None;
 
@@ -2692,9 +2697,17 @@
   Context.toBits(Context.getTypeSizeInChars(Field->getType()));
   if (Field->isBitField()) {
 int64_t BitfieldSize = Field->getBitWidthValue(Context);
-if (BitfieldSize > FieldSizeInBits)
+if (IsBitIntType) {
+  if ((unsigned)BitfieldSize >
+  cast(Field->getType())->getNumBits())
+return llvm::None;
+} else if (BitfieldSize > FieldSizeInBits) {
   return llvm::None;
+}
 FieldSizeInBits = BitfieldSize;
+  } else if (IsBitIntType &&
+ !Context.hasUnique

[PATCH] D125802: Fix std::has_unique_object_representations for _BitInt types with padding bits

2022-05-18 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok updated this revision to Diff 430373.
MitalAshok added a comment.

Removed useless isReferenceType check


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D125802

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/AST/ASTContext.cpp
  clang/test/SemaCXX/has_unique_object_reps_bitint.cpp

Index: clang/test/SemaCXX/has_unique_object_reps_bitint.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/has_unique_object_reps_bitint.cpp
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify -std=c++17 -Wno-bitfield-width %s
+//  expected-no-diagnostics
+
+static_assert(__has_unique_object_representations(_BitInt(8)));
+static_assert(__has_unique_object_representations(unsigned _BitInt(8)));
+static_assert(__has_unique_object_representations(_BitInt(sizeof(int) * 8u)));
+// sizeof(_BitInt(24)) may be 4 to align it to the next greater integer type, in which case it would have 8 padding bits.
+static_assert(__has_unique_object_representations(_BitInt(24)) == (sizeof(_BitInt(24)) == 3));
+
+static_assert(!__has_unique_object_representations(_BitInt(7)));
+static_assert(!__has_unique_object_representations(unsigned _BitInt(7)));
+static_assert(!__has_unique_object_representations(_BitInt(2)));
+static_assert(!__has_unique_object_representations(unsigned _BitInt(1)));
+
+template 
+constexpr bool check() {
+  if constexpr (N <= __BITINT_MAXWIDTH__) {
+static_assert(__has_unique_object_representations(_BitInt(N)) == (sizeof(_BitInt(N)) * 8u == N));
+static_assert(__has_unique_object_representations(unsigned _BitInt(N)) == (sizeof(unsigned _BitInt(N)) * 8u == N));
+  }
+  return true;
+}
+
+template 
+constexpr bool do_check = (check() && ...);
+
+static_assert(do_check<2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18>);
+static_assert(do_check<15, 16, 17, 23, 24, 25, 31, 32, 33>);
+static_assert(do_check<39, 40, 41, 47, 48, 49>);
+static_assert(do_check<127, 128, 129, 255, 256, 257, 383, 384, 385>);
+
+template 
+struct in_struct {
+  _BitInt(N) x;
+  static constexpr bool check() {
+return __has_unique_object_representations(in_struct) == __has_unique_object_representations(_BitInt(N));
+  }
+};
+
+static_assert(in_struct<8>::check());
+static_assert(in_struct<7>::check());
+
+struct bit_fields_1 {
+  _BitInt(7) x : 7;
+  unsigned _BitInt(1) y : 1;
+};
+
+static_assert(__has_unique_object_representations(bit_fields_1) == (sizeof(bit_fields_1) == 1));
+
+struct bit_fields_2 {
+  _BitInt(8) x : 7;
+};
+
+static_assert(!__has_unique_object_representations(bit_fields_2));
+
+struct bit_fields_3 {
+  _BitInt(15) x : 8;
+};
+
+static_assert(__has_unique_object_representations(bit_fields_3) == (sizeof(bit_fields_3) == 1));
+
+#if __BITINT_MAXWIDTH__ >= 129
+struct bit_fields_4 {
+  _BitInt(129) x : 128;
+};
+
+static_assert(__has_unique_object_representations(bit_fields_4) == (sizeof(bit_fields_4) == 128 / 8));
+#endif
+
+struct bit_fields_5 {
+  _BitInt(2) x : 8;
+};
+
+static_assert(!__has_unique_object_representations(bit_fields_5));
+
+template 
+struct ref_member {
+  _BitInt(N) & x;
+};
+
+struct int_ref_member {
+  int &x;
+};
+
+static_assert(__has_unique_object_representations(ref_member<7>) == __has_unique_object_representations(ref_member<8>));
+static_assert(__has_unique_object_representations(ref_member<8>) == __has_unique_object_representations(int_ref_member));
Index: clang/lib/AST/ASTContext.cpp
===
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -2684,7 +2684,11 @@
 if (!RD->isUnion())
   return structHasUniqueObjectRepresentations(Context, RD);
   }
-  if (!Field->getType()->isReferenceType() &&
+
+  // A _BitInt type may not be unique if it has padding bits
+  // but if it is a bitfield the padding bits are not used.
+  bool IsBitIntType = Field->getType()->isBitIntType();
+  if (!Field->getType()->isReferenceType() && !IsBitIntType &&
   !Context.hasUniqueObjectRepresentations(Field->getType()))
 return llvm::None;
 
@@ -2692,9 +2696,17 @@
   Context.toBits(Context.getTypeSizeInChars(Field->getType()));
   if (Field->isBitField()) {
 int64_t BitfieldSize = Field->getBitWidthValue(Context);
-if (BitfieldSize > FieldSizeInBits)
+if (IsBitIntType) {
+  if ((unsigned)BitfieldSize >
+  cast(Field->getType())->getNumBits())
+return llvm::None;
+} else if (BitfieldSize > FieldSizeInBits) {
   return llvm::None;
+}
 FieldSizeInBits = BitfieldSize;
+  } else if (IsBitIntType &&
+ !Context.hasUniqueObjectRepresentations(Field->getType())) {
+return llvm::None;
   }
   return FieldSizeInBits;
 }
@@ -2792,8 +2804,13 @@
 return false;
 
   // All integrals and enums are unique.
-  if (Ty->isIntegralOrEnumerationType())
+  if (Ty->isIntegralOrEnumera

[PATCH] D125802: Fix std::has_unique_object_representations for _BitInt types with padding bits

2022-05-27 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok updated this revision to Diff 432699.
MitalAshok added a comment.

Rebase release notes


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D125802

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/AST/ASTContext.cpp
  clang/test/SemaCXX/has_unique_object_reps_bitint.cpp

Index: clang/test/SemaCXX/has_unique_object_reps_bitint.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/has_unique_object_reps_bitint.cpp
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify -std=c++17 -Wno-bitfield-width %s
+//  expected-no-diagnostics
+
+static_assert(__has_unique_object_representations(_BitInt(8)));
+static_assert(__has_unique_object_representations(unsigned _BitInt(8)));
+static_assert(__has_unique_object_representations(_BitInt(sizeof(int) * 8u)));
+// sizeof(_BitInt(24)) may be 4 to align it to the next greater integer type, in which case it would have 8 padding bits.
+static_assert(__has_unique_object_representations(_BitInt(24)) == (sizeof(_BitInt(24)) == 3));
+
+static_assert(!__has_unique_object_representations(_BitInt(7)));
+static_assert(!__has_unique_object_representations(unsigned _BitInt(7)));
+static_assert(!__has_unique_object_representations(_BitInt(2)));
+static_assert(!__has_unique_object_representations(unsigned _BitInt(1)));
+
+template 
+constexpr bool check() {
+  if constexpr (N <= __BITINT_MAXWIDTH__) {
+static_assert(__has_unique_object_representations(_BitInt(N)) == (sizeof(_BitInt(N)) * 8u == N));
+static_assert(__has_unique_object_representations(unsigned _BitInt(N)) == (sizeof(unsigned _BitInt(N)) * 8u == N));
+  }
+  return true;
+}
+
+template 
+constexpr bool do_check = (check() && ...);
+
+static_assert(do_check<2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18>);
+static_assert(do_check<15, 16, 17, 23, 24, 25, 31, 32, 33>);
+static_assert(do_check<39, 40, 41, 47, 48, 49>);
+static_assert(do_check<127, 128, 129, 255, 256, 257, 383, 384, 385>);
+
+template 
+struct in_struct {
+  _BitInt(N) x;
+  static constexpr bool check() {
+return __has_unique_object_representations(in_struct) == __has_unique_object_representations(_BitInt(N));
+  }
+};
+
+static_assert(in_struct<8>::check());
+static_assert(in_struct<7>::check());
+
+struct bit_fields_1 {
+  _BitInt(7) x : 7;
+  unsigned _BitInt(1) y : 1;
+};
+
+static_assert(__has_unique_object_representations(bit_fields_1) == (sizeof(bit_fields_1) == 1));
+
+struct bit_fields_2 {
+  _BitInt(8) x : 7;
+};
+
+static_assert(!__has_unique_object_representations(bit_fields_2));
+
+struct bit_fields_3 {
+  _BitInt(15) x : 8;
+};
+
+static_assert(__has_unique_object_representations(bit_fields_3) == (sizeof(bit_fields_3) == 1));
+
+#if __BITINT_MAXWIDTH__ >= 129
+struct bit_fields_4 {
+  _BitInt(129) x : 128;
+};
+
+static_assert(__has_unique_object_representations(bit_fields_4) == (sizeof(bit_fields_4) == 128 / 8));
+#endif
+
+struct bit_fields_5 {
+  _BitInt(2) x : 8;
+};
+
+static_assert(!__has_unique_object_representations(bit_fields_5));
+
+template 
+struct ref_member {
+  _BitInt(N) & x;
+};
+
+struct int_ref_member {
+  int &x;
+};
+
+static_assert(__has_unique_object_representations(ref_member<7>) == __has_unique_object_representations(ref_member<8>));
+static_assert(__has_unique_object_representations(ref_member<8>) == __has_unique_object_representations(int_ref_member));
Index: clang/lib/AST/ASTContext.cpp
===
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -2684,7 +2684,11 @@
 if (!RD->isUnion())
   return structHasUniqueObjectRepresentations(Context, RD);
   }
-  if (!Field->getType()->isReferenceType() &&
+
+  // A _BitInt type may not be unique if it has padding bits
+  // but if it is a bitfield the padding bits are not used.
+  bool IsBitIntType = Field->getType()->isBitIntType();
+  if (!Field->getType()->isReferenceType() && !IsBitIntType &&
   !Context.hasUniqueObjectRepresentations(Field->getType()))
 return llvm::None;
 
@@ -2692,9 +2696,17 @@
   Context.toBits(Context.getTypeSizeInChars(Field->getType()));
   if (Field->isBitField()) {
 int64_t BitfieldSize = Field->getBitWidthValue(Context);
-if (BitfieldSize > FieldSizeInBits)
+if (IsBitIntType) {
+  if ((unsigned)BitfieldSize >
+  cast(Field->getType())->getNumBits())
+return llvm::None;
+} else if (BitfieldSize > FieldSizeInBits) {
   return llvm::None;
+}
 FieldSizeInBits = BitfieldSize;
+  } else if (IsBitIntType &&
+ !Context.hasUniqueObjectRepresentations(Field->getType())) {
+return llvm::None;
   }
   return FieldSizeInBits;
 }
@@ -2792,8 +2804,13 @@
 return false;
 
   // All integrals and enums are unique.
-  if (Ty->isIntegralOrEnumerationType())
+  if (Ty->isIntegralOrEnumerationType()) {
+  

[PATCH] D125802: Fix std::has_unique_object_representations for _BitInt types with padding bits

2022-05-28 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok added a comment.

@aaron.ballman yes, with the author "Mital Ashok 
". (replacing the [AT]) Thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D125802

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


[PATCH] D126937: Fix memleak in VarTemplateSpecializationDecl

2022-06-02 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok created this revision.
Herald added a project: All.
MitalAshok added reviewers: akyrtzi, aaron.ballman, erichkeane, browneee.
MitalAshok published this revision for review.
MitalAshok added a project: LLVM.
MitalAshok added a comment.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

VarTemplateSpecializationDecl held a TemplateArgumentListInfo which holds a 
SmallVector, so in this test case 
https://github.com/llvm/llvm-project/blob/ee1cf1f64519c815025d962bdf9c9bb3d09d7699/clang/test/SemaCXX/has_unique_object_reps_bitint.cpp#L27
 where there was a variable template with more than 8 template arguments, it 
leaked


Replace TemplateArgumentListInfo with ASTTemplateArgumentListInfo
and convert between them in some places


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D126937

Files:
  clang/include/clang/AST/DeclTemplate.h
  clang/include/clang/Sema/Template.h
  clang/lib/AST/DeclTemplate.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3801,7 +3801,7 @@
 return nullptr;
 
   // Substitute the current template arguments.
-  const TemplateArgumentListInfo &TemplateArgsInfo = D->getTemplateArgsInfo();
+  const ASTTemplateArgumentListInfo &TemplateArgsInfo = D->getTemplateArgsInfo();
   VarTemplateArgsInfo.setLAngleLoc(TemplateArgsInfo.getLAngleLoc());
   VarTemplateArgsInfo.setRAngleLoc(TemplateArgsInfo.getRAngleLoc());
 
@@ -3831,12 +3831,13 @@
 return nullptr;
 
   return VisitVarTemplateSpecializationDecl(
-  InstVarTemplate, D, VarTemplateArgsInfo, Converted, PrevDecl);
+  InstVarTemplate, D,
+  *ASTTemplateArgumentListInfo::Create(D->getASTContext(), VarTemplateArgsInfo), Converted, PrevDecl);
 }
 
 Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
 VarTemplateDecl *VarTemplate, VarDecl *D,
-const TemplateArgumentListInfo &TemplateArgsInfo,
+const ASTTemplateArgumentListInfo &TemplateArgsInfo,
 ArrayRef Converted,
 VarTemplateSpecializationDecl *PrevDecl) {
 
@@ -5133,7 +5134,9 @@
 
   return cast_or_null(
   Instantiator.VisitVarTemplateSpecializationDecl(
-  VarTemplate, FromVar, TemplateArgsInfo, Converted));
+  VarTemplate, FromVar,
+  *ASTTemplateArgumentListInfo::Create(getASTContext(), TemplateArgsInfo),
+  Converted));
 }
 
 /// Instantiates a variable template specialization by completing it
Index: clang/lib/AST/DeclTemplate.cpp
===
--- clang/lib/AST/DeclTemplate.cpp
+++ clang/lib/AST/DeclTemplate.cpp
@@ -1335,10 +1335,12 @@
 
 void VarTemplateSpecializationDecl::setTemplateArgsInfo(
 const TemplateArgumentListInfo &ArgsInfo) {
-  TemplateArgsInfo.setLAngleLoc(ArgsInfo.getLAngleLoc());
-  TemplateArgsInfo.setRAngleLoc(ArgsInfo.getRAngleLoc());
-  for (const TemplateArgumentLoc &Loc : ArgsInfo.arguments())
-TemplateArgsInfo.addArgument(Loc);
+  TemplateArgsInfo = ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo);
+}
+
+void VarTemplateSpecializationDecl::setTemplateArgsInfo(
+const ASTTemplateArgumentListInfo &ArgsInfo) {
+  TemplateArgsInfo = &ArgsInfo;
 }
 
 //===--===//
Index: clang/include/clang/Sema/Template.h
===
--- clang/include/clang/Sema/Template.h
+++ clang/include/clang/Sema/Template.h
@@ -603,7 +603,7 @@
 
 Decl *VisitVarTemplateSpecializationDecl(
 VarTemplateDecl *VarTemplate, VarDecl *FromVar,
-const TemplateArgumentListInfo &TemplateArgsInfo,
+const ASTTemplateArgumentListInfo &TemplateArgsInfo,
 ArrayRef Converted,
 VarTemplateSpecializationDecl *PrevDecl = nullptr);
 
Index: clang/include/clang/AST/DeclTemplate.h
===
--- clang/include/clang/AST/DeclTemplate.h
+++ clang/include/clang/AST/DeclTemplate.h
@@ -2718,7 +2718,7 @@
 
   /// The template arguments used to describe this specialization.
   const TemplateArgumentList *TemplateArgs;
-  TemplateArgumentListInfo TemplateArgsInfo;
+  const ASTTemplateArgumentListInfo *TemplateArgsInfo;
 
   /// The point where this template was instantiated (if any).
   SourceLocation PointOfInstantiation;
@@ -2773,9 +2773,12 @@
 
   // TODO: Always set this when creating the new specialization?
   void setTemplateArgsInfo(const TemplateArgumentListInfo &ArgsInfo);
+  void setTemplateArgsInfo(const ASTTemplateArgumentListInfo &ArgsInfo);
 
-  const TemplateArgumentListInfo &getTemplateArgsInfo() const {
-return TemplateArgsInfo;
+  const ASTTemplateArgumentListInfo &getTemplateArgsInfo() const {
+assert(TemplateArgsInfo &&
+   "Called

[PATCH] D126937: Fix memleak in VarTemplateSpecializationDecl

2022-06-02 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok added inline comments.



Comment at: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp:5561
 Var = 
cast_or_null(Instantiator.VisitVarTemplateSpecializationDecl(
 VarSpec->getSpecializedTemplate(), Def, VarSpec->getTemplateArgsInfo(),
 VarSpec->getTemplateArgs().asArray(), VarSpec));

The type of VarSpec->getTemplateArgsInfo() changed to 
ASTTemplateArgumentListInfo which is why the type of 
VisitVarTemplateSpecializationDecl needed to change


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D126937

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


[PATCH] D126937: Fix memleak in VarTemplateSpecializationDecl

2022-06-02 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok planned changes to this revision.
MitalAshok added a comment.

Appears that more things need to be changed, I'll get that done soon


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D126937

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


[PATCH] D154716: [SemaCXX] Fix bug where unexpanded lambda captures where assumed to be expanded

2023-07-22 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok updated this revision to Diff 543183.
MitalAshok edited the summary of this revision.
MitalAshok added a comment.

Added entry to changelog and the test from the bug report


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154716

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/TreeTransform.h
  clang/test/SemaCXX/lambda-pack-expansion.cpp


Index: clang/test/SemaCXX/lambda-pack-expansion.cpp
===
--- clang/test/SemaCXX/lambda-pack-expansion.cpp
+++ clang/test/SemaCXX/lambda-pack-expansion.cpp
@@ -21,3 +21,30 @@
   take_by_ref(x);
 }
 }
+
+namespace GH63677 {
+
+template
+void f() {
+  []() -> void {
+[...us = Ts{}]{
+  (Ts(us), ...);
+};
+  }.template operator()();
+}
+
+template void f();
+
+template 
+inline constexpr auto fun =
+  [](Ts... ts) {
+return [... us = (Ts&&) ts](Fun&& fn) mutable {
+  return static_cast(fn)(static_cast(us)...);
+};
+  };
+
+void f() {
+  [[maybe_unused]] auto s = fun(1, 2, 3, 4);
+}
+
+}
Index: clang/lib/Sema/TreeTransform.h
===
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -13340,14 +13340,14 @@
   OldVD->getInit()->getSourceRange(), Unexpanded, Expand,
   RetainExpansion, NumExpansions))
 return ExprError();
+  assert(!RetainExpansion && "Should not need to retain expansion after a "
+ "capture since it cannot be extended");
   if (Expand) {
 for (unsigned I = 0; I != *NumExpansions; ++I) {
   Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
   SubstInitCapture(SourceLocation(), std::nullopt);
 }
-  }
-  if (!Expand || RetainExpansion) {
-ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+  } else {
 SubstInitCapture(ExpansionTL.getEllipsisLoc(), NumExpansions);
 Result.EllipsisLoc = ExpansionTL.getEllipsisLoc();
   }
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1270,7 +1270,8 @@
 }
 
 void transformedLocalDecl(Decl *Old, ArrayRef NewDecls) {
-  if (Old->isParameterPack()) {
+  if (Old->isParameterPack() &&
+  (NewDecls.size() != 1 || !NewDecls.front()->isParameterPack())) {
 SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Old);
 for (auto *New : NewDecls)
   SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -782,6 +782,8 @@
   (`#63903 `_)
 - Fix constraint checking of non-generic lambdas.
   (`#63181 `_)
+- Fix init-capture packs having a size of one before being instantiated
+  (`#63677 `_)
 
 Bug Fixes to AST Handling
 ^


Index: clang/test/SemaCXX/lambda-pack-expansion.cpp
===
--- clang/test/SemaCXX/lambda-pack-expansion.cpp
+++ clang/test/SemaCXX/lambda-pack-expansion.cpp
@@ -21,3 +21,30 @@
   take_by_ref(x);
 }
 }
+
+namespace GH63677 {
+
+template
+void f() {
+  []() -> void {
+[...us = Ts{}]{
+  (Ts(us), ...);
+};
+  }.template operator()();
+}
+
+template void f();
+
+template 
+inline constexpr auto fun =
+  [](Ts... ts) {
+return [... us = (Ts&&) ts](Fun&& fn) mutable {
+  return static_cast(fn)(static_cast(us)...);
+};
+  };
+
+void f() {
+  [[maybe_unused]] auto s = fun(1, 2, 3, 4);
+}
+
+}
Index: clang/lib/Sema/TreeTransform.h
===
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -13340,14 +13340,14 @@
   OldVD->getInit()->getSourceRange(), Unexpanded, Expand,
   RetainExpansion, NumExpansions))
 return ExprError();
+  assert(!RetainExpansion && "Should not need to retain expansion after a "
+ "capture since it cannot be extended");
   if (Expand) {
 for (unsigned I = 0; I != *NumExpansions; ++I) {
   Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
   SubstInitCapture(SourceLocation(), std::nullopt);
 }
-  }
-  if (!Expand || RetainExpansion) {
-ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+  } else {
 SubstInitCapture(ExpansionTL.getEllipsisLoc(), NumExpansions)

[PATCH] D154716: [SemaCXX] Fix bug where unexpanded lambda captures where assumed to be expanded

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



Comment at: clang/lib/Sema/TreeTransform.h:13323
 
 // If this is an init-capture pack, consider expanding the pack now.
 if (OldVD->isParameterPack()) {

shafik wrote:
> Based on the changes is this comment still accurate?
Yes, the code was just changed so it's more clear that the result either has 
`N` distinct arguments for a pack of size `N` or just 1 argument with a 
(possible dependent) pack type


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154716

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


[PATCH] D156032: Implement CWG2137 (list-initialization from objects of the same type)

2023-07-22 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok created this revision.
Herald added a project: All.
MitalAshok updated this revision to Diff 543217.
MitalAshok added a comment.
MitalAshok edited the summary of this revision.
MitalAshok added a reviewer: rsmith.
MitalAshok published this revision for review.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

clang-format




Comment at: clang/lib/Sema/SemaInit.cpp:4249-4250
   InitializedEntity::EK_LambdaToBlockConversionBlockElement &&
-  UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isPRValue() &&
-  S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) 
{
+  Args.size() == 1 && Args[0]->isPRValue() &&
+  S.Context.hasSameUnqualifiedType(Args[0]->getType(), DestType)) {
 // Convert qualifications if necessary.

This change unfortunately exposes the still-open [[ https://wg21.link/CWG2311 | 
CWG2311 ]] but allows `T{ object_of_type_T }` to consider user declared 
constructors.

I am working on a separate fix for CWG2311 (Consider constructors as below, but 
then if the chosen constructor is not an initializer-list constructor, elide 
it).




Comment at: clang/lib/Sema/SemaOverload.cpp:1470-1480
+  // C++ [over.ics.list]p6, per DR2137:
+  //   If C is not an initializer-list constructor and the initializer list
+  //   has a single element of type cv U, where U is X or a class derived
+  //   from X, the implicit conversion sequence has Exact Match rank if U 
is
+  //   X, or Conversion rank if U is derived from X.
+  if (const auto *InitList = dyn_cast(From);
+  InitList && InitList->getNumInits() == 1 &&

This allows with `struct T { T(const T&); } t; void f(T);` for `f({ t })` is an 
exact match standard conversion instead of a user-defined conversion


CWG2137  summary: A non-aggregate class being 
initialized with an initializer list with a single element (previously changed 
by CWG1467 ) should prefer initializer-list 
constructors over copy constructors, like everywhere else.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D156032

Files:
  clang/lib/Sema/SemaInit.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/CXX/drs/dr14xx.cpp
  clang/test/CXX/drs/dr21xx.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
@@ -12629,7 +12629,7 @@
 https://cplusplus.github.io/CWG/issues/2137.html";>2137
 CD4
 List-initialization from object of same type
-Unknown
+Clang 17
   
   
 https://cplusplus.github.io/CWG/issues/2138.html";>2138
Index: clang/test/CXX/drs/dr21xx.cpp
===
--- clang/test/CXX/drs/dr21xx.cpp
+++ clang/test/CXX/drs/dr21xx.cpp
@@ -10,6 +10,16 @@
 #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
 #endif
 
+namespace std {
+  __extension__ typedef __SIZE_TYPE__ size_t;
+
+  template struct initializer_list {
+const E *p; size_t n;
+initializer_list(const E *p, size_t n);
+initializer_list();
+  };
+}
+
 namespace dr2100 { // dr2100: 12
   template struct X {};
   template struct A {
@@ -110,6 +120,36 @@
 #endif
 }
 
+namespace dr2137 { // dr2137: 17
+#if __cplusplus >= 201103L
+  struct Q {
+Q();
+Q(Q&&);
+Q(std::initializer_list) = delete; // expected-note 2 {{has been explicitly marked deleted here}}
+  };
+
+  Q x = Q { Q() }; // expected-error {{call to deleted constructor}}
+
+  int f(Q); // expected-note {{passing argument to parameter here}}
+  int y = f({ Q() }); // expected-error {{call to deleted constructor}}
+
+  struct U {
+U();
+U(const U&);
+  };
+
+  struct Derived : U {
+Derived();
+Derived(const Derived&);
+  } d;
+
+  int g(Derived);
+  int g(U(&&)[1]) = delete;
+
+  int z = g({ d });
+#endif
+}
+
 namespace dr2140 { // dr2140: 9
 #if __cplusplus >= 201103L
   union U { int a; decltype(nullptr) b; };
Index: clang/test/CXX/drs/dr14xx.cpp
===
--- clang/test/CXX/drs/dr14xx.cpp
+++ clang/test/CXX/drs/dr14xx.cpp
@@ -423,6 +423,8 @@
 }
   } // nonaggregate
 
+#if 0  // Pending CWG2311
+
   namespace SelfInitIsNotListInit {
 struct S {
   S();
@@ -433,6 +435,8 @@
 S s2 = {s1}; // ok, not list-initialization so we pick the non-explicit constructor
   }
 
+#endif
+
   struct NestedInit { int a, b, c; };
   NestedInit ni[1] = {{NestedInit{1, 2, 3}}};
 
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -1465,19 +1465,36 @@
 //   called for those cases.
 if (CXXConstructorDecl *Constructor
   = dyn_cast(ICS.UserDefined.Conver

[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 = &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
 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
+++ cla

[PATCH] D156032: Implement CWG2137 (list-initialization from objects of the same type)

2023-07-23 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok updated this revision to Diff 543301.
MitalAshok edited the summary of this revision.
MitalAshok added a comment.

Removing "SelfInitIsNotListInit" test case: copy-list-init for non-aggregate 
classes remains as copy-list-inits, only aggregates copies are converted into 
copy-inits (which I don't think is observable)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156032

Files:
  clang/lib/Sema/SemaInit.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/CXX/drs/dr14xx.cpp
  clang/test/CXX/drs/dr21xx.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
@@ -12629,7 +12629,7 @@
 https://cplusplus.github.io/CWG/issues/2137.html";>2137
 CD4
 List-initialization from object of same type
-Unknown
+Clang 17
   
   
 https://cplusplus.github.io/CWG/issues/2138.html";>2138
Index: clang/test/CXX/drs/dr21xx.cpp
===
--- clang/test/CXX/drs/dr21xx.cpp
+++ clang/test/CXX/drs/dr21xx.cpp
@@ -10,6 +10,16 @@
 #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
 #endif
 
+namespace std {
+  __extension__ typedef __SIZE_TYPE__ size_t;
+
+  template struct initializer_list {
+const E *p; size_t n;
+initializer_list(const E *p, size_t n);
+initializer_list();
+  };
+}
+
 namespace dr2100 { // dr2100: 12
   template struct X {};
   template struct A {
@@ -110,6 +120,36 @@
 #endif
 }
 
+namespace dr2137 { // dr2137: 17
+#if __cplusplus >= 201103L
+  struct Q {
+Q();
+Q(Q&&);
+Q(std::initializer_list) = delete; // expected-note 2 {{has been explicitly marked deleted here}}
+  };
+
+  Q x = Q { Q() }; // expected-error {{call to deleted constructor}}
+
+  int f(Q); // expected-note {{passing argument to parameter here}}
+  int y = f({ Q() }); // expected-error {{call to deleted constructor}}
+
+  struct U {
+U();
+U(const U&);
+  };
+
+  struct Derived : U {
+Derived();
+Derived(const Derived&);
+  } d;
+
+  int g(Derived);
+  int g(U(&&)[1]) = delete;
+
+  int z = g({ d });
+#endif
+}
+
 namespace dr2140 { // dr2140: 9
 #if __cplusplus >= 201103L
   union U { int a; decltype(nullptr) b; };
Index: clang/test/CXX/drs/dr14xx.cpp
===
--- clang/test/CXX/drs/dr14xx.cpp
+++ clang/test/CXX/drs/dr14xx.cpp
@@ -423,16 +423,6 @@
 }
   } // nonaggregate
 
-  namespace SelfInitIsNotListInit {
-struct S {
-  S();
-  explicit S(S &);
-  S(const S &);
-};
-S s1;
-S s2 = {s1}; // ok, not list-initialization so we pick the non-explicit constructor
-  }
-
   struct NestedInit { int a, b, c; };
   NestedInit ni[1] = {{NestedInit{1, 2, 3}}};
 
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -1465,19 +1465,36 @@
 //   called for those cases.
 if (CXXConstructorDecl *Constructor
   = dyn_cast(ICS.UserDefined.ConversionFunction)) {
-  QualType FromCanon
-= S.Context.getCanonicalType(From->getType().getUnqualifiedType());
+  QualType FromType;
+  SourceLocation FromLoc;
+  // C++ [over.ics.list]p6, per DR2137:
+  //   If C is not an initializer-list constructor and the initializer list
+  //   has a single element of type cv U, where U is X or a class derived
+  //   from X, the implicit conversion sequence has Exact Match rank if U is
+  //   X, or Conversion rank if U is derived from X.
+  if (const auto *InitList = dyn_cast(From);
+  InitList && InitList->getNumInits() == 1 &&
+  !S.isInitListConstructor(Constructor)) {
+const Expr *SingleInit = InitList->getInit(0);
+FromType = SingleInit->getType();
+FromLoc = SingleInit->getBeginLoc();
+  } else {
+FromType = From->getType();
+FromLoc = From->getBeginLoc();
+  }
+  QualType FromCanon =
+  S.Context.getCanonicalType(FromType.getUnqualifiedType());
   QualType ToCanon
 = S.Context.getCanonicalType(ToType).getUnqualifiedType();
   if (Constructor->isCopyConstructor() &&
   (FromCanon == ToCanon ||
-   S.IsDerivedFrom(From->getBeginLoc(), FromCanon, ToCanon))) {
+   S.IsDerivedFrom(FromLoc, FromCanon, ToCanon))) {
 // Turn this into a "standard" conversion sequence, so that it
 // gets ranked with standard conversion sequences.
 DeclAccessPair Found = ICS.UserDefined.FoundConversionFunction;
 ICS.setStandard();
 ICS.Standard.setAsIdentityConversion();
-ICS.Standard.setFromType(From->getType());
+ICS.Standard.setFromType(FromType);
 ICS.Standard.setAllToType

[PATCH] D156032: Implement CWG2137 (list-initialization from objects of the same type)

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



Comment at: clang/test/CXX/drs/dr14xx.cpp:433
-S s1;
-S s2 = {s1}; // ok, not list-initialization so we pick the non-explicit 
constructor
-  }

This relies on the old wording. "If T is a class type and the initializer list 
has a single element of type cv U, where U is T or a class derived from T, the 
object is initialized from that element (by copy-initialization for 
copy-list-initialization, or by direct-initialization for 
direct-list-initialization)".

"If T is a class type" -> "If T is an aggregate class type", so this 
copy-list-initialization remains copy-list-initialization (and should fail for 
picking the explicit constructor)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156032

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


[PATCH] D156032: Implement CWG2137 (list-initialization from objects of the same type)

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



Comment at: clang/lib/Sema/SemaInit.cpp:4249-4250
   InitializedEntity::EK_LambdaToBlockConversionBlockElement &&
-  UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isPRValue() &&
-  S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) 
{
+  Args.size() == 1 && Args[0]->isPRValue() &&
+  S.Context.hasSameUnqualifiedType(Args[0]->getType(), DestType)) {
 // Convert qualifications if necessary.

MitalAshok wrote:
> This change unfortunately exposes the still-open [[ https://wg21.link/CWG2311 
> | CWG2311 ]] but allows `T{ object_of_type_T }` to consider user declared 
> constructors.
> 
> I am working on a separate fix for CWG2311 (Consider constructors as below, 
> but then if the chosen constructor is not an initializer-list constructor, 
> elide it).
> 
Fix will be here: https://reviews.llvm.org/D156062

`auto{ prvalue }` will elide a copy for aggregate types again. It will do so 
after checking constructors for non-aggregate classes now.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156032

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


[PATCH] D156064: [SemaCXX] Recognise initializer_list injected-class-name types as initializer_lists

2023-07-23 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok created this revision.
Herald added a project: All.
MitalAshok added reviewers: EricWF, CornedBee, erichkeane.
MitalAshok published this revision for review.
MitalAshok added a comment.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

The implicitly-generated guide for `template struct 
initializer_list;`'s copy constructor's first argument is an 
injected-class-name. When it was not recognised as an initializer_list, it was 
erroneously excluded when the initializer was a braced-init-list.

Also falls foul of `-Wctad-maybe-unsupported`. Looks like this is being worked 
on in https://reviews.llvm.org/D133425 but should `std::initializer_list{ a, b, 
c }` be a built-in exception to this diagnostic? If not, I would recommend 
using `_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(initializer_list)` in libc++ from 
https://reviews.llvm.org/D133535. For comparison, GCC does not warn with 
`-Wctad-maybe-unsupported`.


This allows the implicitly-generated deduction guide for the copy constructor 
to be recognised as an initializer-list constructor, allowing CTAD for 
std::iinitializer_list


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D156064

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp


Index: clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
===
--- clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -12,8 +12,6 @@
 size_t n;
 initializer_list();
   };
-  // FIXME: This should probably not be necessary.
-  template initializer_list(initializer_list) -> 
initializer_list;
 }
 
 template constexpr bool has_type(...) { return false; }
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -11703,11 +11703,17 @@
 
 Template = Specialization->getSpecializedTemplate();
 Arguments = Specialization->getTemplateArgs().data();
-  } else if (const TemplateSpecializationType *TST =
- Ty->getAs()) {
-Template = dyn_cast_or_null(
-TST->getTemplateName().getAsTemplateDecl());
-Arguments = TST->template_arguments().begin();
+  } else {
+const TemplateSpecializationType *TST = nullptr;
+if (auto *ICN = Ty->getAs())
+  TST = ICN->getInjectedTST();
+else
+  TST = Ty->getAs();
+if (TST) {
+  Template = dyn_cast_or_null(
+  TST->getTemplateName().getAsTemplateDecl());
+  Arguments = TST->template_arguments().begin();
+}
   }
   if (!Template)
 return false;
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -789,6 +789,9 @@
   (`#63903 `_)
 - Fix constraint checking of non-generic lambdas.
   (`#63181 `_)
+- Fix CTAD for ``std::initializer_list``. This allows
+  ``std::initializer_list{1, 2, 3}`` to be a ``std::initializer_list``
+  as intended.
 
 Bug Fixes to AST Handling
 ^


Index: clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
===
--- clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -12,8 +12,6 @@
 size_t n;
 initializer_list();
   };
-  // FIXME: This should probably not be necessary.
-  template initializer_list(initializer_list) -> initializer_list;
 }
 
 template constexpr bool has_type(...) { return false; }
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -11703,11 +11703,17 @@
 
 Template = Specialization->getSpecializedTemplate();
 Arguments = Specialization->getTemplateArgs().data();
-  } else if (const TemplateSpecializationType *TST =
- Ty->getAs()) {
-Template = dyn_cast_or_null(
-TST->getTemplateName().getAsTemplateDecl());
-Arguments = TST->template_arguments().begin();
+  } else {
+const TemplateSpecializationType *TST = nullptr;
+if (auto *ICN = Ty->getAs())
+  TST = ICN->getInjectedTST();
+else
+  TST = Ty->getAs();
+if (TST) {
+  Template = dyn_cast_or_null(
+  TST->getTemplateName().getAsTemplateDecl());
+  Arguments = TST->template_arguments().begin();
+}
   }
   if (!Template)
 return false;
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -789,6 +789,9 @@
   (`#63

[PATCH] D155776: [NFC] Add checks for self-assignment.

2023-07-24 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok added a comment.

This doesn't compile, could you fix this or revert 
8ac137acefc01caf636db5f95eb0977c97def1ba 
 ?




Comment at: clang/lib/AST/APValue.cpp:393
 APValue &APValue::operator=(APValue &&RHS) {
-  if (Kind != None && Kind != Indeterminate)
-DestroyDataAndMakeUninit();
-  Kind = RHS.Kind;
-  Data = RHS.Data;
-  RHS.Kind = None;
+  if (this != RHS) {
+if (Kind != None && Kind != Indeterminate)

Ditto for the other changes


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155776

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


[PATCH] D156063: [Clang] Reject programs declaring namespace std to be inline

2023-07-24 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok requested changes to this revision.
MitalAshok added a comment.
This revision now requires changes to proceed.

This does currently break `namespace foo { inline namespace std {} }`, 
`namespace foo::inline std {}`, etc.




Comment at: clang/lib/Sema/SemaDeclCXX.cpp:11369
+// This has to be diagnosed before entering 
DiagnoseNamespaceInlineMismatch.
+if (IsInline && II->isStr("std"))
+  Diag(InlineLoc, diag::err_inline_namespace_std)

You need to check if this is a std namespace declaration at file scope, 
`namespace foo::inline std {}` in a namespace scope should be fine.

The check for this is a few lines below: 
`CurContext->getRedeclContext()->isTranslationUnit()`.



Comment at: clang/lib/Sema/SemaDeclCXX.cpp:11393-11394
   if (IsInline != PrevNS->isInline())
 DiagnoseNamespaceInlineMismatch(*this, NamespaceLoc, Loc, II,
 &IsInline, PrevNS);
 } else if (PrevDecl) {

This ends up giving two errors on the same line if this wasn't the first 
declaration (`error: namespace 'std' cannot be declared inline` followed by 
`error: non-inline namespace cannot be reopened as inline; note: previous 
definition is here`). The wording for the second error is also a little 
confusing (it cannot be opened at all as inline, let alone reopened), so 
consider refactoring so that both diagnostics can't be issued at once


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156063

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


[PATCH] D156063: [Clang] Reject programs declaring namespace std to be inline

2023-07-24 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok accepted this revision.
MitalAshok added a comment.
This revision is now accepted and ready to land.

Looks good!


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

https://reviews.llvm.org/D156063

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


[PATCH] D156064: [SemaCXX] Recognise initializer_list injected-class-name types as initializer_lists

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

Remove now unneeded FIXME


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156064

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaInit.cpp
  clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp


Index: clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
===
--- clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -12,8 +12,6 @@
 size_t n;
 initializer_list();
   };
-  // FIXME: This should probably not be necessary.
-  template initializer_list(initializer_list) -> 
initializer_list;
 }
 
 template constexpr bool has_type(...) { return false; }
Index: clang/lib/Sema/SemaInit.cpp
===
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -10589,8 +10589,6 @@
   // FIXME: Perform "exact type" matching first, per CWG discussion?
   //Or implement this via an implied 'T(T) -> T' deduction guide?
 
-  // FIXME: Do we need/want a std::initializer_list special case?
-
   // Look up deduction guides, including those synthesized from constructors.
   //
   // C++1z [over.match.class.deduct]p1:
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -11703,11 +11703,17 @@
 
 Template = Specialization->getSpecializedTemplate();
 Arguments = Specialization->getTemplateArgs().data();
-  } else if (const TemplateSpecializationType *TST =
- Ty->getAs()) {
-Template = dyn_cast_or_null(
-TST->getTemplateName().getAsTemplateDecl());
-Arguments = TST->template_arguments().begin();
+  } else {
+const TemplateSpecializationType *TST = nullptr;
+if (auto *ICN = Ty->getAs())
+  TST = ICN->getInjectedTST();
+else
+  TST = Ty->getAs();
+if (TST) {
+  Template = dyn_cast_or_null(
+  TST->getTemplateName().getAsTemplateDecl());
+  Arguments = TST->template_arguments().begin();
+}
   }
   if (!Template)
 return false;
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -789,6 +789,9 @@
   (`#63903 `_)
 - Fix constraint checking of non-generic lambdas.
   (`#63181 `_)
+- Fix CTAD for ``std::initializer_list``. This allows
+  ``std::initializer_list{1, 2, 3}`` to be a ``std::initializer_list``
+  as intended.
 
 Bug Fixes to AST Handling
 ^


Index: clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
===
--- clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -12,8 +12,6 @@
 size_t n;
 initializer_list();
   };
-  // FIXME: This should probably not be necessary.
-  template initializer_list(initializer_list) -> initializer_list;
 }
 
 template constexpr bool has_type(...) { return false; }
Index: clang/lib/Sema/SemaInit.cpp
===
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -10589,8 +10589,6 @@
   // FIXME: Perform "exact type" matching first, per CWG discussion?
   //Or implement this via an implied 'T(T) -> T' deduction guide?
 
-  // FIXME: Do we need/want a std::initializer_list special case?
-
   // Look up deduction guides, including those synthesized from constructors.
   //
   // C++1z [over.match.class.deduct]p1:
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -11703,11 +11703,17 @@
 
 Template = Specialization->getSpecializedTemplate();
 Arguments = Specialization->getTemplateArgs().data();
-  } else if (const TemplateSpecializationType *TST =
- Ty->getAs()) {
-Template = dyn_cast_or_null(
-TST->getTemplateName().getAsTemplateDecl());
-Arguments = TST->template_arguments().begin();
+  } else {
+const TemplateSpecializationType *TST = nullptr;
+if (auto *ICN = Ty->getAs())
+  TST = ICN->getInjectedTST();
+else
+  TST = Ty->getAs();
+if (TST) {
+  Template = dyn_cast_or_null(
+  TST->getTemplateName().getAsTemplateDecl());
+  Arguments = TST->template_arguments().begin();
+}
   }
   if (!Template)
 return false;
Index: clang/docs/ReleaseNotes.rst
=

[PATCH] D156032: Implement CWG2137 (list-initialization from objects of the same type)

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

Add CWG2311 fix too

Too much code and tests rely on elision of `T{ T_prvalue }` in C++17, so add 
change to allow that to be elided when this does not pick a initializer-list 
constructor.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156032

Files:
  clang/lib/Sema/SemaInit.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/CXX/drs/dr14xx.cpp
  clang/test/CXX/drs/dr21xx.cpp
  clang/test/CXX/drs/dr23xx.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
@@ -12629,7 +12629,7 @@
 https://cplusplus.github.io/CWG/issues/2137.html";>2137
 CD4
 List-initialization from object of same type
-Unknown
+Clang 17
   
   
 https://cplusplus.github.io/CWG/issues/2138.html";>2138
Index: clang/test/CXX/drs/dr23xx.cpp
===
--- clang/test/CXX/drs/dr23xx.cpp
+++ clang/test/CXX/drs/dr23xx.cpp
@@ -5,6 +5,16 @@
 // RUN: %clang_cc1 -std=c++20 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
 // RUN: %clang_cc1 -std=c++23 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
 
+namespace std {
+  __extension__ typedef __SIZE_TYPE__ size_t;
+
+  template struct initializer_list {
+const E *p; size_t n;
+initializer_list(const E *p, size_t n);
+initializer_list();
+  };
+}
+
 #if __cplusplus >= 201103L
 namespace dr2303 { // dr2303: 12
 template 
@@ -37,6 +47,38 @@
 } //namespace dr2303
 #endif
 
+namespace dr2311 {
+#if __cplusplus >= 201707L
+template
+void test() {
+  // These should all be elided (no move)
+  T a = T{T(0)};
+  T b{T(0)};
+  auto c{T(0)};
+  T d = {T(0)};
+  auto e = {T(0)};
+#if __cplusplus >= 202302L
+  auto f = auto{T(0)};
+#endif
+}
+
+struct NonMovable {
+  NonMovable(int);
+  NonMovable(NonMovable&&) = delete;
+};
+
+template void test();
+
+struct NonMovableNonApplicableIList {
+  NonMovableNonApplicableIList(int);
+  NonMovableNonApplicableIList(NonMovableNonApplicableIList&&) = delete;
+  NonMovableNonApplicableIList(std::initializer_list);
+};
+
+template void test();
+#endif
+}
+
 // dr2331: na
 
 #if __cplusplus >= 201103L
Index: clang/test/CXX/drs/dr21xx.cpp
===
--- clang/test/CXX/drs/dr21xx.cpp
+++ clang/test/CXX/drs/dr21xx.cpp
@@ -10,6 +10,16 @@
 #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
 #endif
 
+namespace std {
+  __extension__ typedef __SIZE_TYPE__ size_t;
+
+  template struct initializer_list {
+const E *p; size_t n;
+initializer_list(const E *p, size_t n);
+initializer_list();
+  };
+}
+
 namespace dr2100 { // dr2100: 12
   template struct X {};
   template struct A {
@@ -110,6 +120,36 @@
 #endif
 }
 
+namespace dr2137 { // dr2137: 17
+#if __cplusplus >= 201103L
+  struct Q {
+Q();
+Q(Q&&);
+Q(std::initializer_list) = delete; // expected-note 2 {{has been explicitly marked deleted here}}
+  };
+
+  Q x = Q { Q() }; // expected-error {{call to deleted constructor}}
+
+  int f(Q); // expected-note {{passing argument to parameter here}}
+  int y = f({ Q() }); // expected-error {{call to deleted constructor}}
+
+  struct U {
+U();
+U(const U&);
+  };
+
+  struct Derived : U {
+Derived();
+Derived(const Derived&);
+  } d;
+
+  int g(Derived);
+  int g(U(&&)[1]) = delete;
+
+  int z = g({ d });
+#endif
+}
+
 namespace dr2140 { // dr2140: 9
 #if __cplusplus >= 201103L
   union U { int a; decltype(nullptr) b; };
Index: clang/test/CXX/drs/dr14xx.cpp
===
--- clang/test/CXX/drs/dr14xx.cpp
+++ clang/test/CXX/drs/dr14xx.cpp
@@ -423,16 +423,6 @@
 }
   } // nonaggregate
 
-  namespace SelfInitIsNotListInit {
-struct S {
-  S();
-  explicit S(S &);
-  S(const S &);
-};
-S s1;
-S s2 = {s1}; // ok, not list-initialization so we pick the non-explicit constructor
-  }
-
   struct NestedInit { int a, b, c; };
   NestedInit ni[1] = {{NestedInit{1, 2, 3}}};
 
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -1465,19 +1465,36 @@
 //   called for those cases.
 if (CXXConstructorDecl *Constructor
   = dyn_cast(ICS.UserDefined.ConversionFunction)) {
-  QualType FromCanon
-= S.Context.getCanonicalType(From->getType().getUnqualifiedType());
+  QualType FromType;
+  SourceLocation FromLoc;
+  // C++ [over.ics.list]p6, per DR2137:
+  //   If C is not an initializer-list constructor and the initializer list
+  //   has a single element of type cv U, where U i

[PATCH] D154951: [clang][Interp] __builtin_bit_cast, Take 2

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



Comment at: clang/lib/AST/Interp/Boolean.h:113
+  static Boolean bitcastFromMemory(const std::byte *Buff) {
+bool Val = static_cast(*Buff);
+return Boolean(Val);

Does this handle padding bits correctly? E.g., `__builtin_bit_cast(bool, 
(unsigned char) 0b10u)` should be false


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154951

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


[PATCH] D156064: [SemaCXX] Recognise initializer_list injected-class-name types as initializer_lists

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

Rebase changelog to clang 18, add more tests


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156064

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaInit.cpp
  clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp


Index: clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
===
--- clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -12,14 +12,19 @@
 size_t n;
 initializer_list();
   };
-  // FIXME: This should probably not be necessary.
-  template initializer_list(initializer_list) -> 
initializer_list;
 }
 
 template constexpr bool has_type(...) { return false; }
 template constexpr bool has_type(T&) { return true; }
 
-std::initializer_list il = {1, 2, 3, 4, 5};
+std::initializer_list il1 = {1, 2, 3, 4, 5};
+auto il2 = std::initializer_list{1, 2, 3, 4};
+auto il3 = std::initializer_list{il1};
+auto il4 = std::initializer_list{il1, il1, il1};
+static_assert(has_type>(il1));
+static_assert(has_type>(il2));
+static_assert(has_type>(il3));
+static_assert(has_type>>(il4));
 
 template struct vector {
   template vector(Iter, Iter);
Index: clang/lib/Sema/SemaInit.cpp
===
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -10589,8 +10589,6 @@
   // FIXME: Perform "exact type" matching first, per CWG discussion?
   //Or implement this via an implied 'T(T) -> T' deduction guide?
 
-  // FIXME: Do we need/want a std::initializer_list special case?
-
   // Look up deduction guides, including those synthesized from constructors.
   //
   // C++1z [over.match.class.deduct]p1:
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -11749,11 +11749,17 @@
 
 Template = Specialization->getSpecializedTemplate();
 Arguments = Specialization->getTemplateArgs().data();
-  } else if (const TemplateSpecializationType *TST =
- Ty->getAs()) {
-Template = dyn_cast_or_null(
-TST->getTemplateName().getAsTemplateDecl());
-Arguments = TST->template_arguments().begin();
+  } else {
+const TemplateSpecializationType *TST = nullptr;
+if (auto *ICN = Ty->getAs())
+  TST = ICN->getInjectedTST();
+else
+  TST = Ty->getAs();
+if (TST) {
+  Template = dyn_cast_or_null(
+  TST->getTemplateName().getAsTemplateDecl());
+  Arguments = TST->template_arguments().begin();
+}
   }
   if (!Template)
 return false;
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -107,6 +107,9 @@
 
 Bug Fixes to C++ Support
 
+- Fix CTAD for ``std::initializer_list``. This allows
+  ``std::initializer_list{1, 2, 3}`` to be a ``std::initializer_list``
+  as intended.
 
 Bug Fixes to AST Handling
 ^


Index: clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
===
--- clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -12,14 +12,19 @@
 size_t n;
 initializer_list();
   };
-  // FIXME: This should probably not be necessary.
-  template initializer_list(initializer_list) -> initializer_list;
 }
 
 template constexpr bool has_type(...) { return false; }
 template constexpr bool has_type(T&) { return true; }
 
-std::initializer_list il = {1, 2, 3, 4, 5};
+std::initializer_list il1 = {1, 2, 3, 4, 5};
+auto il2 = std::initializer_list{1, 2, 3, 4};
+auto il3 = std::initializer_list{il1};
+auto il4 = std::initializer_list{il1, il1, il1};
+static_assert(has_type>(il1));
+static_assert(has_type>(il2));
+static_assert(has_type>(il3));
+static_assert(has_type>>(il4));
 
 template struct vector {
   template vector(Iter, Iter);
Index: clang/lib/Sema/SemaInit.cpp
===
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -10589,8 +10589,6 @@
   // FIXME: Perform "exact type" matching first, per CWG discussion?
   //Or implement this via an implied 'T(T) -> T' deduction guide?
 
-  // FIXME: Do we need/want a std::initializer_list special case?
-
   // Look up deduction guides, including those synthesized from constructors.
   //
   // C++1z [over.match.class.deduct]p1:
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cp

[PATCH] D154838: [analyzer] Add check for null pointer passed to %p of printf family

2023-07-25 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok added a comment.

Instead of checking for hard-coded names, you can check functions with the 
format(printf, x, y) 
 attribute:

  if (auto *Format = FD->getAttr())
CheckPrintfPointerConversionSpecifierNULL(C, CE, Format->getFormatIdx());

You also have to check for pointer types first. This currently warns on 
`printf("%d", 0)`, since `0` is a null pointer constant (This warning should 
only be `T*` pointer types, C2x and C++ `nullptr` and GNU `__null`).

Also this only works for null pointer *constants*. `printf("%p", (void*) 0)` is 
pretty rare. You ideally want this to warn on the following too:

  void f(void* p) {
  if (!p) printf("%p", p);
  }
  void g(void) {
  void* p = NULL;
  printf("%p", p);
  }

Look into how the NonNullParamChecker works


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154838

___
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] D156032: Implement CWG2137 (list-initialization from objects of the same type)

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

Target clang 18 instead; add entry to release notes


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156032

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaInit.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/CXX/drs/dr14xx.cpp
  clang/test/CXX/drs/dr21xx.cpp
  clang/test/CXX/drs/dr23xx.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
@@ -12629,7 +12629,7 @@
 https://cplusplus.github.io/CWG/issues/2137.html";>2137
 CD4
 List-initialization from object of same type
-Unknown
+Clang 18
   
   
 https://cplusplus.github.io/CWG/issues/2138.html";>2138
Index: clang/test/CXX/drs/dr23xx.cpp
===
--- clang/test/CXX/drs/dr23xx.cpp
+++ clang/test/CXX/drs/dr23xx.cpp
@@ -5,6 +5,16 @@
 // RUN: %clang_cc1 -std=c++20 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
 // RUN: %clang_cc1 -std=c++23 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
 
+namespace std {
+  __extension__ typedef __SIZE_TYPE__ size_t;
+
+  template struct initializer_list {
+const E *p; size_t n;
+initializer_list(const E *p, size_t n);
+initializer_list();
+  };
+}
+
 #if __cplusplus >= 201103L
 namespace dr2303 { // dr2303: 12
 template 
@@ -37,6 +47,38 @@
 } //namespace dr2303
 #endif
 
+namespace dr2311 {
+#if __cplusplus >= 201707L
+template
+void test() {
+  // These should all be elided (no move)
+  T a = T{T(0)};
+  T b{T(0)};
+  auto c{T(0)};
+  T d = {T(0)};
+  auto e = {T(0)};
+#if __cplusplus >= 202302L
+  auto f = auto{T(0)};
+#endif
+}
+
+struct NonMovable {
+  NonMovable(int);
+  NonMovable(NonMovable&&) = delete;
+};
+
+template void test();
+
+struct NonMovableNonApplicableIList {
+  NonMovableNonApplicableIList(int);
+  NonMovableNonApplicableIList(NonMovableNonApplicableIList&&) = delete;
+  NonMovableNonApplicableIList(std::initializer_list);
+};
+
+template void test();
+#endif
+}
+
 // dr2331: na
 
 #if __cplusplus >= 201103L
Index: clang/test/CXX/drs/dr21xx.cpp
===
--- clang/test/CXX/drs/dr21xx.cpp
+++ clang/test/CXX/drs/dr21xx.cpp
@@ -10,6 +10,16 @@
 #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
 #endif
 
+namespace std {
+  __extension__ typedef __SIZE_TYPE__ size_t;
+
+  template struct initializer_list {
+const E *p; size_t n;
+initializer_list(const E *p, size_t n);
+initializer_list();
+  };
+}
+
 namespace dr2100 { // dr2100: 12
   template struct X {};
   template struct A {
@@ -110,6 +120,36 @@
 #endif
 }
 
+namespace dr2137 { // dr2137: 18
+#if __cplusplus >= 201103L
+  struct Q {
+Q();
+Q(Q&&);
+Q(std::initializer_list) = delete; // expected-note 2 {{has been explicitly marked deleted here}}
+  };
+
+  Q x = Q { Q() }; // expected-error {{call to deleted constructor}}
+
+  int f(Q); // expected-note {{passing argument to parameter here}}
+  int y = f({ Q() }); // expected-error {{call to deleted constructor}}
+
+  struct U {
+U();
+U(const U&);
+  };
+
+  struct Derived : U {
+Derived();
+Derived(const Derived&);
+  } d;
+
+  int g(Derived);
+  int g(U(&&)[1]) = delete;
+
+  int z = g({ d });
+#endif
+}
+
 namespace dr2140 { // dr2140: 9
 #if __cplusplus >= 201103L
   union U { int a; decltype(nullptr) b; };
Index: clang/test/CXX/drs/dr14xx.cpp
===
--- clang/test/CXX/drs/dr14xx.cpp
+++ clang/test/CXX/drs/dr14xx.cpp
@@ -423,16 +423,6 @@
 }
   } // nonaggregate
 
-  namespace SelfInitIsNotListInit {
-struct S {
-  S();
-  explicit S(S &);
-  S(const S &);
-};
-S s1;
-S s2 = {s1}; // ok, not list-initialization so we pick the non-explicit constructor
-  }
-
   struct NestedInit { int a, b, c; };
   NestedInit ni[1] = {{NestedInit{1, 2, 3}}};
 
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -1465,19 +1465,36 @@
 //   called for those cases.
 if (CXXConstructorDecl *Constructor
   = dyn_cast(ICS.UserDefined.ConversionFunction)) {
-  QualType FromCanon
-= S.Context.getCanonicalType(From->getType().getUnqualifiedType());
+  QualType FromType;
+  SourceLocation FromLoc;
+  // C++ [over.ics.list]p6, per DR2137:
+  //   If C is not an initializer-list constructor and the initializer list
+  //   has a single element of type cv U, where U is X or a class derived
+  //   from X, the implicit conversion sequence has Exact Match rank if U is
+  

[PATCH] D156064: [SemaCXX] Recognise initializer_list injected-class-name types as initializer_lists

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

wording of changelog


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156064

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaInit.cpp
  clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp


Index: clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
===
--- clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -12,14 +12,19 @@
 size_t n;
 initializer_list();
   };
-  // FIXME: This should probably not be necessary.
-  template initializer_list(initializer_list) -> 
initializer_list;
 }
 
 template constexpr bool has_type(...) { return false; }
 template constexpr bool has_type(T&) { return true; }
 
-std::initializer_list il = {1, 2, 3, 4, 5};
+std::initializer_list il1 = {1, 2, 3, 4, 5};
+auto il2 = std::initializer_list{1, 2, 3, 4};
+auto il3 = std::initializer_list{il1};
+auto il4 = std::initializer_list{il1, il1, il1};
+static_assert(has_type>(il1));
+static_assert(has_type>(il2));
+static_assert(has_type>(il3));
+static_assert(has_type>>(il4));
 
 template struct vector {
   template vector(Iter, Iter);
Index: clang/lib/Sema/SemaInit.cpp
===
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -10589,8 +10589,6 @@
   // FIXME: Perform "exact type" matching first, per CWG discussion?
   //Or implement this via an implied 'T(T) -> T' deduction guide?
 
-  // FIXME: Do we need/want a std::initializer_list special case?
-
   // Look up deduction guides, including those synthesized from constructors.
   //
   // C++1z [over.match.class.deduct]p1:
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -11749,11 +11749,17 @@
 
 Template = Specialization->getSpecializedTemplate();
 Arguments = Specialization->getTemplateArgs().data();
-  } else if (const TemplateSpecializationType *TST =
- Ty->getAs()) {
-Template = dyn_cast_or_null(
-TST->getTemplateName().getAsTemplateDecl());
-Arguments = TST->template_arguments().begin();
+  } else {
+const TemplateSpecializationType *TST = nullptr;
+if (auto *ICN = Ty->getAs())
+  TST = ICN->getInjectedTST();
+else
+  TST = Ty->getAs();
+if (TST) {
+  Template = dyn_cast_or_null(
+  TST->getTemplateName().getAsTemplateDecl());
+  Arguments = TST->template_arguments().begin();
+}
   }
   if (!Template)
 return false;
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -108,6 +108,10 @@
 Bug Fixes to C++ Support
 
 
+- Fix CTAD for ``std::initializer_list``. This allows
+  ``std::initializer_list{1, 2, 3}`` to be deduced as
+  ``std::initializer_list`` as intended.
+
 Bug Fixes to AST Handling
 ^
 


Index: clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
===
--- clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -12,14 +12,19 @@
 size_t n;
 initializer_list();
   };
-  // FIXME: This should probably not be necessary.
-  template initializer_list(initializer_list) -> initializer_list;
 }
 
 template constexpr bool has_type(...) { return false; }
 template constexpr bool has_type(T&) { return true; }
 
-std::initializer_list il = {1, 2, 3, 4, 5};
+std::initializer_list il1 = {1, 2, 3, 4, 5};
+auto il2 = std::initializer_list{1, 2, 3, 4};
+auto il3 = std::initializer_list{il1};
+auto il4 = std::initializer_list{il1, il1, il1};
+static_assert(has_type>(il1));
+static_assert(has_type>(il2));
+static_assert(has_type>(il3));
+static_assert(has_type>>(il4));
 
 template struct vector {
   template vector(Iter, Iter);
Index: clang/lib/Sema/SemaInit.cpp
===
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -10589,8 +10589,6 @@
   // FIXME: Perform "exact type" matching first, per CWG discussion?
   //Or implement this via an implied 'T(T) -> T' deduction guide?
 
-  // FIXME: Do we need/want a std::initializer_list special case?
-
   // Look up deduction guides, including those synthesized from constructors.
   //
   // C++1z [over.match.class.deduct]p1:
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/

[PATCH] D156032: Implement CWG2137 (list-initialization from objects of the same type)

2023-08-10 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok updated this revision to Diff 549145.
MitalAshok added a comment.
Herald added a project: libc++.
Herald added a subscriber: libcxx-commits.
Herald added a reviewer: libc++.

Fix broken libc++ pair constructor test


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156032

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaInit.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/CXX/drs/dr14xx.cpp
  clang/test/CXX/drs/dr21xx.cpp
  clang/test/CXX/drs/dr23xx.cpp
  clang/www/cxx_dr_status.html
  libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp

Index: libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp
===
--- libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp
+++ libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp
@@ -121,7 +121,30 @@
 test_pair_rv();
 test_pair_rv();
 
-test_pair_rv();
+/* For ExplicitTypes::CopyOnly, two of the viable candidates for initializing from a non-const xvalue are:
+ *   pair(const pair&);  // (defaulted copy constructor)
+ *   template explicit pair(const pair&&); [U1 = ExplicitTypes::CopyOnly, U2 = int]
+ * This results in diverging behavior for test_convertible which uses copy-list-initialization
+ * Prior to CWG2137, this would have selected the first (non-explicit) ctor as explicit ctors would not be considered
+ * Afterwards, it should select the second since it is a better match, and then failed because it is explicit
+ *
+ * This may change with future defect reports, and some compilers only have partial support for CWG2137,
+ * so use std::is_convertible directly to avoid a copy-list-initialization
+ */
+//test_pair_rv();
+static_assert(std::is_constructible,
+std::pair&&>::value,
+  "");
+static_assert(std::is_convertible&&,
+  std::pair>::value,
+  "");
+static_assert(std::is_constructible,
+std::pair&&>::value,
+  "");
+static_assert(std::is_convertible&&,
+  std::pair>::value,
+  "");
+
 test_pair_rv();
 test_pair_rv();
 
Index: clang/www/cxx_dr_status.html
===
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -12629,7 +12629,7 @@
 https://cplusplus.github.io/CWG/issues/2137.html";>2137
 CD4
 List-initialization from object of same type
-Unknown
+Clang 18
   
   
 https://cplusplus.github.io/CWG/issues/2138.html";>2138
Index: clang/test/CXX/drs/dr23xx.cpp
===
--- clang/test/CXX/drs/dr23xx.cpp
+++ clang/test/CXX/drs/dr23xx.cpp
@@ -5,6 +5,16 @@
 // RUN: %clang_cc1 -std=c++20 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
 // RUN: %clang_cc1 -std=c++23 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
 
+namespace std {
+  __extension__ typedef __SIZE_TYPE__ size_t;
+
+  template struct initializer_list {
+const E *p; size_t n;
+initializer_list(const E *p, size_t n);
+initializer_list();
+  };
+}
+
 #if __cplusplus >= 201103L
 namespace dr2303 { // dr2303: 12
 template 
@@ -37,6 +47,67 @@
 } //namespace dr2303
 #endif
 
+namespace dr2311 {
+#if __cplusplus >= 201707L
+template
+void test() {
+  // Ensure none of these expressions try to call a move constructor
+  T a = T{T(0)};
+  T b{T(0)};
+  auto c{T(0)};
+  T d = {T(0)};
+  auto e = {T(0)};
+#if __cplusplus >= 202302L
+  auto f = auto{T(0)};
+#endif
+  void(*fn)(T);
+  fn({T(0)});
+}
+
+struct NonMovable {
+  NonMovable(int);
+  NonMovable(NonMovable&&) = delete;
+};
+struct NonMovableNonApplicableIList {
+  NonMovableNonApplicableIList(int);
+  NonMovableNonApplicableIList(NonMovableNonApplicableIList&&) = delete;
+  NonMovableNonApplicableIList(std::initializer_list);
+};
+struct ExplicitMovable {
+  ExplicitMovable(int);
+  explicit ExplicitMovable(ExplicitMovable&&);
+};
+struct ExplicitNonMovable {
+  ExplicitNonMovable(int);
+  explicit ExplicitNonMovable(ExplicitNonMovable&&) = delete;
+};
+struct ExplicitNonMovableNonApplicableIList {
+  ExplicitNonMovableNonApplicableIList(int);
+  explicit ExplicitNonMovableNonApplicableIList(ExplicitNonMovableNonApplicableIList&&) = delete;
+  ExplicitNonMovableNonApplicableIList(std::initializer_list);
+};
+struct CopyOnly {
+  CopyOnly(int);
+  CopyOnly(const CopyOnly&);
+  CopyOnly(CopyOnly&&) = delete;
+};
+struct ExplicitCopyOnly {
+  ExplicitCopyOnly(int);
+

[PATCH] D156032: Implement CWG2137 (list-initialization from objects of the same type)

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

It seems there were two places which relied on `T x = { xvalue_of_type_T }` 
being a copy-initialization: The test at 
https://reviews.llvm.org/D156032#inline-1509544 and that one pair constructor 
test.

GCC seems to allow it but I don't think that's standard. I also have a pretty 
short patch to implement this behaviour if we decide that it needs to be 
supported (maybe this is a standard defect?)




Comment at: clang/test/CXX/drs/dr23xx.cpp:9
+namespace std {
+  __extension__ typedef __SIZE_TYPE__ size_t;
+

cor3ntin wrote:
> 
Wouldn't work in c++98 mode this file is being run in. I've copied this from 
other tests in this directory. I guess I can put a `#if __cplusplus >= 201103L` 
instead?



Comment at: clang/test/CXX/drs/dr23xx.cpp:50
 
+namespace dr2311 {
+#if __cplusplus >= 201707L

cor3ntin wrote:
> the dr status html page is generated automatically by leaving a magic comment 
> here - and then running `clang/www/make_cxx_dr_status`
CWG2311 is still open, but clang did support list-initialization elision before 
this patch. The committee still needs to decide how exactly this elision is 
going to work, which might be different from how this patch implements it, so 
hesitant to mark this as done.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156032

___
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 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 -verify=ex

[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);
+  printf(

[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) {
+  (void)__builtin_va_a

[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, v

[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] D156032: Implement CWG2137 (list-initialization from objects of the same type)

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

Address comments; better implementation for elision (check after considering 
only initializer list constructors)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156032

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaInit.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/CXX/drs/dr14xx.cpp
  clang/test/CXX/drs/dr21xx.cpp
  clang/test/CXX/drs/dr23xx.cpp
  clang/www/cxx_dr_status.html
  libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp

Index: libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp
===
--- libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp
+++ libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp
@@ -121,7 +121,26 @@
 test_pair_rv();
 test_pair_rv();
 
-test_pair_rv();
+/* For ExplicitTypes::CopyOnly, two of the viable candidates for initializing from a non-const xvalue are:
+ *   pair(const pair&);  // (defaulted copy constructor)
+ *   template explicit pair(const pair&&); [U1 = ExplicitTypes::CopyOnly, U2 = int]
+ * This results in diverging behavior for test_convertible which uses copy-list-initialization
+ * Prior to CWG2137, this would have selected the first (non-explicit) ctor as explicit ctors would not be considered
+ * Afterwards, it should select the second since it is a better match, and then failed because it is explicit
+ *
+ * This may change with future defect reports, and some compilers only have partial support for CWG2137,
+ * so use std::is_convertible directly to avoid a copy-list-initialization
+ */
+{
+  using P1  = std::pair;
+  using P2  = std::pair;
+  using UP1 = std::pair&&;
+  using UP2 = std::pair&&;
+  static_assert(std::is_constructible::value, "");
+  static_assert(std::is_convertible::value, "");
+  static_assert(std::is_constructible::value, "");
+  static_assert(std::is_convertible::value, "");
+}
 test_pair_rv();
 test_pair_rv();
 
Index: clang/www/cxx_dr_status.html
===
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -12629,7 +12629,7 @@
 https://cplusplus.github.io/CWG/issues/2137.html";>2137
 CD4
 List-initialization from object of same type
-Unknown
+Clang 18
   
   
 https://cplusplus.github.io/CWG/issues/2138.html";>2138
@@ -13673,7 +13673,7 @@
 https://cplusplus.github.io/CWG/issues/2311.html";>2311
 open
 Missed case for guaranteed copy elision
-Not resolved
+Clang 18
   
   
 https://cplusplus.github.io/CWG/issues/2312.html";>2312
Index: clang/test/CXX/drs/dr23xx.cpp
===
--- clang/test/CXX/drs/dr23xx.cpp
+++ clang/test/CXX/drs/dr23xx.cpp
@@ -5,6 +5,16 @@
 // RUN: %clang_cc1 -std=c++20 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
 // RUN: %clang_cc1 -std=c++23 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
 
+namespace std {
+  __extension__ typedef __SIZE_TYPE__ size_t;
+
+  template struct initializer_list {
+const E *p; size_t n;
+initializer_list(const E *p, size_t n);
+initializer_list();
+  };
+}
+
 #if __cplusplus >= 201103L
 namespace dr2303 { // dr2303: 12
 template 
@@ -37,6 +47,80 @@
 } //namespace dr2303
 #endif
 
+namespace dr2311 {  // dr2311: 18 open
+#if __cplusplus >= 201707L
+template
+void test() {
+  // Ensure none of these expressions try to call a move constructor.
+  T a = T{T(0)};
+  T b{T(0)};
+  auto c{T(0)};
+  T d = {T(0)};
+  auto e = {T(0)};
+#if __cplusplus >= 202302L
+  auto f = auto{T(0)};
+#endif
+  void(*fn)(T);
+  fn({T(0)});
+}
+
+struct NonMovable {
+  NonMovable(int);
+  NonMovable(NonMovable&&) = delete;
+};
+struct NonMovableNonApplicableIList {
+  NonMovableNonApplicableIList(int);
+  NonMovableNonApplicableIList(NonMovableNonApplicableIList&&) = delete;
+  NonMovableNonApplicableIList(std::initializer_list);
+};
+struct ExplicitMovable {
+  ExplicitMovable(int);
+  explicit ExplicitMovable(ExplicitMovable&&);
+};
+struct ExplicitNonMovable {
+  ExplicitNonMovable(int);
+  explicit ExplicitNonMovable(ExplicitNonMovable&&) = delete;
+};
+struct ExplicitNonMovableNonApplicableIList {
+  ExplicitNonMovableNonApplicableIList(int);
+  explicit ExplicitNonMovableNonApplicableIList(ExplicitNonMovableNonApplicableIList&&) = delete;
+  ExplicitNonMovableNonApplicableIList(std::initializer_list);
+};
+struct CopyOnly {
+  CopyOnly(int);
+  CopyOnly(const CopyOnly&);
+  CopyOnly(CopyOnly&&) = delete;
+};
+struct E

[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-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-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}}
Ind

[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 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", &np);  // expected-warning {{format specifies type 'void **' but 
the argument has type 'nullptr_t *'}}
+  scanf("%p", &npp);  // 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] D154301: Fix aggregate CTAD with string literals adding extra const

2023-07-02 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok created this revision.
Herald added a project: All.
MitalAshok edited the summary of this revision.
MitalAshok added reviewers: ychen, aaron.ballman, cor3ntin.
MitalAshok added a subscriber: cfe-commits.
MitalAshok retitled this revision from "Fix CTAD with string literals adding 
extra const" to "Fix aggregate CTAD with string literals adding extra const".
MitalAshok added inline comments.
MitalAshok published this revision for review.
Herald added a project: clang.



Comment at: clang/lib/Sema/SemaInit.cpp:10707
 //   if e_i is of array type and x_i is a bstring-literal, T_i is an
 //   lvalue reference to the const-qualified declared type of e_i and
 // C++ [over.match.class.deduct]p1.10:

The "const-qualified" here was missing


Missing a `withConst`, so when deducing from a string literal, a `const` is 
erroneously added to the deduced type.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154301

Files:
  clang/lib/Sema/SemaInit.cpp
  
clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p1-9.cpp


Index: 
clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p1-9.cpp
===
--- /dev/null
+++ 
clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p1-9.cpp
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -verify -std=c++20 %s
+
+using size_t = decltype(sizeof(int));
+
+template
+struct H {
+  T array[N];
+};
+template
+struct I {
+  volatile T array[N];
+};
+template
+struct J {  // expected-note 3{{candidate}}
+  unsigned char array[N];
+};
+
+H h = { "abc" };
+I i = { "def" };
+static_assert(__is_same(decltype(h), H));  // Not H
+static_assert(__is_same(decltype(i), I));
+
+J j = { "ghi" };  // expected-error {{no viable constructor or deduction 
guide}}
+
+template
+struct K {
+  char array[N];
+};
+K k = { "abc" };
+static_assert(__is_same(decltype(k), K<4>));
+
+template
+struct L {
+  const T array[N];
+};
+L l = { "abc" };
+static_assert(__is_same(decltype(l), L));
+
+template
+struct M {
+  T array[sizeof(T) == 0 ? 4 : 4];
+};
+M m = { "abc" };
+static_assert(__is_same(decltype(m), M));
+
+/*
+template
+struct N {
+  T array[4];
+};
+// The C99 extension, brace elision for designated initializers,
+// makes `T = const char*` viable, and that is used instead
+N n = { .array = "abc" };
+static_assert(__is_same(decltype(n), N));
+ */
Index: clang/lib/Sema/SemaInit.cpp
===
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -10714,7 +10714,8 @@
   ElementTypes[I] = 
Context.getRValueReferenceType(ElementTypes[I]);
 else if (isa(
  ListInit->getInit(I)->IgnoreParenImpCasts()))
-  ElementTypes[I] = 
Context.getLValueReferenceType(ElementTypes[I]);
+  ElementTypes[I] =
+  Context.getLValueReferenceType(ElementTypes[I].withConst());
   }
 
 llvm::FoldingSetNodeID ID;


Index: clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p1-9.cpp
===
--- /dev/null
+++ clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p1-9.cpp
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -verify -std=c++20 %s
+
+using size_t = decltype(sizeof(int));
+
+template
+struct H {
+  T array[N];
+};
+template
+struct I {
+  volatile T array[N];
+};
+template
+struct J {  // expected-note 3{{candidate}}
+  unsigned char array[N];
+};
+
+H h = { "abc" };
+I i = { "def" };
+static_assert(__is_same(decltype(h), H));  // Not H
+static_assert(__is_same(decltype(i), I));
+
+J j = { "ghi" };  // expected-error {{no viable constructor or deduction guide}}
+
+template
+struct K {
+  char array[N];
+};
+K k = { "abc" };
+static_assert(__is_same(decltype(k), K<4>));
+
+template
+struct L {
+  const T array[N];
+};
+L l = { "abc" };
+static_assert(__is_same(decltype(l), L));
+
+template
+struct M {
+  T array[sizeof(T) == 0 ? 4 : 4];
+};
+M m = { "abc" };
+static_assert(__is_same(decltype(m), M));
+
+/*
+template
+struct N {
+  T array[4];
+};
+// The C99 extension, brace elision for designated initializers,
+// makes `T = const char*` viable, and that is used instead
+N n = { .array = "abc" };
+static_assert(__is_same(decltype(n), N));
+ */
Index: clang/lib/Sema/SemaInit.cpp
===
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -10714,7 +10714,8 @@
   ElementTypes[I] = Context.getRValueReferenceType(ElementTypes[I]);
 else if (isa(
  ListInit->getInit(I)->IgnoreParenImpCasts()))
-  ElementTypes[I] = Context.getLValueReferenceType(ElementTypes[I]);
+  ElementTypes[I] =
+  Context.getLValueReferenceType(ElementTypes[I].with

[PATCH] D154301: Fix aggregate CTAD with string literals adding extra const

2023-07-02 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok updated this revision to Diff 536648.
MitalAshok edited the summary of this revision.
MitalAshok added a comment.

Add status for CWG2681 and fixed aggregate-deduction-candidate test


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154301

Files:
  clang/lib/Sema/SemaInit.cpp
  clang/test/CXX/drs/dr26xx.cpp
  clang/test/SemaTemplate/aggregate-deduction-candidate.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
@@ -15893,7 +15893,7 @@
 https://cplusplus.github.io/CWG/issues/2681.html";>2681
 DR
 Deducing member array type from string literal
-Unknown
+Clang 17
   
   
 https://cplusplus.github.io/CWG/issues/2682.html";>2682
Index: clang/test/SemaTemplate/aggregate-deduction-candidate.cpp
===
--- clang/test/SemaTemplate/aggregate-deduction-candidate.cpp
+++ clang/test/SemaTemplate/aggregate-deduction-candidate.cpp
@@ -198,22 +198,22 @@
   // CHECK: FunctionTemplateDecl {{.*}} implicit 
   // CHECK: |-TemplateTypeParmDecl {{.*}} referenced typename depth 0 index 0 T
   // CHECK: |-NonTypeTemplateParmDecl {{.*}} 'size_t':'unsigned {{.*}}' depth 
0 index 1 N
-  // CHECK: |-CXXDeductionGuideDecl {{.*}} implicit  
'auto (T (&)[N]) -> A'
-  // CHECK: | `-ParmVarDecl {{.*}} 'T (&)[N]'
-  // CHECK: `-CXXDeductionGuideDecl {{.*}} implicit used  'auto (const char (&)[5]) -> Array::A'
-  // CHECK:   |-TemplateArgument type 'const char'
-  // CHECK:   | `-QualType {{.*}} 'const char' const
-  // CHECK:   |   `-BuiltinType {{.*}} 'char'
+  // CHECK: |-CXXDeductionGuideDecl {{.*}} implicit  
'auto (const T (&)[N]) -> A'
+  // CHECK: | `-ParmVarDecl {{.*}} 'const T (&)[N]'
+  // CHECK: `-CXXDeductionGuideDecl {{.*}} implicit used  'auto (const char (&)[5]) -> Array::A'
+  // CHECK:   |-TemplateArgument type 'char'
+  // CHECK:   | `-BuiltinType {{.*}} 'char'
   // CHECK:   |-TemplateArgument integral 5
   // CHECK:   `-ParmVarDecl {{.*}} 'const char (&)[5]'
-  // CHECK: FunctionProtoType {{.*}} 'auto (T (&)[N]) -> A' dependent 
trailing_return cdecl
+  // CHECK: FunctionProtoType {{.*}} 'auto (const T (&)[N]) -> A' 
dependent trailing_return cdecl
   // CHECK: |-InjectedClassNameType {{.*}} 'A' dependent
   // CHECK: | `-CXXRecord {{.*}} 'A'
-  // CHECK: `-LValueReferenceType {{.*}} 'T (&)[N]' dependent
-  // CHECK:   `-DependentSizedArrayType {{.*}} 'T[N]' dependent
-  // CHECK: |-TemplateTypeParmType {{.*}} 'T' dependent depth 0 index 0
-  // CHECK: | `-TemplateTypeParm {{.*}} 'T'
-  // CHECK: `-DeclRefExpr {{.*}} 'size_t':'unsigned {{.*}}' 
NonTypeTemplateParm {{.*}} 'N' 'size_t':'unsigned {{.*}}'
+  // CHECK: `-LValueReferenceType {{.*}} 'const T (&)[N]' dependent
+  // CHECK:   `-QualType {{.*}} 'const T[N]' const
+  // CHECK: `-DependentSizedArrayType {{.*}} 'T[N]' dependent
+  // CHECK:   |-TemplateTypeParmType {{.*}} 'T' dependent depth 0 index 0
+  // CHECK:   | `-TemplateTypeParm {{.*}} 'T'
+  // CHECK:   `-DeclRefExpr {{.*}} 'size_t':'unsigned{{.*}}' 
NonTypeTemplateParm {{.*}} 'N' 'size_t':'unsigned{{.*}}'
 }
 
 namespace BraceElision {
Index: clang/test/CXX/drs/dr26xx.cpp
===
--- clang/test/CXX/drs/dr26xx.cpp
+++ clang/test/CXX/drs/dr26xx.cpp
@@ -126,3 +126,27 @@
 brachiosaur |= neck;// OK
 }
 }
+
+namespace dr2681 { // dr2681: 17
+using size_t = decltype(sizeof(int));
+
+template
+struct H {
+  T array[N];
+};
+template
+struct I {
+  volatile T array[N];
+};
+template
+struct J {  // expected-note 3{{candidate}}
+  unsigned char array[N];
+};
+
+H h = { "abc" };
+I i = { "def" };
+static_assert(__is_same(decltype(h), H));  // Not H
+static_assert(__is_same(decltype(i), I));
+
+J j = { "ghi" };  // expected-error {{no viable constructor or deduction 
guide}}
+}
Index: clang/lib/Sema/SemaInit.cpp
===
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -10714,7 +10714,8 @@
   ElementTypes[I] = 
Context.getRValueReferenceType(ElementTypes[I]);
 else if (isa(
  ListInit->getInit(I)->IgnoreParenImpCasts()))
-  ElementTypes[I] = 
Context.getLValueReferenceType(ElementTypes[I]);
+  ElementTypes[I] =
+  Context.getLValueReferenceType(ElementTypes[I].withConst());
   }
 
 llvm::FoldingSetNodeID ID;


Index: clang/www/cxx_dr_status.html
===
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -15893,7 +15893,7 @@
 https://cplusplus.github.io/CWG/issues/2681.html";>2681
 DR
 Deducing member array type fro

[PATCH] D154716: [SemaCXX] Fix bug where unexpanded lambda captures where assumed to be expanded

2023-07-07 Thread Mital Ashok via Phabricator via cfe-commits
MitalAshok created this revision.
Herald added a project: All.
MitalAshok edited the summary of this revision.
MitalAshok added reviewers: rsmith, cor3ntin.
MitalAshok published this revision for review.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

When instantiating the closure type of a lambda in a template, sometimes a 
capture which is a pack is not expanded. When that happens, it is replaced with 
a pack of size 1 containing that pack. Before it is replaced by another 
instantiation where the pack is expanded, the size is reported to be 1 instead 
of unknown.

This checks if this is happening (i.e., trying to replace a pack declaration 
with a single declaration that is itself a pack), and not expanding it out in 
that case.

Fixes https://github.com/llvm/llvm-project/issues/63677


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154716

Files:
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/TreeTransform.h
  clang/test/SemaCXX/lambda-pack-expansion.cpp


Index: clang/test/SemaCXX/lambda-pack-expansion.cpp
===
--- clang/test/SemaCXX/lambda-pack-expansion.cpp
+++ clang/test/SemaCXX/lambda-pack-expansion.cpp
@@ -21,3 +21,18 @@
   take_by_ref(x);
 }
 }
+
+namespace GH63677 {
+
+template
+void f() {
+[]() -> void {
+[...us = Ts{}]{
+(Ts(us), ...);
+};
+}.template operator()();
+}
+
+template void f();
+
+}
Index: clang/lib/Sema/TreeTransform.h
===
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -13340,14 +13340,14 @@
   OldVD->getInit()->getSourceRange(), Unexpanded, Expand,
   RetainExpansion, NumExpansions))
 return ExprError();
+  assert(!RetainExpansion && "Should not need to retain expansion after a "
+ "capture since it cannot be extended");
   if (Expand) {
 for (unsigned I = 0; I != *NumExpansions; ++I) {
   Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
   SubstInitCapture(SourceLocation(), std::nullopt);
 }
-  }
-  if (!Expand || RetainExpansion) {
-ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+  } else {
 SubstInitCapture(ExpansionTL.getEllipsisLoc(), NumExpansions);
 Result.EllipsisLoc = ExpansionTL.getEllipsisLoc();
   }
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1270,7 +1270,8 @@
 }
 
 void transformedLocalDecl(Decl *Old, ArrayRef NewDecls) {
-  if (Old->isParameterPack()) {
+  if (Old->isParameterPack() &&
+  (NewDecls.size() != 1 || !NewDecls.front()->isParameterPack())) {
 SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Old);
 for (auto *New : NewDecls)
   SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(


Index: clang/test/SemaCXX/lambda-pack-expansion.cpp
===
--- clang/test/SemaCXX/lambda-pack-expansion.cpp
+++ clang/test/SemaCXX/lambda-pack-expansion.cpp
@@ -21,3 +21,18 @@
   take_by_ref(x);
 }
 }
+
+namespace GH63677 {
+
+template
+void f() {
+[]() -> void {
+[...us = Ts{}]{
+(Ts(us), ...);
+};
+}.template operator()();
+}
+
+template void f();
+
+}
Index: clang/lib/Sema/TreeTransform.h
===
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -13340,14 +13340,14 @@
   OldVD->getInit()->getSourceRange(), Unexpanded, Expand,
   RetainExpansion, NumExpansions))
 return ExprError();
+  assert(!RetainExpansion && "Should not need to retain expansion after a "
+ "capture since it cannot be extended");
   if (Expand) {
 for (unsigned I = 0; I != *NumExpansions; ++I) {
   Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
   SubstInitCapture(SourceLocation(), std::nullopt);
 }
-  }
-  if (!Expand || RetainExpansion) {
-ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+  } else {
 SubstInitCapture(ExpansionTL.getEllipsisLoc(), NumExpansions);
 Result.EllipsisLoc = ExpansionTL.getEllipsisLoc();
   }
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1270,7 +1270,8 @@
 }
 
 void transformedLocalDecl(Decl *Old, ArrayRef NewDecls) {
-  if (Old->isParameterPack()) {
+  if (Old->isParameterPack() &&
+  (NewDecls

[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 {{secon

[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); // expect

[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] D156032: Implement CWG2137 (list-initialization from objects of the same type)

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

rebased onto fast-forwarded main branch

(trying to fix seemingly unrelated CI build failure)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156032

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaInit.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/CXX/drs/dr14xx.cpp
  clang/test/CXX/drs/dr21xx.cpp
  clang/test/CXX/drs/dr23xx.cpp
  clang/www/cxx_dr_status.html
  libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp

Index: libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp
===
--- libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp
+++ libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp
@@ -121,7 +121,26 @@
 test_pair_rv();
 test_pair_rv();
 
-test_pair_rv();
+/* For ExplicitTypes::CopyOnly, two of the viable candidates for initializing from a non-const xvalue are:
+ *   pair(const pair&);  // (defaulted copy constructor)
+ *   template explicit pair(const pair&&); [U1 = ExplicitTypes::CopyOnly, U2 = int]
+ * This results in diverging behavior for test_convertible which uses copy-list-initialization
+ * Prior to CWG2137, this would have selected the first (non-explicit) ctor as explicit ctors would not be considered
+ * Afterwards, it should select the second since it is a better match, and then failed because it is explicit
+ *
+ * This may change with future defect reports, and some compilers only have partial support for CWG2137,
+ * so use std::is_convertible directly to avoid a copy-list-initialization
+ */
+{
+  using P1  = std::pair;
+  using P2  = std::pair;
+  using UP1 = std::pair&&;
+  using UP2 = std::pair&&;
+  static_assert(std::is_constructible::value, "");
+  static_assert(std::is_convertible::value, "");
+  static_assert(std::is_constructible::value, "");
+  static_assert(std::is_convertible::value, "");
+}
 test_pair_rv();
 test_pair_rv();
 
Index: clang/www/cxx_dr_status.html
===
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -12629,7 +12629,7 @@
 https://cplusplus.github.io/CWG/issues/2137.html";>2137
 CD4
 List-initialization from object of same type
-Unknown
+Clang 18
   
   
 https://cplusplus.github.io/CWG/issues/2138.html";>2138
@@ -13673,7 +13673,7 @@
 https://cplusplus.github.io/CWG/issues/2311.html";>2311
 open
 Missed case for guaranteed copy elision
-Not resolved
+Clang 18
   
   
 https://cplusplus.github.io/CWG/issues/2312.html";>2312
Index: clang/test/CXX/drs/dr23xx.cpp
===
--- clang/test/CXX/drs/dr23xx.cpp
+++ clang/test/CXX/drs/dr23xx.cpp
@@ -5,6 +5,16 @@
 // RUN: %clang_cc1 -std=c++20 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
 // RUN: %clang_cc1 -std=c++23 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
 
+namespace std {
+  __extension__ typedef __SIZE_TYPE__ size_t;
+
+  template struct initializer_list {
+const E *p; size_t n;
+initializer_list(const E *p, size_t n);
+initializer_list();
+  };
+}
+
 #if __cplusplus >= 201103L
 namespace dr2303 { // dr2303: 12
 template 
@@ -37,6 +47,80 @@
 } //namespace dr2303
 #endif
 
+namespace dr2311 {  // dr2311: 18 open
+#if __cplusplus >= 201707L
+template
+void test() {
+  // Ensure none of these expressions try to call a move constructor.
+  T a = T{T(0)};
+  T b{T(0)};
+  auto c{T(0)};
+  T d = {T(0)};
+  auto e = {T(0)};
+#if __cplusplus >= 202302L
+  auto f = auto{T(0)};
+#endif
+  void(*fn)(T);
+  fn({T(0)});
+}
+
+struct NonMovable {
+  NonMovable(int);
+  NonMovable(NonMovable&&) = delete;
+};
+struct NonMovableNonApplicableIList {
+  NonMovableNonApplicableIList(int);
+  NonMovableNonApplicableIList(NonMovableNonApplicableIList&&) = delete;
+  NonMovableNonApplicableIList(std::initializer_list);
+};
+struct ExplicitMovable {
+  ExplicitMovable(int);
+  explicit ExplicitMovable(ExplicitMovable&&);
+};
+struct ExplicitNonMovable {
+  ExplicitNonMovable(int);
+  explicit ExplicitNonMovable(ExplicitNonMovable&&) = delete;
+};
+struct ExplicitNonMovableNonApplicableIList {
+  ExplicitNonMovableNonApplicableIList(int);
+  explicit ExplicitNonMovableNonApplicableIList(ExplicitNonMovableNonApplicableIList&&) = delete;
+  ExplicitNonMovableNonApplicableIList(std::initializer_list);
+};
+struct CopyOnly {
+  CopyOnly(int);
+  CopyOnly(const CopyOnly&);
+  CopyOnly(CopyOnly&&) = delete;
+};
+struct ExplicitCopyOnly {
+ 

[PATCH] D156032: Implement CWG2137 (list-initialization from objects of the same type)

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

Remove accidental unrelated changelog


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156032

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaInit.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/CXX/drs/dr14xx.cpp
  clang/test/CXX/drs/dr21xx.cpp
  clang/test/CXX/drs/dr23xx.cpp
  clang/www/cxx_dr_status.html
  libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp

Index: libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp
===
--- libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp
+++ libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_move.pass.cpp
@@ -121,7 +121,26 @@
 test_pair_rv();
 test_pair_rv();
 
-test_pair_rv();
+/* For ExplicitTypes::CopyOnly, two of the viable candidates for initializing from a non-const xvalue are:
+ *   pair(const pair&);  // (defaulted copy constructor)
+ *   template explicit pair(const pair&&); [U1 = ExplicitTypes::CopyOnly, U2 = int]
+ * This results in diverging behavior for test_convertible which uses copy-list-initialization
+ * Prior to CWG2137, this would have selected the first (non-explicit) ctor as explicit ctors would not be considered
+ * Afterwards, it should select the second since it is a better match, and then failed because it is explicit
+ *
+ * This may change with future defect reports, and some compilers only have partial support for CWG2137,
+ * so use std::is_convertible directly to avoid a copy-list-initialization
+ */
+{
+  using P1  = std::pair;
+  using P2  = std::pair;
+  using UP1 = std::pair&&;
+  using UP2 = std::pair&&;
+  static_assert(std::is_constructible::value, "");
+  static_assert(std::is_convertible::value, "");
+  static_assert(std::is_constructible::value, "");
+  static_assert(std::is_convertible::value, "");
+}
 test_pair_rv();
 test_pair_rv();
 
Index: clang/www/cxx_dr_status.html
===
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -12629,7 +12629,7 @@
 https://cplusplus.github.io/CWG/issues/2137.html";>2137
 CD4
 List-initialization from object of same type
-Unknown
+Clang 18
   
   
 https://cplusplus.github.io/CWG/issues/2138.html";>2138
@@ -13673,7 +13673,7 @@
 https://cplusplus.github.io/CWG/issues/2311.html";>2311
 open
 Missed case for guaranteed copy elision
-Not resolved
+Clang 18
   
   
 https://cplusplus.github.io/CWG/issues/2312.html";>2312
Index: clang/test/CXX/drs/dr23xx.cpp
===
--- clang/test/CXX/drs/dr23xx.cpp
+++ clang/test/CXX/drs/dr23xx.cpp
@@ -5,6 +5,16 @@
 // RUN: %clang_cc1 -std=c++20 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
 // RUN: %clang_cc1 -std=c++23 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
 
+namespace std {
+  __extension__ typedef __SIZE_TYPE__ size_t;
+
+  template struct initializer_list {
+const E *p; size_t n;
+initializer_list(const E *p, size_t n);
+initializer_list();
+  };
+}
+
 #if __cplusplus >= 201103L
 namespace dr2303 { // dr2303: 12
 template 
@@ -37,6 +47,80 @@
 } //namespace dr2303
 #endif
 
+namespace dr2311 {  // dr2311: 18 open
+#if __cplusplus >= 201707L
+template
+void test() {
+  // Ensure none of these expressions try to call a move constructor.
+  T a = T{T(0)};
+  T b{T(0)};
+  auto c{T(0)};
+  T d = {T(0)};
+  auto e = {T(0)};
+#if __cplusplus >= 202302L
+  auto f = auto{T(0)};
+#endif
+  void(*fn)(T);
+  fn({T(0)});
+}
+
+struct NonMovable {
+  NonMovable(int);
+  NonMovable(NonMovable&&) = delete;
+};
+struct NonMovableNonApplicableIList {
+  NonMovableNonApplicableIList(int);
+  NonMovableNonApplicableIList(NonMovableNonApplicableIList&&) = delete;
+  NonMovableNonApplicableIList(std::initializer_list);
+};
+struct ExplicitMovable {
+  ExplicitMovable(int);
+  explicit ExplicitMovable(ExplicitMovable&&);
+};
+struct ExplicitNonMovable {
+  ExplicitNonMovable(int);
+  explicit ExplicitNonMovable(ExplicitNonMovable&&) = delete;
+};
+struct ExplicitNonMovableNonApplicableIList {
+  ExplicitNonMovableNonApplicableIList(int);
+  explicit ExplicitNonMovableNonApplicableIList(ExplicitNonMovableNonApplicableIList&&) = delete;
+  ExplicitNonMovableNonApplicableIList(std::initializer_list);
+};
+struct CopyOnly {
+  CopyOnly(int);
+  CopyOnly(const CopyOnly&);
+  CopyOnly(CopyOnly&&) = delete;
+};
+struct ExplicitCopyOnly {
+  ExplicitCopyOnly(int);
+  explicit ExplicitCopyOnly(con