[PATCH] D87561: [Sema] List conversion validate character array

Mark de Wever via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Sat Sep 12 09:44:53 PDT 2020


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

The function `TryListConversion` didn't properly validate the following part of the standard:

  Otherwise, if the parameter type is a character array [... ]
  and the initializer list has a single element that is an
  appropriately-typed string literal (8.5.2 [dcl.init.string]), the
  implicit conversion sequence is the identity conversion.

This caused the following call to `f()` to be ambiguous.

  void f(int(&&)[1]);
  void f(unsigned(&&)[1]);
  
  void g(unsigned i) {
    f({i});
  }

This issue only occurrs when the initializer list had one element.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D87561

Files:
  clang/lib/Sema/SemaOverload.cpp
  clang/test/CXX/drs/dr14xx.cpp


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,31 @@
     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 wchar_t[4]);
+  void f(const char16_t[4]);
+  void f(const char32_t[4]);
+  void g() {
+    f({"abc"});     // expected-warning {{braces around scalar initializer}}
+    f({L"abc"});    // expected-warning {{braces around scalar initializer}}
+    f({uR"(abc)"}); // expected-warning {{braces around scalar initializer}}
+    f({UR"(abc)"}); // expected-warning {{braces around scalar initializer}}
+  }
+  } // 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,12 +4984,12 @@
                                      InOverloadResolution,
                                      AllowObjCWritebackConversion);
     }
-    // FIXME: Check the other conditions here: array of character type,
-    // initializer is a string literal.
-    if (ToType->isArrayType()) {
+
+    if (ToType->isArrayType() && ToType->isCharType() &&
+        isa<StringLiteral>(From->getInit(0))) {
       InitializedEntity Entity =
-        InitializedEntity::InitializeParameter(S.Context, ToType,
-                                               /*Consumed=*/false);
+          InitializedEntity::InitializeParameter(S.Context, ToType,
+                                                 /*Consumed=*/false);
       if (S.CanPerformCopyInitialization(Entity, From)) {
         Result.setStandard();
         Result.Standard.setAsIdentityConversion();


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D87561.291399.patch
Type: text/x-patch
Size: 2690 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200912/49b88db9/attachment.bin>


More information about the cfe-commits mailing list