Richard,
here's the reference-cast case of the unrelated hierarchy patch I recently created for ptr-to-class (http://llvm.org/bugs/show_bug.cgi?id=17456). I had a bit of a struggle coming up with a nicely worded diagnostic. This now produces:

17456-2.cc:6:10: error: non-const lvalue reference to class 'B' cannot bind to a value of class 'A', which is not related by inheritance
  return static_cast<B&>(arg);
         ^               ~~~
when the src and target reference types are classes. It also notes if either is incomplete.

ok?

nathan
Index: src/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- src/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td	(revision 228403)
+++ src/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td	(working copy)
@@ -1470,6 +1470,10 @@ def err_lvalue_reference_bind_to_unrelat
   "%select{non-const|volatile}0 lvalue reference "
   "%diff{to type $ cannot bind to a value of unrelated type $|"
   "cannot bind to a value of unrelated type}1,2">;
+def err_lvalue_reference_bind_to_unrelated_class : Error<
+  "%select{non-const|volatile}0 lvalue reference "
+  "%diff{to class $ cannot bind to a value of class $, which is not related by inheritance|"
+  "cannot bind to a value of class type that is not related by inheritance}1,2">;
 def err_reference_bind_drops_quals : Error<
   "binding of reference %diff{to type $ to a value of type $ drops qualifiers|"
   "drops qualifiers}0,1">;
