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/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index eb14ff5..0e8f2b6 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -721,7 +721,7 @@
   CanQualType OCLImage1dTy, OCLImage1dArrayTy, OCLImage1dBufferTy;
   CanQualType OCLImage2dTy, OCLImage2dArrayTy;
   CanQualType OCLImage3dTy;
-  CanQualType OCLEventTy;
+  CanQualType OCLSamplerTy, OCLEventTy;
 
   // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
   mutable QualType AutoDeductTy;     // Deduction against 'auto'.
diff --git a/include/clang/AST/BuiltinTypes.def b/include/clang/AST/BuiltinTypes.def
index 503d963..488cace 100644
--- a/include/clang/AST/BuiltinTypes.def
+++ b/include/clang/AST/BuiltinTypes.def
@@ -162,6 +162,9 @@
 BUILTIN_TYPE(OCLImage2dArray, OCLImage2dArrayTy)
 BUILTIN_TYPE(OCLImage3d, OCLImage3dTy)
 
+// OpenCL sampler_t.
+BUILTIN_TYPE(OCLSampler, OCLSamplerTy)
+
 // OpenCL event_t.
 BUILTIN_TYPE(OCLEvent, OCLEventTy)
 
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 1469746..3e6297a 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -1584,6 +1584,7 @@
 
   bool isImageType() const;                     // Any OpenCL image type
 
+  bool isSamplerT() const;                      // OpenCL sampler_t
   bool isEventT() const;                        // OpenCL event_t
 
   bool isOpenCLSpecificType() const;            // Any OpenCL specific type
@@ -4918,6 +4919,11 @@
 inline bool Type::isImage3dT() const {
   return isSpecificBuiltinType(BuiltinType::OCLImage3d);
 }
+
+inline bool Type::isSamplerT() const {
+  return isSpecificBuiltinType(BuiltinType::OCLSampler);
+}
+
 inline bool Type::isEventT() const {
   return isSpecificBuiltinType(BuiltinType::OCLEvent);
 }
@@ -4929,7 +4935,7 @@
 }
 
 inline bool Type::isOpenCLSpecificType() const {
-  return isImageType() || isEventT();
+  return isSamplerT() || isEventT() || isImageType();
 }
 
 inline bool Type::isTemplateTypeParmType() const {
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index bcc33d1..e190d7b 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6139,6 +6139,10 @@
   "the event_t type can only be used with __private address space qualifier">;
 def err_expected_kernel_void_return_type : Error<
   "kernel must have void return type">;
+def err_sampler_argument_required : Error<
+  "sampler_t variable required - got %0">;
+def err_wrong_sampler_addressspace: Error<
+  "sampler type cannot be used with the __local and __global address space qualifiers">;
 
 } // end of sema category
 
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index 533cefe..8706179 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/include/clang/Basic/Specifiers.h
@@ -68,6 +68,7 @@
     TST_image2d_t,        // OpenCL image2d_t
     TST_image2d_array_t,  // OpenCL image2d_array_t
     TST_image3d_t,        // OpenCL image3d_t
+    TST_sampler_t,        // OpenCL sampler_t
     TST_event_t,          // OpenCL event_t
     TST_error         // erroneous type
   };
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index 8008ca6..6850bd5 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -455,6 +455,7 @@
 KEYWORD(image2d_t                   , KEYOPENCL)
 KEYWORD(image2d_array_t             , KEYOPENCL)
 KEYWORD(image3d_t                   , KEYOPENCL)
+KEYWORD(sampler_t                   , KEYOPENCL)
 KEYWORD(event_t                     , KEYOPENCL)
 
 // Borland Extensions.
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index fc43ed6..867c654 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -282,6 +282,7 @@
   static const TST TST_image2d_t = clang::TST_image2d_t;
   static const TST TST_image2d_array_t = clang::TST_image2d_array_t;
   static const TST TST_image3d_t = clang::TST_image3d_t;
