<div dir="ltr">Hello Anastasia,<br><br>Added test fails on one of our new builders:<br><br>Failing Tests (1):<br>    Clang :: SemaOpenCL/<a href="http://overload_addrspace_resolution.cl">overload_addrspace_resolution.cl</a><br><br><a href="http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/23/steps/test-check-all/logs/stdio">http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/23/steps/test-check-all/logs/stdio</a><br><br>Please have a look at it?<br><br>Thanks<br><br>Galina<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Mar 10, 2017 at 7:23 AM, Anastasia Stulova via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: stulova<br>
Date: Fri Mar 10 09:23:07 2017<br>
New Revision: 297468<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=297468&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=297468&view=rev</a><br>
Log:<br>
[OpenCL] Fix type compatibility check and generic AS mangling.<br>
<br>
1. Reimplemented conditional operator so that it checks<br>
compatibility of unqualified pointees of the 2nd and<br>
the 3rd operands (C99, OpenCL v2.0 6.5.15).<br>
<br>
Define QualTypes compatibility for OpenCL as following:<br>
<br>
   - corresponding types are compatible (C99 6.7.3)<br>
   - CVR-qualifiers are equal (C99 6.7.3)<br>
   - address spaces are equal (implementation defined)<br>
<br>
2. Added generic address space to Itanium mangling.<br>
<br>
Review: D30037<br>
<br>
Patch by Dmitry Borisenkov!<br>
<br>
<br>
Added:<br>
    cfe/trunk/test/SemaOpenCL/<a href="http://overload_addrspace_resolution.cl" rel="noreferrer" target="_blank">over<wbr>load_addrspace_resolution.cl</a><br>
Modified:<br>
    cfe/trunk/lib/AST/ASTContext.<wbr>cpp<br>
    cfe/trunk/lib/AST/<wbr>ItaniumMangle.cpp<br>
    cfe/trunk/lib/Sema/SemaExpr.<wbr>cpp<br>
    cfe/trunk/test/SemaOpenCL/<a href="http://address-spaces-conversions-cl2.0.cl" rel="noreferrer" target="_blank">addr<wbr>ess-spaces-conversions-cl2.0.<wbr>cl</a><br>
