]> granicus.if.org Git - clang/commitdiff
[Sema] Fix diagnostic for addr spaces in reference binding
authorAnastasia Stulova <anastasia.stulova@arm.com>
Fri, 21 Jun 2019 11:36:15 +0000 (11:36 +0000)
committerAnastasia Stulova <anastasia.stulova@arm.com>
Fri, 21 Jun 2019 11:36:15 +0000 (11:36 +0000)
Extend reference binding behavior to account for address spaces.

Differential Revision: https://reviews.llvm.org/D62914

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaInit.cpp
test/SemaOpenCLCXX/address-space-references.cl

index c8674d781c9b417382c344676ff4a48879c316a6..2abf7d73c1e52ba99aa4391d1751a33bb38c58fa 100644 (file)
@@ -1852,7 +1852,7 @@ def err_lvalue_reference_bind_to_unrelated : Error<
   "cannot bind to a value of unrelated type}1,2">;
 def err_reference_bind_drops_quals : Error<
   "binding reference %diff{of type $ to value of type $|to value}0,1 "
-  "drops %2 qualifier%plural{1:|2:|4:|:s}3">;
+  "%select{drops %3 qualifier%plural{1:|2:|4:|:s}4|changes address space}2">;
 def err_reference_bind_failed : Error<
   "reference %diff{to %select{type|incomplete type}1 $ could not bind to an "
   "%select{rvalue|lvalue}2 of type $|could not bind to %select{rvalue|lvalue}2 of "
index 128809175e247dcb22f647382db10509119f6ce3..d2a4a0979d15a5a7d57793c0c9a2f10e18935c2d 100644 (file)
@@ -4631,7 +4631,10 @@ static void TryReferenceInitializationCore(Sema &S,
   //     - Otherwise, the reference shall be an lvalue reference to a
   //       non-volatile const type (i.e., cv1 shall be const), or the reference
   //       shall be an rvalue reference.
-  if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile())) {
+  //       For address spaces, we interpret this to mean that an addr space
+  //       of a reference "cv1 T1" is a superset of addr space of "cv2 T2".
+  if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile() &&
+                       T1Quals.isAddressSpaceSupersetOf(T2Quals))) {
     if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy)
       Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
     else if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
@@ -4640,7 +4643,10 @@ static void TryReferenceInitializationCore(Sema &S,
                                   ConvOvlResult);
     else if (!InitCategory.isLValue())
       Sequence.SetFailed(
-          InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
+          T1Quals.isAddressSpaceSupersetOf(T2Quals)
+              ? InitializationSequence::
+                    FK_NonConstLValueReferenceBindingToTemporary
+              : InitializationSequence::FK_ReferenceInitDropsQualifiers);
     else {
       InitializationSequence::FailureKind FK;
       switch (RefRelationship) {
@@ -8521,12 +8527,16 @@ bool InitializationSequence::Diagnose(Sema &S,
     Qualifiers DroppedQualifiers =
         SourceType.getQualifiers() - NonRefType.getQualifiers();
 
-    S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
-      << NonRefType
-      << SourceType
-      << Qualifiers::fromCVRMask(DroppedQualifiers.getCVRQualifiers())
-      << DroppedQualifiers.getCVRQualifiers()
-      << Args[0]->getSourceRange();
+    if (!NonRefType.getQualifiers().isAddressSpaceSupersetOf(
+            SourceType.getQualifiers()))
+      S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
+          << NonRefType << SourceType << 1 /*addr space*/
+          << Args[0]->getSourceRange();
+    else
+      S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
+          << NonRefType << SourceType << 0 /*cv quals*/
+          << Qualifiers::fromCVRMask(DroppedQualifiers.getCVRQualifiers())
+          << DroppedQualifiers.getCVRQualifiers() << Args[0]->getSourceRange();
     break;
   }
 
index c359bbd713a4ac09f0410c3cfe6a86c5ff506895..851d3023df29b0cb74a1eccafbbf0e991f67ff23 100644 (file)
@@ -3,3 +3,13 @@
 __global const int& f(__global float &ref) {
   return ref; // expected-error{{reference of type 'const __global int &' cannot bind to a temporary object because of address space mismatch}}
 }
+
+int bar(const __global unsigned int &i); // expected-note{{passing argument to parameter 'i' here}}
+//FIXME: With the overload below the call should be resolved
+// successfully. However, current overload resolution logic
+// can't detect this case and therefore fails.
+int bar(const unsigned int &i);
+
+void foo() {
+  bar(1) // expected-error{{binding reference of type 'const __global unsigned int' to value of type 'int' changes address space}}
+}