Index: src/tools/clang/lib/Sema/SemaInit.cpp
===================================================================
--- src/tools/clang/lib/Sema/SemaInit.cpp	(revision 228403)
+++ src/tools/clang/lib/Sema/SemaInit.cpp	(working copy)
@@ -6646,14 +6646,32 @@ bool InitializationSequence::Diagnose(Se
     // Intentional fallthrough
 
   case FK_NonConstLValueReferenceBindingToUnrelated:
-    S.Diag(Kind.getLocation(),
-           Failure == FK_NonConstLValueReferenceBindingToTemporary
+    {
+      auto DestNonRef = DestType.getNonReferenceType();
+      auto SrcType = Args[0]->getType();
+      auto DestRec = DestNonRef->getAs<RecordType>();
+      auto SrcRec = SrcType->getAs<RecordType>();
+      S.Diag(Kind.getLocation(),
+             Failure == FK_NonConstLValueReferenceBindingToTemporary
              ? diag::err_lvalue_reference_bind_to_temporary
+             : DestRec && SrcRec
+             ? diag::err_lvalue_reference_bind_to_unrelated_class
              : diag::err_lvalue_reference_bind_to_unrelated)
-      << DestType.getNonReferenceType().isVolatileQualified()
-      << DestType.getNonReferenceType()
-      << Args[0]->getType()
-      << Args[0]->getSourceRange();
+        << DestNonRef.isVolatileQualified() << DestNonRef
+        << SrcType << Args[0]->getSourceRange();
+      if (SrcRec) {
+        auto SrcDecl = SrcRec->getAsCXXRecordDecl();
+        if (!SrcDecl->isCompleteDefinition())
+          S.Diag(SrcDecl->getLocation(), diag::note_type_incomplete)
+            << SrcDecl->getDeclName();
+      }
+      if (DestRec) {
+        auto DestDecl = DestRec->getAsCXXRecordDecl();
+        if (!DestDecl->isCompleteDefinition())
+          S.Diag(DestDecl->getLocation(), diag::note_type_incomplete)
+            << DestDecl->getDeclName();
+      }
+    }
     break;
 
   case FK_RValueReferenceBindingToLValue:
Index: src/tools/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp
===================================================================
--- src/tools/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp	(revision 228403)
+++ src/tools/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp	(working copy)
@@ -51,7 +51,7 @@ void bind_lvalue_to_lvalue(Base b, Deriv
   Base &br1 = b;
   Base &br2 = d;
   Derived &dr1 = d;
-  Derived &dr2 = b; // expected-error{{non-const lvalue reference to type 'Derived' cannot bind to a value of unrelated type 'Base'}}
+  Derived &dr2 = b; // expected-error{{non-const lvalue reference to class 'Derived' cannot bind to a value of class 'Base', which is not related by inheritance}}
   Base &br3 = bc; // expected-error{{drops qualifiers}}
   Base &br4 = dc; // expected-error{{drops qualifiers}}
   Base &br5 = diamond; // expected-error{{ambiguous conversion from derived class 'Diamond' to base class 'Base':}}
@@ -83,8 +83,8 @@ void bind_lvalue_to_rvalue() {
 }
 
 void bind_lvalue_to_unrelated(Unrelated ur) {
-  Base &br1 = ur; // expected-error{{non-const lvalue reference to type 'Base' cannot bind to a value of unrelated type 'Unrelated'}}
-  const volatile Base &br2 = ur; // expected-error{{volatile lvalue reference to type 'const volatile Base' cannot bind to a value of unrelated type 'Unrelated'}}
+  Base &br1 = ur; // expected-error{{non-const lvalue reference to class 'Base' cannot bind to a value of class 'Unrelated', which is not related by inheritance}}
+  const volatile Base &br2 = ur; // expected-error{{volatile lvalue reference to class 'const volatile Base' cannot bind to a value of class 'Unrelated', which is not related by inheritance}}
 }
 
 void bind_lvalue_to_conv_lvalue() {
Index: src/tools/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p9.cpp
===================================================================
Index: src/tools/clang/test/Misc/diag-template-diffing-color.cpp
===================================================================
--- src/tools/clang/test/Misc/diag-template-diffing-color.cpp	(revision 228403)
+++ src/tools/clang/test/Misc/diag-template-diffing-color.cpp	(working copy)
@@ -13,8 +13,8 @@ int main() {
 
 foo<int> A;
 foo<double> &B = A;
-// CHECK: {{.*}}non-const lvalue reference to type 'foo<[[CYAN]]double[[RESET]][[BOLD:.\[1m]]>' cannot bind to a value of unrelated type 'foo<[[CYAN]]int[[RESET]][[BOLD]]>'[[RESET]]
-// TREE: non-const lvalue reference cannot bind to a value of unrelated type
+// CHECK: {{.*}}non-const lvalue reference to class 'foo<[[CYAN]]double[[RESET]][[BOLD:.\[1m]]>' cannot bind to a value of class 'foo<[[CYAN]]int[[RESET]][[BOLD]]>', which is not related by inheritance[[RESET]]
+// TREE: non-const lvalue reference cannot bind to a value of class type that is not related by inheritance
 // TREE:   foo<
 // TREE:     {{\[}}[[CYAN]]double[[RESET]][[BOLD:.\[1m]] != [[CYAN]]int[[RESET]][[BOLD]]]>[[RESET]]
 
Index: src/tools/clang/test/SemaCXX/rval-references.cpp
===================================================================
--- src/tools/clang/test/SemaCXX/rval-references.cpp	(revision 228403)
+++ src/tools/clang/test/SemaCXX/rval-references.cpp	(working copy)
@@ -48,7 +48,7 @@ void f() {
 
   conv_to_not_int_rvalue cnir;
   not_int &&ni4 = cnir;
-  not_int &ni5 = cnir; // expected-error{{non-const lvalue reference to type 'not_int' cannot bind to a value of unrelated type 'conv_to_not_int_rvalue'}}
+  not_int &ni5 = cnir; // expected-error{{non-const lvalue reference to class 'not_int' cannot bind to a value of class 'conv_to_not_int_rvalue', which is not related by inheritance}}
   not_int &&ni6 = conv_to_not_int_rvalue();
 
   fun_type &&fun_ref = fun; // works because functions are special
Index: src/tools/clang/test/SemaCXX/static-cast.cpp
===================================================================
--- src/tools/clang/test/SemaCXX/static-cast.cpp	(revision 228403)
+++ src/tools/clang/test/SemaCXX/static-cast.cpp	(working copy)
@@ -93,7 +93,7 @@ void t_529_5_8()
   (void)static_cast<H*>((A*)0); // expected-error {{ambiguous cast from base 'A' to derived 'H':\n    struct A -> struct B -> struct G1 -> struct H\n    struct A -> struct B -> struct G2 -> struct H}}
   (void)static_cast<H&>(*((A*)0)); // expected-error {{ambiguous cast from base 'A' to derived 'H':\n    struct A -> struct B -> struct G1 -> struct H\n    struct A -> struct B -> struct G2 -> struct H}}
   (void)static_cast<E*>((B*)0); // expected-error {{static_cast from 'B *' to 'E *', which are not related by inheritance, is not allowed}}
-  (void)static_cast<E&>(*((B*)0)); // expected-error {{non-const lvalue reference to type 'E' cannot bind to a value of unrelated type 'B'}}
+  (void)static_cast<E&>(*((B*)0)); // expected-error {{non-const lvalue reference to class 'E' cannot bind to a value of class 'B', which is not related by inheritance}}
 
 
   (void)static_cast<E*>((J*)0); // expected-error {{static_cast from 'J *' to 'E *', which are not related by inheritance, is not allowed}}
Index: src/tools/clang/test/SemaTemplate/derived.cpp
===================================================================
--- src/tools/clang/test/SemaTemplate/derived.cpp	(revision 228403)
+++ src/tools/clang/test/SemaTemplate/derived.cpp	(working copy)
@@ -25,7 +25,7 @@ namespace rdar13267210 {
 
     void AddSourceLocation(A<long> &R); // expected-note{{passing argument to parameter 'R' here}}
     void AddTemplateKWAndArgsInfo() {
-      AddSourceLocation(Record); // expected-error{{non-const lvalue reference to type}}
+      AddSourceLocation(Record); // expected-error{{non-const lvalue reference to class 'A<long>' cannot bind to a value of class 'C<long, 64>', which is not related by inheritance}}
     }
   };
 }
# svn diff src/tools/clang/tools/extra
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to