Anastasia created this revision.
Anastasia added a reviewer: rjmccall.
Herald added a subscriber: ebevhan.

When we diagnose `static_cast` we should prevent accidental address space 
conversions unless the conversion is safe (i.e. converting to an address space 
that is a super set is safe!).

Some more details are explained in this RFC: 
http://lists.llvm.org/pipermail/cfe-dev/2018-December/060546.html

This patch also changes diagnostic to use Qualifiers print method.


https://reviews.llvm.org/D58060

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaInit.cpp
  test/SemaCXX/err_reference_bind_drops_quals.cpp
  test/SemaOpenCLCXX/address-space-castoperators.cpp

Index: test/SemaOpenCLCXX/address-space-castoperators.cpp
===================================================================
--- /dev/null
+++ test/SemaOpenCLCXX/address-space-castoperators.cpp
@@ -0,0 +1,17 @@
+//RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -pedantic -verify
+
+void test_ref(int &gen, __global const int& glob){
+static_cast<__global int&>(gen); // expected-error{{binding value of type '__generic int' to reference to type '__global int' changes address space}}
+static_cast<__global const int&>(gen); //expected-error{{binding value of type '__generic int' to reference to type 'const __global int' changes address space}}
+static_cast<__global int&>(glob); //expected-error{{binding value of type 'const __global int' to reference to type '__global int' drops 'const' qualifier}}
+static_cast<__local int&>(glob); //expected-error{{binding value of type 'const __global int' to reference to type '__local int' changes address space}}
+static_cast<__generic const int&>(glob); //expected-warning{{expression result unused}}
+}
+
+void test_ptr(int *gen, __global const int* glob){
+ static_cast<__global int*>(gen); // expected-error{{static_cast from '__generic int *' to '__global int *' is not allowed}}
+ static_cast<__global const int*>(gen); //expected-error{{static_cast from '__generic int *' to 'const __global int *' is not allowed}}
+ static_cast<__global int*>(glob); //expected-error{{static_cast from 'const __global int *' to '__global int *' is not allowed}}
+ static_cast<__local int*>(glob); //expected-error{{static_cast from 'const __global int *' to '__local int *' is not allowed}}
+ static_cast<__generic const int*>(glob); //expected-warning{{expression result unused}}
+}
Index: test/SemaCXX/err_reference_bind_drops_quals.cpp
===================================================================
--- test/SemaCXX/err_reference_bind_drops_quals.cpp
+++ test/SemaCXX/err_reference_bind_drops_quals.cpp
@@ -7,30 +7,30 @@
            const restrict volatile ptr crvp) {
   ptr& p1 = p;
   ptr& p2 = cp; // expected-error {{drops 'const' qualifier}}
-  ptr& p3 = rp; // expected-error {{drops 'restrict' qualifier}}
-  ptr& p4 = crp; // expected-error {{drops 'const' and 'restrict' qualifiers}}
+  ptr& p3 = rp; // expected-error {{drops '__restrict' qualifier}}
+  ptr& p4 = crp; // expected-error {{drops 'const __restrict' qualifiers}}
   ptr& p5 = vp; // expected-error {{drops 'volatile' qualifier}}
-  ptr& p6 = cvp; // expected-error {{drops 'const' and 'volatile' qualifiers}}
-  ptr& p7 = rvp; // expected-error {{drops 'restrict' and 'volatile' qualifiers}}
-  ptr& p8 = crvp; // expected-error {{drops 'const', 'restrict', and 'volatile' qualifiers}}
+  ptr& p6 = cvp; // expected-error {{drops 'const volatile' qualifiers}}
+  ptr& p7 = rvp; // expected-error {{drops 'volatile __restrict' qualifiers}}
+  ptr& p8 = crvp; // expected-error {{drops 'const volatile __restrict' qualifiers}}
 
   const ptr& cp1 = p;
   const ptr& cp2 = cp;
-  const ptr& cp3 = rp; // expected-error {{drops 'restrict' qualifier}}
-  const ptr& cp4 = crp; // expected-error {{drops 'restrict' qualifier}}
+  const ptr& cp3 = rp; // expected-error {{drops '__restrict' qualifier}}
+  const ptr& cp4 = crp; // expected-error {{drops '__restrict' qualifier}}
   const ptr& cp5 = vp; // expected-error {{drops 'volatile' qualifier}}
   const ptr& cp6 = cvp; // expected-error {{drops 'volatile' qualifier}}
-  const ptr& cp7 = rvp; // expected-error {{drops 'restrict' and 'volatile' qualifiers}}
-  const ptr& cp8 = crvp; // expected-error {{drops 'restrict' and 'volatile' qualifiers}}
+  const ptr& cp7 = rvp; // expected-error {{drops 'volatile __restrict' qualifiers}}
+  const ptr& cp8 = crvp; // expected-error {{drops 'volatile __restrict' qualifiers}}
 
   const volatile ptr& cvp1 = p;
   const volatile ptr& cvp2 = cp;
-  const volatile ptr& cvp3 = rp; // expected-error {{drops 'restrict' qualifier}}
-  const volatile ptr& cvp4 = crp; // expected-error {{drops 'restrict' qualifier}}
+  const volatile ptr& cvp3 = rp; // expected-error {{drops '__restrict' qualifier}}
+  const volatile ptr& cvp4 = crp; // expected-error {{drops '__restrict' qualifier}}
   const volatile ptr& cvp5 = vp;
   const volatile ptr& cvp6 = cvp;
-  const volatile ptr& cvp7 = rvp; // expected-error {{drops 'restrict' qualifier}}
-  const volatile ptr& cvp8 = crvp; // expected-error {{drops 'restrict' qualifier}}
+  const volatile ptr& cvp7 = rvp; // expected-error {{drops '__restrict' qualifier}}
+  const volatile ptr& cvp8 = crvp; // expected-error {{drops '__restrict' qualifier}}
 
   const restrict volatile ptr& crvp1 = p;
   const restrict volatile ptr& crvp2 = cp;
Index: lib/Sema/SemaInit.cpp
===================================================================
--- lib/Sema/SemaInit.cpp
+++ lib/Sema/SemaInit.cpp
@@ -4596,7 +4596,9 @@
   //     - 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())) {
+  if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile() &&
+      // addr space must be a superset.
+      T1Quals.isAddressSpaceSupersetOf(T2Quals))) {
     if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy)
       Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
     else if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