+  static const TST TST_sampler_t = clang::TST_sampler_t;
   static const TST TST_event_t = clang::TST_event_t;
   static const TST TST_error = clang::TST_error;
 
diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h
index 002a126..e177374 100644
--- a/include/clang/Sema/Initialization.h
+++ b/include/clang/Sema/Initialization.h
@@ -625,6 +625,8 @@
     SK_ProduceObjCObject,
     /// \brief Construct a std::initializer_list from an initializer list.
     SK_StdInitializerList,
+    /// \brief Initialize an OpenCL sampler from an integer.
+    SK_OCLSamplerInit,
     /// \brief Passing zero to a function where OpenCL event_t is expected.
     SK_OCLZeroEvent
   };
@@ -955,6 +957,10 @@
   /// initializer list.
   void AddStdInitializerListConstructionStep(QualType T);
 
+  /// \brief Add a step to initialize an OpenCL sampler from an integer
+  /// constant.
+  void AddOCLSamplerInitStep(QualType T);
+
   /// \brief Add a step to initialize an OpenCL event_t from a NULL
   /// constant.
   void AddOCLZeroEventStep(QualType T);
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 6f76367..a672c7e 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -720,7 +720,10 @@
       PREDEF_TYPE_IMAGE2D_ARR_ID = 42,
       /// \brief OpenCL 3d image type.
       PREDEF_TYPE_IMAGE3D_ID    = 43,
-      PREDEF_TYPE_EVENT_ID      = 44
+      /// \brief OpenCL event type.
+      PREDEF_TYPE_EVENT_ID      = 44,
+      /// \brief OpenCL sampler type.
+      PREDEF_TYPE_SAMPLER_ID    = 45
     };
 
     /// \brief The number of predefined type IDs that are reserved for
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index f97e6e9..bdb464c 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -906,6 +906,7 @@
     InitBuiltinType(OCLImage2dArrayTy, BuiltinType::OCLImage2dArray);
     InitBuiltinType(OCLImage3dTy, BuiltinType::OCLImage3d);
 
+    InitBuiltinType(OCLSamplerTy, BuiltinType::OCLSampler);
     InitBuiltinType(OCLEventTy, BuiltinType::OCLEvent);
   }
   
@@ -1448,6 +1449,11 @@
       Width = Target->getPointerWidth(0); 
       Align = Target->getPointerAlign(0);
       break;
+    case BuiltinType::OCLSampler:
+      // Samplers are modeled as integers.
+      Width = Target->getIntWidth();
+      Align = Target->getIntAlign();
+      break;
     case BuiltinType::OCLEvent:
     case BuiltinType::OCLImage1d:
     case BuiltinType::OCLImage1dArray:
@@ -4923,6 +4929,7 @@
     case BuiltinType::OCLImage2dArray:
     case BuiltinType::OCLImage3d:
     case BuiltinType::OCLEvent:
+    case BuiltinType::OCLSampler:
     case BuiltinType::Dependent:
 #define BUILTIN_TYPE(KIND, ID)
 #define PLACEHOLDER_TYPE(KIND, ID) \
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 926384d..792bda6 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -1886,6 +1886,7 @@
   case BuiltinType::OCLImage2d: Out << "11ocl_image2d"; break;
   case BuiltinType::OCLImage2dArray: Out << "16ocl_image2darray"; break;
   case BuiltinType::OCLImage3d: Out << "11ocl_image3d"; break;
+  case BuiltinType::OCLSampler: Out << "11ocl_sampler"; break;
   case BuiltinType::OCLEvent: Out << "9ocl_event"; break;
   }
 }
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 0b77ac8..326b0d3 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -1060,6 +1060,7 @@
   case BuiltinType::OCLImage2d: Out << "PAUocl_image2d@@"; break;
   case BuiltinType::OCLImage2dArray: Out << "PAUocl_image2darray@@"; break;
   case BuiltinType::OCLImage3d: Out << "PAUocl_image3d@@"; break;
