Add OpenCL samplers as Clang builtin types and check sampler related restrictions.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174601 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index 6d30b89..569352e 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -286,6 +286,7 @@
     case TST_image2d_t:
     case TST_image2d_array_t:
     case TST_image3d_t:
+    case TST_sampler_t:
     case TST_event_t:
       return false;
 
@@ -428,6 +429,7 @@
   case DeclSpec::TST_image2d_t:   return "image2d_t";
   case DeclSpec::TST_image2d_array_t: return "image2d_array_t";
   case DeclSpec::TST_image3d_t:   return "image3d_t";
+  case DeclSpec::TST_sampler_t:   return "sampler_t";
   case DeclSpec::TST_event_t:     return "event_t";
   case DeclSpec::TST_error:       return "(error)";
   }
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 45f7cae..7c31be6 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -4483,6 +4483,14 @@
       SCAsWritten = SC_OpenCLWorkGroupLocal;
     }
 
+    // OpenCL v1.2 s6.9.b p4:
+    // The sampler type cannot be used with the __local and __global address
+    // space qualifiers.
+    if (R->isSamplerT() && (R.getAddressSpace() == LangAS::opencl_local ||
+      R.getAddressSpace() == LangAS::opencl_global)) {
+      Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace);
+    }
+
     // OpenCL 1.2 spec, p6.9 r:
     // The event type cannot be used to declare a program scope variable.
     // The event type cannot be used with the __local, __constant and __global
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 87e6648..0612c73 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -2424,6 +2424,7 @@
   case SK_PassByIndirectRestore:
   case SK_ProduceObjCObject:
   case SK_StdInitializerList:
+  case SK_OCLSamplerInit:
   case SK_OCLZeroEvent:
     break;
 
@@ -2653,6 +2654,13 @@
   Steps.push_back(S);
 }
 
+void InitializationSequence::AddOCLSamplerInitStep(QualType T) {
+  Step S;
+  S.Kind = SK_OCLSamplerInit;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
 void InitializationSequence::AddOCLZeroEventStep(QualType T) {
   Step S;
   S.Kind = SK_OCLZeroEvent;
@@ -4017,6 +4025,18 @@
   return true;
 }
 
+static bool TryOCLSamplerInitialization(Sema &S,
+                                        InitializationSequence &Sequence,
+                                        QualType DestType,
+                                        Expr *Initializer) {
+  if (!S.getLangOpts().OpenCL || !DestType->isSamplerT() ||
+    !Initializer->isIntegerConstantExpr(S.getASTContext()))
+    return false;
+
+  Sequence.AddOCLSamplerInitStep(DestType);
+  return true;
+}
+
 //
 // OpenCL 1.2 spec, s6.12.10
 //
@@ -4180,7 +4200,9 @@
         tryObjCWritebackConversion(S, *this, Entity, Initializer)) {
       return;
     }
-    
+
+    if (TryOCLSamplerInitialization(S, *this, DestType, Initializer))
+      return;
 
     if (TryOCLZeroEventInitialization(S, *this, DestType, Initializer))
       return;
@@ -4974,6 +4996,7 @@
   case SK_PassByIndirectRestore:
   case SK_ProduceObjCObject:
   case SK_StdInitializerList:
+  case SK_OCLSamplerInit:
   case SK_OCLZeroEvent: {
     assert(Args.size() == 1);
     CurInit = Args[0];
@@ -5490,6 +5513,23 @@
       CurInit = S.Owned(Semantic);
       break;
     }
+    case SK_OCLSamplerInit: {
+      assert(Step->Type->isSamplerT() && 
+             "Sampler initialization on non sampler type.");
+
+      QualType SourceType = CurInit.get()->getType();
+      InitializedEntity::EntityKind EntityKind = Entity.getKind();
+
+      if (EntityKind == InitializedEntity::EK_Parameter) {
+        if (!SourceType->isSamplerT())
+          S.Diag(Kind.getLocation(), diag::err_sampler_argument_required)
+            << SourceType;
+      } else if (EntityKind != InitializedEntity::EK_Variable) {
+        llvm_unreachable("Invalid EntityKind!");
+      }
+
+      break;
+    }
     case SK_OCLZeroEvent: {
       assert(Step->Type->isEventT() && 
              "Event initialization on non event type.");
@@ -6186,6 +6226,10 @@
       OS << "std::initializer_list from initializer list";
       break;
 
+    case SK_OCLSamplerInit:
+      OS << "OpenCL sampler_t from integer constant";
+      break;
+
     case SK_OCLZeroEvent:
       OS << "OpenCL event_t from zero";
       break;
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 2d4d159..ac9dec4 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -1664,7 +1664,9 @@
                                        == CanonTo.getLocalUnqualifiedType() &&
         (CanonFrom.getLocalCVRQualifiers() != CanonTo.getLocalCVRQualifiers()
          || CanonFrom.getObjCGCAttr() != CanonTo.getObjCGCAttr()
-         || CanonFrom.getObjCLifetime() != CanonTo.getObjCLifetime())) {
+         || CanonFrom.getObjCLifetime() != CanonTo.getObjCLifetime()
+         || (CanonFrom->isSamplerT() && 
+           CanonFrom.getAddressSpace() != CanonTo.getAddressSpace()))) {
       FromType = ToType;
       CanonFrom = CanonTo;
     }
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 470896e..c13a2f6 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -737,6 +737,7 @@
   case TST_image2d_t:
   case TST_image2d_array_t:
   case TST_image3d_t:
+  case TST_sampler_t:
   case TST_event_t:
   case TST_error:
     break;
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index ae8d030..b257a59 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -952,6 +952,10 @@
     Result = Context.OCLImage3dTy;
     break;
 
+  case DeclSpec::TST_sampler_t:
+    Result = Context.OCLSamplerTy;
+    break;
+
   case DeclSpec::TST_event_t:
     Result = Context.OCLEventTy;
     break;