<br>
Modified: cfe/trunk/lib/AST/ASTContext.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=297468&r1=297467&r2=297468&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>ASTContext.cpp?rev=297468&r1=<wbr>297467&r2=297468&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/AST/ASTContext.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/AST/ASTContext.<wbr>cpp Fri Mar 10 09:23:07 2017<br>
@@ -8066,15 +8066,6 @@ QualType ASTContext::mergeTypes(<wbr>QualType<br>
   Qualifiers LQuals = LHSCan.getLocalQualifiers();<br>
   Qualifiers RQuals = RHSCan.getLocalQualifiers();<br>
   if (LQuals != RQuals) {<br>
-    if (getLangOpts().OpenCL) {<br>
-      if (LHSCan.getUnqualifiedType() != RHSCan.getUnqualifiedType() ||<br>
-          LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers())<br>
-        return QualType();<br>
-      if (LQuals.<wbr>isAddressSpaceSupersetOf(<wbr>RQuals))<br>
-        return LHS;<br>
-      if (RQuals.<wbr>isAddressSpaceSupersetOf(<wbr>LQuals))<br>
-        return RHS;<br>
-    }<br>
     // If any of these qualifiers are different, we have a type<br>
     // mismatch.<br>
     if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() ||<br>
@@ -8200,6 +8191,20 @@ QualType ASTContext::mergeTypes(<wbr>QualType<br>
       LHSPointee = LHSPointee.getUnqualifiedType(<wbr>);<br>
       RHSPointee = RHSPointee.getUnqualifiedType(<wbr>);<br>
     }<br>
+    if (getLangOpts().OpenCL) {<br>
+      Qualifiers LHSPteeQual = LHSPointee.getQualifiers();<br>
+      Qualifiers RHSPteeQual = RHSPointee.getQualifiers();<br>
+      // Blocks can't be an expression in a ternary operator (OpenCL v2.0<br>
+      // 6.12.5) thus the following check is asymmetric.<br>
+      if (!LHSPteeQual.<wbr>isAddressSpaceSupersetOf(<wbr>RHSPteeQual))<br>
+        return QualType();<br>
+      LHSPteeQual.<wbr>removeAddressSpace();<br>
+      RHSPteeQual.<wbr>removeAddressSpace();<br>
+      LHSPointee =<br>
+          QualType(LHSPointee.<wbr>getTypePtr(), LHSPteeQual.getAsOpaqueValue()<wbr>);<br>
+      RHSPointee =<br>
+          QualType(RHSPointee.<wbr>getTypePtr(), RHSPteeQual.getAsOpaqueValue()<wbr>);<br>
+    }<br>
     QualType ResultType = mergeTypes(LHSPointee, RHSPointee, OfBlockPointer,<br>
                                      Unqualified);<br>
     if (ResultType.isNull()) return QualType();<br>
<br>
Modified: cfe/trunk/lib/AST/<wbr>ItaniumMangle.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=297468&r1=297467&r2=297468&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>ItaniumMangle.cpp?rev=297468&<wbr>r1=297467&r2=297468&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/AST/<wbr>ItaniumMangle.cpp (original)<br>
+++ cfe/trunk/lib/AST/<wbr>ItaniumMangle.cpp Fri Mar 10 09:23:07 2017<br>
@@ -2159,10 +2159,12 @@ void CXXNameMangler::<wbr>mangleQualifiers(Qu<br>
     } else {<br>
       switch (AS) {<br>
       default: llvm_unreachable("Not a language specific address space");<br>
-      //  <OpenCL-addrspace> ::= "CL" [ "global" | "local" | "constant" ]<br>
+      //  <OpenCL-addrspace> ::= "CL" [ "global" | "local" | "constant |<br>
+      //                                "generic" ]<br>
       case LangAS::opencl_global:   ASString = "CLglobal";   break;<br>
       case LangAS::opencl_local:    ASString = "CLlocal";    break;<br>
       case LangAS::opencl_constant: ASString = "CLconstant"; break;<br>
+      case LangAS::opencl_generic:  ASString = "CLgeneric";  break;<br>
       //  <CUDA-addrspace> ::= "CU" [ "device" | "constant" | "shared" ]<br>
       case LangAS::cuda_device:     ASString = "CUdevice";   break;<br>
       case LangAS::cuda_constant:   ASString = "CUconstant"; break;<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExpr.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=297468&r1=297467&r2=297468&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaExpr.cpp?rev=297468&r1=<wbr>297467&r2=297468&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/SemaExpr.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExpr.<wbr>cpp Fri Mar 10 09:23:07 2017<br>
@@ -6335,92 +6335,98 @@ static QualType checkConditionalPointerC<br>
   Qualifiers lhQual = lhptee.getQualifiers();<br>
   Qualifiers rhQual = rhptee.getQualifiers();<br>
<br>
+  unsigned ResultAddrSpace = 0;<br>
+  unsigned LAddrSpace = lhQual.getAddressSpace();<br>
+  unsigned RAddrSpace = rhQual.getAddressSpace();<br>
+  if (S.getLangOpts().OpenCL) {<br>
+    // OpenCL v1.1 s6.5 - Conversion between pointers to distinct address<br>
+    // spaces is disallowed.<br>
+    if (lhQual.<wbr>isAddressSpaceSupersetOf(<wbr>rhQual))<br>
+      ResultAddrSpace = LAddrSpace;<br>
+    else if (rhQual.<wbr>isAddressSpaceSupersetOf(<wbr>lhQual))<br>
+      ResultAddrSpace = RAddrSpace;<br>
+    else {<br>
+      S.Diag(Loc,<br>
+             diag::err_typecheck_op_on_<wbr>nonoverlapping_address_space_<wbr>pointers)<br>
+          << LHSTy << RHSTy << 2 << LHS.get()->getSourceRange()<br>
+          << RHS.get()->getSourceRange();<br>
+      return QualType();<br>
+    }<br>
+  }<br>
+<br>
   unsigned MergedCVRQual = lhQual.getCVRQualifiers() | rhQual.getCVRQualifiers();<br>
+  auto LHSCastKind = CK_BitCast, RHSCastKind = CK_BitCast;<br>
   lhQual.removeCVRQualifiers();<br>
   rhQual.removeCVRQualifiers();<br>
<br>
+  // OpenCL v2.0 specification doesn't extend compatibility of type qualifiers<br>
+  // (C99 6.7.3) for address spaces. We assume that the check should behave in<br>
+  // the same manner as it's defined for CVR qualifiers, so for OpenCL two<br>
+  // qual types are compatible iff<br>
+  //  * corresponded types are compatible<br>
+  //  * CVR qualifiers are equal<br>
+  //  * address spaces are equal<br>
+  // Thus for conditional operator we merge CVR and address space unqualified<br>
+  // pointees and if there is a composite type we return a pointer to it with<br>
+  // merged qualifiers.<br>
+  if (S.getLangOpts().OpenCL) {<br>
+    LHSCastKind = LAddrSpace == ResultAddrSpace<br>
+                      ? CK_BitCast<br>
+                      : CK_AddressSpaceConversion;<br>
+    RHSCastKind = RAddrSpace == ResultAddrSpace<br>
+                      ? CK_BitCast<br>
+                      : CK_AddressSpaceConversion;<br>
+    lhQual.removeAddressSpace();<br>
+    rhQual.removeAddressSpace();<br>
+  }<br>
+<br>
   lhptee = S.Context.getQualifiedType(<wbr>lhptee.getUnqualifiedType(), lhQual);<br>
   rhptee = S.Context.getQualifiedType(<wbr>rhptee.getUnqualifiedType(), rhQual);<br>
<br>
-  // For OpenCL:<br>
-  // 1. If LHS and RHS types match exactly and:<br>
-  //  (a) AS match => use standard C rules, no bitcast or addrspacecast<br>
-  //  (b) AS overlap => generate addrspacecast<br>
-  //  (c) AS don't overlap => give an error<br>
-  // 2. if LHS and RHS types don't match:<br>
-  //  (a) AS match => use standard C rules, generate bitcast<br>
-  //  (b) AS overlap => generate addrspacecast instead of bitcast<br>
-  //  (c) AS don't overlap => give an error<br>
-<br>
-  // For OpenCL, non-null composite type is returned only for cases 1a and 1b.<br>
   QualType CompositeTy = S.Context.mergeTypes(lhptee, rhptee);<br>
<br>
-  // OpenCL cases 1c, 2a, 2b, and 2c.<br>
   if (CompositeTy.isNull()) {<br>
     // In this situation, we assume void* type. No especially good<br>
     // reason, but this is what gcc does, and we do have to pick<br>
     // to get a consistent AST.<br>
     QualType incompatTy;<br>
-    if (S.getLangOpts().OpenCL) {<br>
-      // OpenCL v1.1 s6.5 - Conversion between pointers to distinct address<br>
-      // spaces is disallowed.<br>
-      unsigned ResultAddrSpace;<br>
-      if (lhQual.<wbr>isAddressSpaceSupersetOf(<wbr>rhQual)) {<br>
-        // Cases 2a and 2b.<br>
-        ResultAddrSpace = lhQual.getAddressSpace();<br>
-      } else if (rhQual.<wbr>isAddressSpaceSupersetOf(<wbr>lhQual)) {<br>
-        // Cases 2a and 2b.<br>
-        ResultAddrSpace = rhQual.getAddressSpace();<br>
-      } else {<br>
-        // Cases 1c and 2c.<br>
-        S.Diag(Loc,<br>
-               diag::err_typecheck_op_on_<wbr>nonoverlapping_address_space_<wbr>pointers)<br>
-            << LHSTy << RHSTy << 2 << LHS.get()->getSourceRange()<br>
-            << RHS.get()->getSourceRange();<br>
-        return QualType();<br>
-      }<br>
-<br>
-      // Continue handling cases 2a and 2b.<br>
-      incompatTy = S.Context.getPointerType(<br>
-          S.Context.<wbr>getAddrSpaceQualType(S.<wbr>Context.VoidTy, ResultAddrSpace));<br>
-      LHS = S.ImpCastExprToType(LHS.get(), incompatTy,<br>
-                                (lhQual.getAddressSpace() != ResultAddrSpace)<br>
-                                    ? CK_AddressSpaceConversion /* 2b */<br>
-                                    : CK_BitCast /* 2a */);<br>
-      RHS = S.ImpCastExprToType(RHS.get(), incompatTy,<br>
-                                (rhQual.getAddressSpace() != ResultAddrSpace)<br>
-                                    ? CK_AddressSpaceConversion /* 2b */<br>
-                                    : CK_BitCast /* 2a */);<br>
-    } else {<br>
-      S.Diag(Loc, diag::ext_typecheck_cond_<wbr>incompatible_pointers)<br>
-          << LHSTy << RHSTy << LHS.get()->getSourceRange()<br>
-          << RHS.get()->getSourceRange();<br>
-      incompatTy = S.Context.getPointerType(S.<wbr>Context.VoidTy);<br>
-      LHS = S.ImpCastExprToType(LHS.get(), incompatTy, CK_BitCast);<br>
-      RHS = S.ImpCastExprToType(RHS.get(), incompatTy, CK_BitCast);<br>
-    }<br>
+    incompatTy = S.Context.getPointerType(<br>
+        S.Context.<wbr>getAddrSpaceQualType(S.<wbr>Context.VoidTy, ResultAddrSpace));<br>
+    LHS = S.ImpCastExprToType(LHS.get(), incompatTy, LHSCastKind);<br>
+    RHS = S.ImpCastExprToType(RHS.get(), incompatTy, RHSCastKind);<br>
+    // FIXME: For OpenCL the warning emission and cast to void* leaves a room<br>
+    // for casts between types with incompatible address space qualifiers.<br>
+    // For the following code the compiler produces casts between global and<br>
+    // local address spaces of the corresponded innermost pointees:<br>
+    // local int *global *a;<br>
+    // global int *global *b;<br>
+    // a = (0 ? a : b); // see C99 6.5.16.1.p1.<br>
+    S.Diag(Loc, diag::ext_typecheck_cond_<wbr>incompatible_pointers)<br>
+        << LHSTy << RHSTy << LHS.get()->getSourceRange()<br>
+        << RHS.get()->getSourceRange();<br>
     return incompatTy;<br>
   }<br>
<br>
   // The pointer types are compatible.<br>
-  QualType ResultTy = CompositeTy.withCVRQualifiers(<wbr>MergedCVRQual);<br>
-  auto LHSCastKind = CK_BitCast, RHSCastKind = CK_BitCast;<br>
+  // In case of OpenCL ResultTy should have the address space qualifier<br>
+  // which is a superset of address spaces of both the 2nd and the 3rd<br>
+  // operands of the conditional operator.<br>
+  QualType ResultTy = [&, ResultAddrSpace]() {<br>
+    if (S.getLangOpts().OpenCL) {<br>
+      Qualifiers CompositeQuals = CompositeTy.getQualifiers();<br>
+      CompositeQuals.<wbr>setAddressSpace(<wbr>ResultAddrSpace);<br>
+      return S.Context<br>
+          .getQualifiedType(CompositeTy.<wbr>getUnqualifiedType(), CompositeQuals)<br>
+          .withCVRQualifiers(<wbr>MergedCVRQual);<br>
+    } else<br>
+      return CompositeTy.withCVRQualifiers(<wbr>MergedCVRQual);<br>
+  }();<br>
   if (IsBlockPointer)<br>
     ResultTy = S.Context.getBlockPointerType(<wbr>ResultTy);<br>
   else {<br>
-    // Cases 1a and 1b for OpenCL.<br>
-    auto ResultAddrSpace = ResultTy.getQualifiers().<wbr>getAddressSpace();<br>
-    LHSCastKind = lhQual.getAddressSpace() == ResultAddrSpace<br>
-                      ? CK_BitCast /* 1a */<br>
-                      : CK_AddressSpaceConversion /* 1b */;<br>
-    RHSCastKind = rhQual.getAddressSpace() == ResultAddrSpace<br>
-                      ? CK_BitCast /* 1a */<br>
-                      : CK_AddressSpaceConversion /* 1b */;<br>
     ResultTy = S.Context.getPointerType(<wbr>ResultTy);<br>
   }<br>
<br>
-  // For case 1a of OpenCL, S.ImpCastExprToType will not insert bitcast<br>
-  // if the target type does not change.<br>
   LHS = S.ImpCastExprToType(LHS.get(), ResultTy, LHSCastKind);<br>
   RHS = S.ImpCastExprToType(RHS.get(), ResultTy, RHSCastKind);<br>
   return ResultTy;<br>
@@ -7399,7 +7405,22 @@ checkBlockPointerTypesForAssig<wbr>nment(Sema<br>
   if (LQuals != RQuals)<br>
     ConvTy = Sema::<wbr>CompatiblePointerDiscardsQuali<wbr>fiers;<br>
<br>
-  if (!S.Context.<wbr>typesAreBlockPointerCompatible<wbr>(LHSType, RHSType))<br>
+  // FIXME: OpenCL doesn't define the exact compile time semantics for a block<br>
+  // assignment.<br>
+  // The current behavior is similar to C++ lambdas. A block might be<br>
+  // assigned to a variable iff its return type and parameters are compatible<br>
+  // (C99 6.2.7) with the corresponding return type and parameters of the LHS of<br>
+  // an assignment. Presumably it should behave in way that a function pointer<br>
+  // assignment does in C, so for each parameter and return type:<br>
+  //  * CVR and address space of LHS should be a superset of CVR and address<br>
+  //  space of RHS.<br>
+  //  * unqualified types should be compatible.<br>
+  if (S.getLangOpts().OpenCL) {<br>
+    if (!S.Context.<wbr>typesAreBlockPointerCompatible<wbr>(<br>
+            S.Context.getQualifiedType(<wbr>LHSType.getUnqualifiedType(), LQuals),<br>
+            S.Context.getQualifiedType(<wbr>RHSType.getUnqualifiedType(), RQuals)))<br>
+      return Sema::<wbr>IncompatibleBlockPointer;<br>
+  } else if (!S.Context.<wbr>typesAreBlockPointerCompatible<wbr>(LHSType, RHSType))<br>
     return Sema::<wbr>IncompatibleBlockPointer;<br>
<br>
   return ConvTy;<br>
<br>
Modified: cfe/trunk/test/SemaOpenCL/<a href="http://address-spaces-conversions-cl2.0.cl" rel="noreferrer" target="_blank">addr<wbr>ess-spaces-conversions-cl2.0.<wbr>cl</a><br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl?rev=297468&r1=297467&r2=297468&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>SemaOpenCL/address-spaces-<wbr>conversions-cl2.0.cl?rev=<wbr>297468&r1=297467&r2=297468&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/SemaOpenCL/<a href="http://address-spaces-conversions-cl2.0.cl" rel="noreferrer" target="_blank">addr<wbr>ess-spaces-conversions-cl2.0.<wbr>cl</a> (original)<br>
+++ cfe/trunk/test/SemaOpenCL/<a href="http://address-spaces-conversions-cl2.0.cl" rel="noreferrer" target="_blank">addr<wbr>ess-spaces-conversions-cl2.0.<wbr>cl</a> Fri Mar 10 09:23:07 2017<br>
@@ -18,14 +18,20 @@<br>
<br>
 #ifdef GENERIC<br>
 #define AS generic<br>
+#define AS_COMP local<br>
+#define AS_INCOMP constant<br>
 #endif<br>
<br>
 #ifdef GLOBAL<br>
 #define AS global<br>
+#define AS_COMP global<br>
+#define AS_INCOMP local<br>
 #endif<br>
<br>
 #ifdef CONSTANT<br>
 #define AS constant<br>
+#define AS_COMP constant<br>
+#define AS_INCOMP global<br>
 #endif<br>
<br>
 void f_glob(global int *arg_glob) {}<br>
@@ -263,12 +269,16 @@ void test_ternary() {<br>
   var_void_gen = 0 ? var_cond : var_glob_ch;<br>
 #ifdef CONSTANT<br>
 // expected-error@-2{{conditional operator with the second and third operands of type  ('__constant int *' and '__global char *') which are pointers to non-overlapping address spaces}}<br>
+#else<br>
+// expected-warning-re@-4{{<wbr>pointer type mismatch ('__{{global|generic}} int *' and '__global char *')}}<br>
 #endif<br>
<br>
   local char *var_loc_ch;<br>
   var_void_gen = 0 ? var_cond : var_loc_ch;<br>
 #ifndef GENERIC<br>
 // expected-error-re@-2{{<wbr>conditional operator with the second and third operands of type  ('__{{global|constant}} int *' and '__local char *') which are pointers to non-overlapping address spaces}}<br>
+#else<br>
+// expected-warning@-4{{pointer type mismatch ('__generic int *' and '__local char *')}}<br>
 #endif<br>
<br>
   constant void *var_void_const;<br>
@@ -276,18 +286,45 @@ void test_ternary() {<br>
   var_void_const = 0 ? var_cond : var_const_ch;<br>
 #ifndef CONSTANT<br>
 // expected-error-re@-2{{<wbr>conditional operator with the second and third operands of type  ('__{{global|generic}} int *' and '__constant char *') which are pointers to non-overlapping address spaces}}<br>
+#else<br>
+// expected-warning@-4{{pointer type mismatch ('__constant int *' and '__constant char *')}}<br>
 #endif<br>
<br>
   private char *var_priv_ch;<br>
   var_void_gen = 0 ? var_cond : var_priv_ch;<br>
 #ifndef GENERIC<br>
 // expected-error-re@-2{{<wbr>conditional operator with the second and third operands of type  ('__{{global|constant}} int *' and 'char *') which are pointers to non-overlapping address spaces}}<br>
+#else<br>
+// expected-warning@-4{{pointer type mismatch ('__generic int *' and 'char *')}}<br>
 #endif<br>
<br>
   generic char *var_gen_ch;<br>
   var_void_gen = 0 ? var_cond : var_gen_ch;<br>
 #ifdef CONSTANT<br>
 // expected-error@-2{{conditional operator with the second and third operands of type  ('__constant int *' and '__generic char *') which are pointers to non-overlapping address spaces}}<br>
+#else<br>
+// expected-warning-re@-4{{<wbr>pointer type mismatch ('__{{global|generic}} int *' and '__generic char *')}}<br>
 #endif<br>
 }<br>
<br>
+void test_pointer_chains() {<br>
+  AS int *AS *var_as_as_int;<br>
+  AS int *AS_COMP *var_asc_as_int;<br>
+  AS_INCOMP int *AS_COMP *var_asc_asn_int;<br>
+  AS_COMP int *AS_COMP *var_asc_asc_int;<br>
+<br>
+  // Case 1:<br>
+  //  * address spaces of corresponded most outer pointees overlaps, their canonical types are equal<br>
+  //  * CVR, address spaces and canonical types of the rest of pointees are equivalent.<br>
+  var_as_as_int = 0 ? var_as_as_int : var_asc_as_int;<br>
+<br>
+  // Case 2: Corresponded inner pointees has non-overlapping address spaces.<br>
+  var_as_as_int = 0 ? var_as_as_int : var_asc_asn_int;<br>
+// expected-warning-re@-1{{<wbr>pointer type mismatch ('__{{(generic|global|<wbr>constant)}} int *__{{(generic|global|constant)<wbr>}} *' and '__{{(local|global|constant)}} int *__{{(constant|local|global)}} *')}}<br>
+<br>
+  // Case 3: Corresponded inner pointees has overlapping but not equivalent address spaces.<br>
+#ifdef GENERIC<br>
+  var_as_as_int = 0 ? var_as_as_int : var_asc_asc_int;<br>
+// expected-warning-re@-1{{<wbr>pointer type mismatch ('__{{(generic|global|<wbr>constant)}} int *__{{(generic|global|constant)<wbr>}} *' and '__{{(local|global|constant)}} int *__{{(local|global|constant)}} *')}}<br>
+#endif<br>
+}<br>
<br>
Added: cfe/trunk/test/SemaOpenCL/<a href="http://overload_addrspace_resolution.cl" rel="noreferrer" target="_blank">over<wbr>load_addrspace_resolution.cl</a><br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaOpenCL/overload_addrspace_resolution.cl?rev=297468&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>SemaOpenCL/overload_addrspace_<wbr>resolution.cl?rev=297468&view=<wbr>auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/SemaOpenCL/<a href="http://overload_addrspace_resolution.cl" rel="noreferrer" target="_blank">over<wbr>load_addrspace_resolution.cl</a> (added)<br>
+++ cfe/trunk/test/SemaOpenCL/<a href="http://overload_addrspace_resolution.cl" rel="noreferrer" target="_blank">over<wbr>load_addrspace_resolution.cl</a> Fri Mar 10 09:23:07 2017<br>
@@ -0,0 +1,29 @@<br>
+// RUN: %clang_cc1 -cl-std=CL2.0 -emit-llvm -o - %s | FileCheck %s<br>
+<br>
+void __attribute__((overloadable)) foo(global int *a, global int *b);<br>
+void __attribute__((overloadable)) foo(generic int *a, generic int *b);<br>
+void __attribute__((overloadable)) bar(generic int *global *a, generic int *global *b);<br>
+void __attribute__((overloadable)) bar(generic int *generic *a, generic int *generic *b);<br>
+<br>
+void kernel ker() {<br>
+  global int *a;<br>
+  global int *b;<br>
+  generic int *c;<br>
+  local int *d;<br>
+  generic int *generic *gengen;<br>
+  generic int *local *genloc;<br>
+  generic int *global *genglob;<br>
+  // CHECK: call void @_Z3fooPU8CLglobaliS0_(i32* undef, i32* undef)<br>
+  foo(a, b);<br>
+  // CHECK: call void @_Z3fooPU9CLgenericiS0_(i32* undef, i32* undef)<br>
+  foo(b, c);<br>
+  // CHECK: call void @_Z3fooPU9CLgenericiS0_(i32* undef, i32* undef)<br>
+  foo(a, d);<br>
+<br>
+  // CHECK: call void @_<wbr>Z3barPU9CLgenericPU9CLgenerici<wbr>S2_(i32** undef, i32** undef)<br>
+  bar(gengen, genloc);<br>
+  // CHECK: call void @_<wbr>Z3barPU9CLgenericPU9CLgenerici<wbr>S2_(i32** undef, i32** undef)<br>
+  bar(gengen, genglob);<br>
+  // CHECK: call void @_<wbr>Z3barPU8CLglobalPU9CLgenericiS<wbr>2_(i32** undef, i32** undef)<br>
+  bar(genglob, genglob);<br>
+}<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>