+  case BuiltinType::OCLSampler: Out << "PAUocl_sampler@@"; break;
   case BuiltinType::OCLEvent: Out << "PAUocl_event@@"; break;
  
   case BuiltinType::NullPtr: Out << "$$T"; break;
diff --git a/lib/AST/NSAPI.cpp b/lib/AST/NSAPI.cpp
index c8cf920..4c20235 100644
--- a/lib/AST/NSAPI.cpp
+++ b/lib/AST/NSAPI.cpp
@@ -351,6 +351,7 @@
   case BuiltinType::OCLImage2d:
   case BuiltinType::OCLImage2dArray:
   case BuiltinType::OCLImage3d:
+  case BuiltinType::OCLSampler:
   case BuiltinType::OCLEvent:
   case BuiltinType::BoundMember:
   case BuiltinType::Dependent:
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 524d005..efd588a 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1518,6 +1518,7 @@
   case OCLImage2d:        return "image2d_t";
   case OCLImage2dArray:   return "image2d_array_t";
   case OCLImage3d:        return "image3d_t";
+  case OCLSampler:        return "sampler_t";
   case OCLEvent:          return "event_t";
   }
   
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index 3efa148..010ea2d 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -268,6 +268,7 @@
   case BuiltinType::OCLImage2d:
   case BuiltinType::OCLImage2dArray:
   case BuiltinType::OCLImage3d:
+  case BuiltinType::OCLSampler:
   case BuiltinType::OCLEvent:
   case BuiltinType::BuiltinFn:
     return TST_unspecified;
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 5e60bd8..a4153d3 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -426,6 +426,11 @@
   case BuiltinType::OCLImage3d:
     return getOrCreateStructPtrType("opencl_image3d_t",
                                     OCLImage3dDITy);
+  case BuiltinType::OCLSampler:
+    return DBuilder.createBasicType("opencl_sampler_t",
+                                    CGM.getContext().getTypeSize(BT),
+                                    CGM.getContext().getTypeAlign(BT),
+                                    llvm::dwarf::DW_ATE_unsigned);
   case BuiltinType::OCLEvent:
     return getOrCreateStructPtrType("opencl_event_t",
                                     OCLEventDITy);
diff --git a/lib/CodeGen/CGOpenCLRuntime.cpp b/lib/CodeGen/CGOpenCLRuntime.cpp
index 215d096..7c454ac 100644
--- a/lib/CodeGen/CGOpenCLRuntime.cpp
+++ b/lib/CodeGen/CGOpenCLRuntime.cpp
@@ -55,6 +55,8 @@
   case BuiltinType::OCLImage3d:
     return llvm::PointerType::get(llvm::StructType::create(
                            CGM.getLLVMContext(), "opencl.image3d_t"), 0);
+  case BuiltinType::OCLSampler:
+    return llvm::IntegerType::get(CGM.getLLVMContext(),32);
   case BuiltinType::OCLEvent:
     return llvm::PointerType::get(llvm::StructType::create(
                            CGM.getLLVMContext(), "opencl.event_t"), 0);
diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp
index 366ce29..869843c 100644
--- a/lib/CodeGen/CGRTTI.cpp
+++ b/lib/CodeGen/CGRTTI.cpp
@@ -197,6 +197,7 @@
     case BuiltinType::OCLImage2d:
     case BuiltinType::OCLImage2dArray:
     case BuiltinType::OCLImage3d:
+    case BuiltinType::OCLSampler:
     case BuiltinType::OCLEvent:
       return true;
       
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index e78cbab..c82e1d8 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -378,6 +378,7 @@
     case BuiltinType::OCLImage2d:
     case BuiltinType::OCLImage2dArray:
     case BuiltinType::OCLImage3d:
+    case BuiltinType::OCLSampler:
     case BuiltinType::OCLEvent:
       ResultType = CGM.getOpenCLRuntime().convertOpenCLSpecificType(Ty);
       break;
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index e11fb91..8e24a14 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2781,6 +2781,10 @@
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image3d_t, Loc,
                                      PrevSpec, DiagID);
       break;