@@ -8439,11 +8441,18 @@
     Qualifiers DroppedQualifiers =
         SourceType.getQualifiers() - NonRefType.getQualifiers();
 
-    S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
-      << SourceType
-      << NonRefType
-      << DroppedQualifiers.getCVRQualifiers()
-      << Args[0]->getSourceRange();
+    if (DroppedQualifiers.hasAddressSpace())
+      S.Diag(Kind.getLocation(), diag::err_reference_bind_changes_addr_space)
+        << SourceType
+        << NonRefType
+        << Args[0]->getSourceRange();
+    else
+      S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
+        << SourceType
+        << NonRefType
+        << Qualifiers::fromCVRMask(DroppedQualifiers.getCVRQualifiers())
+        << DroppedQualifiers.getCVRQualifiers()
+        << Args[0]->getSourceRange();
     break;
   }
 
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -1824,9 +1824,10 @@
   "cannot bind to a value of unrelated type}1,2">;
 def err_reference_bind_drops_quals : Error<
   "binding value %diff{of type $ to reference to type $|to reference}0,1 "
-  "drops %select{<<ERROR>>|'const'|'restrict'|'const' and 'restrict'|"
-  "'volatile'|'const' and 'volatile'|'restrict' and 'volatile'|"
-  "'const', 'restrict', and 'volatile'}2 qualifier%plural{1:|2:|4:|:s}2">;
+  "drops %2 qualifier%plural{1:|2:|4:|:s}3">;
+def err_reference_bind_changes_addr_space : Error<
+  "binding value %diff{of type $ to reference to type $|to reference}0,1 "
+  "changes address space">;
 def err_reference_bind_failed : Error<
   "reference %diff{to type $ could not bind to an %select{rvalue|lvalue}1 of "
   "type $|could not bind to %select{rvalue|lvalue}1 of incompatible type}0,2">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to