]> granicus.if.org Git - clang/commitdiff
PR20844: If we fail to list-initialize a reference, map to the referenced type
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 4 Sep 2014 22:13:39 +0000 (22:13 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 4 Sep 2014 22:13:39 +0000 (22:13 +0000)
before retrying the initialization to produce diagnostics. Otherwise, we may
fail to produce any diagnostics, and silently produce invalid AST in a -Asserts
build. Also add a note to this codepath to make it more clear why we were
trying to create a temporary.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@217197 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaInit.cpp
test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp
test/SemaCXX/cxx0x-initializer-references.cpp
test/SemaCXX/explicit.cpp

index 600c5a3a8194420557c0131eab44b4d31402defd..e26374c8af0a6ef7157efbe5523497ef41291e36 100644 (file)
@@ -1517,6 +1517,9 @@ def note_block_var_fixit_add_initialization : Note<
 def note_in_omitted_aggregate_initializer : Note<
   "in implicit initialization of %select{array element %1|field %1}0 "
   "with omitted initializer">;
+def note_in_reference_temporary_list_initializer : Note<
+  "in initialization of temporary of type %0 created to "
+  "list-initialize this reference">;
 def note_var_fixit_add_initialization : Note<
   "initialize the variable %0 to silence this warning">;
 def note_uninit_fixit_remove_cond : Note<
index 326bfc90875ad39d09ad72a185e28071543f0d3f..7a2fa08e28d1f34ef1e07b6e8b421130eb922ace 100644 (file)
@@ -6431,6 +6431,19 @@ static void diagnoseListInit(Sema &S, const InitializedEntity &Entity,
     return diagnoseListInit(S, HiddenArray, InitList);
   }
 
+  if (DestType->isReferenceType()) {
+    // A list-initialization failure for a reference means that we tried to
+    // create a temporary of the inner type (per [dcl.init.list]p3.6) and the
+    // inner initialization failed.
+    QualType T = DestType->getAs<ReferenceType>()->getPointeeType();
+    diagnoseListInit(S, InitializedEntity::InitializeTemporary(T), InitList);
+    SourceLocation Loc = InitList->getLocStart();
+    if (auto *D = Entity.getDecl())
+      Loc = D->getLocation();
+    S.Diag(Loc, diag::note_in_reference_temporary_list_initializer) << T;
+    return;
+  }
+
   InitListChecker DiagnoseInitList(S, Entity, InitList, DestType,
                                    /*VerifyOnly=*/false);
   assert(DiagnoseInitList.HadError() &&
index 971e0c11aff14a6a07f2e42e2c5afc8c3ead1f58..d7ffd0758a68a63f9b46b3c8017696af54010670 100644 (file)
@@ -4,7 +4,7 @@ namespace std {
   typedef decltype(sizeof(int)) size_t;
 
   template <typename E>
-  struct initializer_list // expected-note 2{{candidate}}
+  struct initializer_list
   {
     const E *p;
     size_t n;
@@ -112,15 +112,16 @@ namespace bullet8 {
 }
 
 namespace rdar13395022 {
-  struct MoveOnly {
-    MoveOnly(MoveOnly&&);
+  struct MoveOnly { // expected-note {{candidate}}
+    MoveOnly(MoveOnly&&); // expected-note 2{{copy constructor is implicitly deleted because}} expected-note {{candidate}}
   };
 
   void test(MoveOnly mo) {
-    // FIXME: These diagnostics are poor.
-    auto &&list1 = {mo}; // expected-error{{no viable conversion}}
-    MoveOnly (&&list2)[1] = {mo}; // expected-error{{no viable conversion}}
+    auto &&list1 = {mo}; // expected-error {{call to implicitly-deleted copy constructor}} expected-note {{in initialization of temporary of type 'std::initializer_list}}
+    MoveOnly (&&list2)[1] = {mo}; // expected-error {{call to implicitly-deleted copy constructor}} expected-note {{in initialization of temporary of type 'rdar13395022::MoveOnly [1]'}}
     std::initializer_list<MoveOnly> &&list3 = {};
-    MoveOnly (&&list4)[1] = {}; // expected-error{{uninitialized}}
+    MoveOnly (&&list4)[1] = {}; // expected-error {{no matching constructor}}
+    // expected-note@-1 {{in implicit initialization of array element 0 with omitted initializer}}
+    // expected-note@-2 {{in initialization of temporary of type 'rdar13395022::MoveOnly [1]' created to list-initialize this reference}}
   }
 }
index 9096c8a1c2d55704882f78c0e2c7f53237784a7c..d1a9ed30076f36988cb712fd0349188ff01cbddb 100644 (file)
@@ -118,3 +118,9 @@ namespace inner_init {
   F f2 { { 0 } }; // expected-error {{chosen constructor is explicit}}
   F f3 { { { 0 } } }; // expected-error {{chosen constructor is explicit}}
 }
+
+namespace PR20844 {
+  struct A {};
+  struct B { operator A&(); } b;
+  A &a{b}; // expected-error {{excess elements}} expected-note {{in initialization of temporary of type 'PR20844::A'}}
+}
index aa28bd85af4655e60f76e75797794a6eea9566ef..155141c058c48aa612e082f3f280bad2a1c44867 100644 (file)
@@ -86,7 +86,7 @@ namespace Conversion {
     // Y is an aggregate, so aggregate-initialization is performed and the
     // conversion function is not considered.
     const Y y10{z}; // expected-error {{excess elements}}
-    const Y& y11{z}; // expected-error {{no viable conversion from 'Z' to 'const Y'}}
+    const Y& y11{z}; // expected-error {{excess elements}} expected-note {{in initialization of temporary of type 'const Y'}}
     const int& y12{z};
 
     // X is not an aggregate, so constructors are considered.