Mordante updated this revision to Diff 294556.
Mordante added a comment.

Addresses the review comments.
Adds an extra test case to test whether the proper overload is called. The 
proper overload is a bit of a surprise so when the expected behaviour changes 
the overload test can be adjusted.


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

https://reviews.llvm.org/D87561

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaInit.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/CXX/drs/dr14xx.cpp
  clang/test/SemaCXX/overload-array-size.cpp
  clang/test/SemaObjCXX/overload.mm

Index: clang/test/SemaObjCXX/overload.mm
===================================================================
--- clang/test/SemaObjCXX/overload.mm
+++ clang/test/SemaObjCXX/overload.mm
@@ -201,3 +201,17 @@
 }
 
 }
+
+namespace StringLiterals {
+void f(const char(&&)[5]);
+void f(const wchar_t(&&)[5]);
+void f(const char16_t(&&)[5]);
+void f(const char32_t(&&)[5]);
+void g() {
+  f({"abc"});
+  f({(((@encode(int))))});
+  f({L"abc"});
+  f({uR"(abc)"});
+  f({(UR"(abc)")});
+}
+} // namespace StringLiterals
Index: clang/test/SemaCXX/overload-array-size.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/overload-array-size.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 %s -ast-dump | FileCheck %s
+
+// When the array size is 4 the call will attempt to bind an lvalue to an
+// rvalue and fail. Therfore #2 will be called. (rsmith will bring this issue
+// to CWG)
+void f(const char(&&)[4]); // #1
+void f(const char(&&)[5]); // #2
+void g() {
+  f({"abc"});
+  // CHECK: ExprWithCleanups {{.*}} <line:[[@LINE-1]]:{{.*}}> 'void'
+  // CHECK-NEXT: CallExpr
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(const char (&&)[5])'
+}
Index: clang/test/CXX/drs/dr14xx.cpp
===================================================================
--- clang/test/CXX/drs/dr14xx.cpp
+++ clang/test/CXX/drs/dr14xx.cpp
@@ -334,6 +334,22 @@
 
     X x;
     X x2{x};
+
+    void f1(int);
+    void f1(std::initializer_list<long>);
+    void g1() { f1({42}); }
+
+    template <class T, class U>
+    struct Pair {
+      Pair(T, U);
+    };
+    struct String {
+      String(const char *);
+    };
+
+    void f2(Pair<const char *, const char *>);
+    void f2(std::initializer_list<String>);
+    void g2() { f2({"foo", "bar"}); }
   } // dr_example
 
   namespace nonaggregate {
@@ -379,6 +395,43 @@
     struct Value { Value(Pair); Value(TwoPairs); };
     void f() { Value{{{1,2},{3,4}}}; }
   }
+  namespace NonAmbiguous {
+  // The original implementation made this case ambigious due to the special
+  // handling of one element initialization lists.
+  void f(int(&&)[1]);
+  void f(unsigned(&&)[1]);
+
+  void g(unsigned i) {
+    f({i});
+  }
+  } // namespace NonAmbiguous
+
+#if __cplusplus >= 201103L
+  namespace StringLiterals {
+  void f(const char(&&)[4]);
+  void f(const char(&&)[5]);
+  void f(const wchar_t(&&)[4]);
+  void f(const wchar_t(&&)[5]);
+#if __cplusplus >= 202002L
+  void f(const char8_t(&&)[4]);
+  void f(const char8_t(&&)[5]);
+#endif
+  void f(const char16_t(&&)[4]);
+  void f(const char16_t(&&)[5]);
+  void f(const char32_t(&&)[4]);
+  void f(const char32_t(&&)[5]);
+  void g() {
+    f({"abc"});
+    f({((("abc")))});
+    f({L"abc"});
+#if __cplusplus >= 202002L
+    f({u8"abc"});
+#endif
+    f({uR"(abc)"});
+    f({(UR"(abc)")});
+  }
+  } // namespace StringLiterals
+#endif
 } // dr1467
 
 namespace dr1490 {  // dr1490: 3.7 c++11
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -4984,20 +4984,20 @@
                                      InOverloadResolution,
                                      AllowObjCWritebackConversion);
     }
-    // FIXME: Check the other conditions here: array of character type,
-    // initializer is a string literal.
-    if (ToType->isArrayType()) {
-      InitializedEntity Entity =
-        InitializedEntity::InitializeParameter(S.Context, ToType,
-                                               /*Consumed=*/false);
-      if (S.CanPerformCopyInitialization(Entity, From)) {
-        Result.setStandard();
-        Result.Standard.setAsIdentityConversion();
-        Result.Standard.setFromType(ToType);
-        Result.Standard.setAllToTypes(ToType);
-        return Result;
+
+    if (const auto *AT = S.Context.getAsArrayType(ToType))
+      if (S.IsStringInit(From->getInit(0), AT)) {
+        InitializedEntity Entity =
+          InitializedEntity::InitializeParameter(S.Context, ToType,
+                                                 /*Consumed=*/false);
+        if (S.CanPerformCopyInitialization(Entity, From)) {
+          Result.setStandard();
+          Result.Standard.setAsIdentityConversion();
+          Result.Standard.setFromType(ToType);
+          Result.Standard.setAllToTypes(ToType);
+          return Result;
+        }
       }
-    }
   }
 
   // C++14 [over.ics.list]p2: Otherwise, if the parameter type [...] (below).
Index: clang/lib/Sema/SemaInit.cpp
===================================================================
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -3112,6 +3112,10 @@
   return !Check.HadError();
 }
 
+bool Sema::IsStringInit(Expr *Init, const ArrayType *AT) {
+  return ::IsStringInit(Init, AT, Context) == SIF_None;
+}
+
 /// Check that the given Index expression is a valid array designator
 /// value. This is essentially just a wrapper around
 /// VerifyIntegerConstantExpression that also checks for negative values
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -3188,6 +3188,8 @@
   bool CanPerformAggregateInitializationForOverloadResolution(
       const InitializedEntity &Entity, InitListExpr *From);
 
+  bool IsStringInit(Expr *Init, const ArrayType *AT);
+
   bool CanPerformCopyInitialization(const InitializedEntity &Entity,
                                     ExprResult Init);
   ExprResult PerformCopyInitialization(const InitializedEntity &Entity,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to