+    case tok::kw_sampler_t:
+      isInvalid = DS.SetTypeSpecType(DeclSpec::TST_sampler_t, Loc,
+                                     PrevSpec, DiagID);
+      break;
     case tok::kw_event_t:
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_event_t, Loc,
                                      PrevSpec, DiagID);
@@ -3635,6 +3639,7 @@
   case tok::kw_image2d_t:
   case tok::kw_image2d_array_t:
   case tok::kw_image3d_t:
+  case tok::kw_sampler_t:
   case tok::kw_event_t:
 
     // struct-or-union-specifier (C99) or class-specifier (C++)
@@ -3716,6 +3721,7 @@
   case tok::kw_image2d_t:
   case tok::kw_image2d_array_t:
   case tok::kw_image3d_t:
+  case tok::kw_sampler_t:
   case tok::kw_event_t:
 
     // struct-or-union-specifier (C99) or class-specifier (C++)
@@ -3869,6 +3875,7 @@
   case tok::kw_image2d_t:
   case tok::kw_image2d_array_t:
   case tok::kw_image3d_t:
+  case tok::kw_sampler_t:
   case tok::kw_event_t:
 
     // struct-or-union-specifier (C99) or class-specifier (C++)
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 4ed0bd0..7775909 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1024,6 +1024,7 @@
   case tok::kw_image2d_t:
   case tok::kw_image2d_array_t:
   case tok::kw_image3d_t:
