Mordante created this revision.
Mordante added reviewers: lvoufo, rsmith.
Mordante added a project: clang.
Mordante requested review of this revision.

This implements C++20's P0388.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D87566

Files:
  clang/lib/AST/ASTContext.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/SemaCXX/const-cast.cpp
  clang/test/SemaCXX/overload-call.cpp
  clang/www/cxx_status.html

Index: clang/www/cxx_status.html
===================================================================
--- clang/www/cxx_status.html
+++ clang/www/cxx_status.html
@@ -1188,7 +1188,7 @@
     <tr>
       <td>Permit conversions to arrays of unknown bound</td>
       <td><a href="https://wg21.link/p0388r4";>P0388R4</a></td>
-      <td class="none" align="center">No</td>
+      <td class="unreleased" align="center">Clang 12</td>
     </tr>
     <tr>
       <td><tt>constinit</tt></td>
Index: clang/test/SemaCXX/overload-call.cpp
===================================================================
--- clang/test/SemaCXX/overload-call.cpp
+++ clang/test/SemaCXX/overload-call.cpp
@@ -1,6 +1,9 @@
 // RUN: %clang_cc1 -triple %itanium_abi_triple -pedantic -verify %s
 // RUN: %clang_cc1 -triple %itanium_abi_triple -pedantic -verify -std=c++98 %s
 // RUN: %clang_cc1 -triple %itanium_abi_triple -pedantic -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -pedantic -verify -std=c++14 %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -pedantic -verify -std=c++17 %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -pedantic -verify -std=c++20 %s
 
 int* f(int) { return 0; }
 float* f(float) { return 0; }
@@ -721,4 +724,25 @@
 }
 
 } // namespace InitializerListToArray
+
+namespace P0338 {
+void f(int(&&)[]);
+void f(double(&&)[]);
+void f(int(&&)[2]);
+
+void g() {
+  f({1});
+#if __cplusplus < 202002L
+// expected-error@+3 {{type 'double' cannot be narrowed to 'int' in initializer list}}
+// expected-note@+2 {{insert an explicit cast to silence this issue}}
+#endif
+  f({1.0});
+#if __cplusplus < 202002L
+// expected-error@+3 2 {{type 'double' cannot be narrowed to 'int' in initializer list}}
+// expected-note@+2 2 {{insert an explicit cast to silence this issue}}
+#endif
+  f({1.0, 2.0});
+  f({1, 2});
+}
+} // namespace P0338
 #endif
Index: clang/test/SemaCXX/const-cast.cpp
===================================================================
--- clang/test/SemaCXX/const-cast.cpp
+++ clang/test/SemaCXX/const-cast.cpp
@@ -66,9 +66,15 @@
   (void) const_cast<int *(*)[100]>(&ar); // ok
   (void) const_cast<int *(*)[]>(&aub); // ok
   // ... but the array bound must exactly match.
-  (void) const_cast<int *(*)[]>(&ar); // expected-error {{const_cast from 'const int *(*)[100]' to 'int *(*)[]' is not allowed}}
+  (void) const_cast<int *(*)[]>(&ar);
+#if __cplusplus < 202002L // P0388
+  // expected-error@-2 {{const_cast from 'const int *(*)[100]' to 'int *(*)[]' is not allowed}}
+#endif
   (void) const_cast<int *(*)[99]>(&ar); // expected-error {{const_cast from 'const int *(*)[100]' to 'int *(*)[99]' is not allowed}}
-  (void) const_cast<int *(*)[100]>(&aub); // expected-error {{const_cast from 'const int *(*)[]' to 'int *(*)[100]' is not allowed}}
+  (void) const_cast<int *(*)[100]>(&aub);
+#if __cplusplus < 202002L // P0388
+  // expected-error@-2 {{const_cast from 'const int *(*)[]' to 'int *(*)[100]' is not allowed}}
+#endif
   f fp1 = 0;
   // Function pointers.
   f fp2 = const_cast<f>(fp1); // expected-error {{const_cast to 'f' (aka 'int (*)(int)'), which is not a reference, pointer-to-object, or pointer-to-data-member}}
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -5060,8 +5060,10 @@
   Result.setBad(BadConversionSequence::no_conversion, From, ToType);
 
   // We need a complete type for what follows. Incomplete types can never be
-  // initialized from init lists.
-  if (!S.isCompleteType(From->getBeginLoc(), ToType))
+  // initialized from init lists. In C++20 an array of unknown bound can be
+  // initialized form a init list.
+  if (!S.isCompleteType(From->getBeginLoc(), ToType) &&
+      !S.getLangOpts().CPlusPlus20 && !isa<IncompleteArrayType>(ToType))
     return Result;
 
   // Per DR1467:
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -5665,28 +5665,33 @@
                                     SourceRange());
 }
 
+static bool canUnwrapSimilarArrayTypes(const ArrayType *AT1,
+                                       const ArrayType *AT2, bool CPlusPlus20) {
+  // If we don't have two array types with the same constant bound nor two
+  // incomplete array types, we've unwrapped everything we can.
+  // C++20 allows the combintion of constant bound and incomplete arrays.
+  if (const auto *CAT1 = dyn_cast<ConstantArrayType>(AT1))
+    if (const auto *CAT2 = dyn_cast<ConstantArrayType>(AT2))
+      return CAT1->getSize() == CAT2->getSize();
+
+  return CPlusPlus20 ||
+         (isa<IncompleteArrayType>(AT1) && isa<IncompleteArrayType>(AT2));
+}
+
 /// Attempt to unwrap two types that may both be array types with the same bound
 /// (or both be array types of unknown bound) for the purpose of comparing the
 /// cv-decomposition of two types per C++ [conv.qual].
 bool ASTContext::UnwrapSimilarArrayTypes(QualType &T1, QualType &T2) {
   bool UnwrappedAny = false;
   while (true) {
-    auto *AT1 = getAsArrayType(T1);
+    const auto *AT1 = getAsArrayType(T1);
     if (!AT1) return UnwrappedAny;
 
-    auto *AT2 = getAsArrayType(T2);
+    const auto *AT2 = getAsArrayType(T2);
     if (!AT2) return UnwrappedAny;
 
-    // If we don't have two array types with the same constant bound nor two
-    // incomplete array types, we've unwrapped everything we can.
-    if (auto *CAT1 = dyn_cast<ConstantArrayType>(AT1)) {
-      auto *CAT2 = dyn_cast<ConstantArrayType>(AT2);
-      if (!CAT2 || CAT1->getSize() != CAT2->getSize())
-        return UnwrappedAny;
-    } else if (!isa<IncompleteArrayType>(AT1) ||
-               !isa<IncompleteArrayType>(AT2)) {
+    if (!canUnwrapSimilarArrayTypes(AT1, AT2, getLangOpts().CPlusPlus20))
       return UnwrappedAny;
-    }
 
     T1 = AT1->getElementType();
     T2 = AT2->getElementType();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D87566: [... Mark de Wever via Phabricator via cfe-commits

Reply via email to