+  case tok::kw_sampler_t:
   case tok::kw_event_t: {
     if (!getLangOpts().CPlusPlus) {
       Diag(Tok, diag::err_expected_expression);
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index 1116daa..b3cf983 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -843,6 +843,7 @@
   case tok::kw_image2d_t:
   case tok::kw_image2d_array_t:
   case tok::kw_image3d_t:
+  case tok::kw_sampler_t:
   case tok::kw_event_t:
   case tok::kw___unknown_anytype:
     return TPResult::False();
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;
diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp
index 955dc96..9f1514b 100644
--- a/lib/Serialization/ASTCommon.cpp
+++ b/lib/Serialization/ASTCommon.cpp
@@ -67,6 +67,7 @@
   case BuiltinType::OCLImage2d:       ID = PREDEF_TYPE_IMAGE2D_ID;      break;
   case BuiltinType::OCLImage2dArray:  ID = PREDEF_TYPE_IMAGE2D_ARR_ID;  break;
   case BuiltinType::OCLImage3d:       ID = PREDEF_TYPE_IMAGE3D_ID;      break;
+  case BuiltinType::OCLSampler:       ID = PREDEF_TYPE_SAMPLER_ID;      break;
   case BuiltinType::OCLEvent:         ID = PREDEF_TYPE_EVENT_ID;        break;
   case BuiltinType::BuiltinFn:
                                 ID = PREDEF_TYPE_BUILTIN_FN; break;
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 1213084..a00d406 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -4903,6 +4903,7 @@
     case PREDEF_TYPE_IMAGE2D_ID:    T = Context.OCLImage2dTy;       break;
     case PREDEF_TYPE_IMAGE2D_ARR_ID: T = Context.OCLImage2dArrayTy; break;
     case PREDEF_TYPE_IMAGE3D_ID:    T = Context.OCLImage3dTy;       break;
+    case PREDEF_TYPE_SAMPLER_ID:    T = Context.OCLSamplerTy;       break;
     case PREDEF_TYPE_EVENT_ID:      T = Context.OCLEventTy;         break;
     case PREDEF_TYPE_AUTO_DEDUCT:   T = Context.getAutoDeductType(); break;
         
diff --git a/test/CodeGenOpenCL/opencl_types.cl b/test/CodeGenOpenCL/opencl_types.cl
index ab2ebe1..b1e558d 100644
--- a/test/CodeGenOpenCL/opencl_types.cl
+++ b/test/CodeGenOpenCL/opencl_types.cl
@@ -1,5 +1,8 @@
 // RUN: %clang_cc1 %s -emit-llvm -o - -O0 | FileCheck %s
 
+constant sampler_t glb_smp = 7;
+// CHECK: global i32 7
+
 void fnc1(image1d_t img) {}
 // CHECK: @fnc1(%opencl.image1d_t*
 
@@ -18,7 +21,17 @@
 void fnc3(image3d_t img) {}
 // CHECK: @fnc3(%opencl.image3d_t*
 
+void fnc4smp(sampler_t s) {}
+// CHECK: define void @fnc4smp(i32
+
 kernel void foo(image1d_t img) {
+	sampler_t smp = 5;
+// CHECK: alloca i32
 	event_t evt;
 // CHECK: alloca %opencl.event_t*
+// CHECK: store i32 5,
+  fnc4smp(smp);
+// CHECK: call void @fnc4smp(i32
+  fnc4smp(glb_smp);
+// CHECK: call void @fnc4smp(i32
 }
diff --git a/test/PCH/ocl_types.cl b/test/PCH/ocl_types.cl
index 29de5e3..d788a32 100644
--- a/test/PCH/ocl_types.cl
+++ b/test/PCH/ocl_types.cl
@@ -17,6 +17,10 @@
 
 void foo6(img3d_t img);
 
+void foo7(smp_t smp) {
+  smp_t loc_smp;
+}
+
 void foo8(evt_t evt) {
   evt_t loc_evt;
 }
diff --git a/test/PCH/ocl_types.h b/test/PCH/ocl_types.h
index 829ea03..65c6acb 100644
--- a/test/PCH/ocl_types.h
+++ b/test/PCH/ocl_types.h
@@ -18,5 +18,8 @@
 // image3d_t
 typedef image3d_t img3d_t;
 
+// sampler_t
+typedef sampler_t smp_t;
+
 // event_t
 typedef event_t evt_t;
diff --git a/test/SemaOpenCL/sampler_t.cl b/test/SemaOpenCL/sampler_t.cl
new file mode 100644
index 0000000..96f6dbf
--- /dev/null
+++ b/test/SemaOpenCL/sampler_t.cl
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
+
+constant sampler_t glb_smp = 5;
+
+void foo(sampler_t); 
+
+void kernel ker(sampler_t argsmp) {
+  local sampler_t smp; // expected-error {{sampler type cannot be used with the __local and __global address space qualifiers}}
+  const sampler_t const_smp = 7;
+  foo(glb_smp);
+  foo(const_smp);
+  foo(5); // expected-error {{sampler_t variable required - got 'int'}}
+}
diff --git a/test/SemaOpenCL/sampler_t_overload.cl b/test/SemaOpenCL/sampler_t_overload.cl
new file mode 100644
index 0000000..83a854f
--- /dev/null
+++ b/test/SemaOpenCL/sampler_t_overload.cl
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 %s
+
+void __attribute__((overloadable)) foo(sampler_t, read_only image1d_t);
+void __attribute__((overloadable)) foo(sampler_t, read_only image2d_t);
+
+constant sampler_t glb_smp = 5;
+
+void kernel ker(read_only image1d_t src1, read_only image2d_t src2) {
+  const sampler_t smp = 10;
+  foo(glb_smp, src1);
+  foo(smp, src2);
+}
diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp
index c6f4d7c..a911ce5 100644
--- a/tools/libclang/CIndexUSRs.cpp
+++ b/tools/libclang/CIndexUSRs.cpp
@@ -596,6 +596,7 @@
         case BuiltinType::OCLImage2dArray:
         case BuiltinType::OCLImage3d:
         case BuiltinType::OCLEvent:
+        case BuiltinType::OCLSampler:
           IgnoreResults = true;
           return;
         case BuiltinType::ObjCId: