Index: test/SemaOpenCL/sampler_type.cl
===================================================================
--- test/SemaOpenCL/sampler_type.cl	(revision 0)
+++ test/SemaOpenCL/sampler_type.cl	(revision 0)
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
+
+#define CLK_NORMALIZED_COORDS_TRUE 1
+#define CLK_ADDRESS_REPEAT 2
+#define CLK_FILTER_NEAREST 4
+#define VALUE (CLK_NORMALIZED_COORDS_TRUE | CLK_ADDRESS_REPEAT | CLK_FILTER_NEAREST)
+
+
+// two valid forms of declaring sampler variables in program source
+const sampler_t const_sampler = VALUE;
+constant sampler_t constant_sampler = VALUE;
+
+
+kernel void f_kernel()
+{
+  // outermost kernel function scope
+  const sampler_t const_sampler_kernel = VALUE;
+  sampler_t constant_sampler_kernel = VALUE;
+  
+  // invalid qualifiers
+  global sampler_t global_sampler; // expected-error {{using invalid qualifier with sampler type}}
+  private sampler_t private_sampler;
+  local sampler_t local_sampler; // expected-error {{using invalid qualifier with sampler type}}
+  
+  // non-outermost kernel function scope
+  {
+    const sampler_t const_sampler_non_outermost_kernel = VALUE;
+    sampler_t constant_sampler_non_outermost_kernel = VALUE;
+  }
+}
+
+
+sampler_t f_non_kernel(sampler_t argument_sampler) // expected-error {{declaring return value of type 'sampler_t' is not allowed}}
+{
+  // non-kernel function scope
+  const sampler_t non_kernel_sampler = VALUE; // expected-error {{declaring sampler variable in this context is not allowed}}
+  
+  argument_sampler = VALUE; // expected-error {{read-only variable is not assignable}}
+  
+  const sampler_t * pointer_sampler; // expected-error {{declaring pointer to type 'const sampler_t' is not allowed}}
+  
+  const sampler_t array_sampler[2]; // expected-error {{declaring array of type 'const sampler_t' is not allowed}}
+  
+  struct {
+    sampler_t sampler; // expected-error{{declaring field of type 'sampler_t' is not allowed}}
+  } struct_sampler;
+  
+  union {
+    sampler_t sampler; // expected-error{{declaring field of type 'sampler_t' is not allowed}}
+  } union_sampler;
+  
+  return argument_sampler;
+}
+
+
Index: include/clang/Basic/Specifiers.h
===================================================================
--- include/clang/Basic/Specifiers.h	(revision 158757)
+++ include/clang/Basic/Specifiers.h	(working copy)
@@ -60,6 +60,7 @@
     TST_auto,         // C++0x auto
     TST_unknown_anytype, // __unknown_anytype extension
     TST_atomic,       // C11 _Atomic
+    TST_sampler_t,    // OpenCL sampler type
     TST_error         // erroneous type
   };
   
Index: include/clang/Basic/TokenKinds.def
===================================================================
--- include/clang/Basic/TokenKinds.def	(revision 158757)
+++ include/clang/Basic/TokenKinds.def	(working copy)
@@ -440,6 +440,7 @@
 ALIAS("write_only", __write_only    , KEYOPENCL)
 ALIAS("read_write", __read_write    , KEYOPENCL)
 KEYWORD(__builtin_astype            , KEYOPENCL)
+KEYWORD(sampler_t                   , KEYOPENCL)
 
 // Borland Extensions.
 KEYWORD(__pascal                    , KEYALL)
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td	(revision 158759)
+++ include/clang/Basic/DiagnosticSemaKinds.td	(working copy)
@@ -5626,6 +5626,13 @@
   "kernel functions cannot be declared static">;
 def err_static_function_scope : Error<
   "variables in function scope cannot be declared static">;
+def err_opencl_sampler_declaration : Error<
+  "declaring sampler variable in this context is not allowed">;
+def err_opencl_sampler_qualifier : Error<"using invalid qualifier with sampler type">;
+def err_opencl_type_pointer : Error<"%0: declaring pointer to type %1 is not allowed">;
+def err_opencl_type_array : Error<"%0: declaring array of type %1 is not allowed">;
+def err_opencl_type_return : Error<"declaring return value of type %0 is not allowed">;
+  def err_opencl_type_field : Error<"%0: declaring field of type %1 is not allowed">;
 
 } // end of sema category
 
Index: include/clang/Sema/DeclSpec.h
===================================================================
--- include/clang/Sema/DeclSpec.h	(revision 158757)
+++ include/clang/Sema/DeclSpec.h	(working copy)
@@ -265,6 +265,7 @@
   static const TST TST_auto = clang::TST_auto;
   static const TST TST_unknown_anytype = clang::TST_unknown_anytype;
   static const TST TST_atomic = clang::TST_atomic;
+  static const TST TST_sampler_t = clang::TST_sampler_t;
   static const TST TST_error = clang::TST_error;
 
   // type-qualifiers
Index: include/clang/AST/TypeNodes.def
===================================================================
--- include/clang/AST/TypeNodes.def	(revision 158757)
+++ include/clang/AST/TypeNodes.def	(working copy)
@@ -102,6 +102,7 @@
 TYPE(ObjCObject, Type)
 TYPE(ObjCInterface, ObjCObjectType)
 TYPE(ObjCObjectPointer, Type)
+TYPE(OpenCLSampler, Type)
 TYPE(Atomic, Type)
 
 #ifdef LAST_TYPE
@@ -114,6 +115,7 @@
 LEAF_TYPE(Enum)
 LEAF_TYPE(Builtin)
 LEAF_TYPE(Record)
+LEAF_TYPE(OpenCLSampler)
 LEAF_TYPE(InjectedClassName)
 LEAF_TYPE(ObjCInterface)
 LEAF_TYPE(TemplateTypeParm)
Index: include/clang/AST/Type.h
===================================================================
--- include/clang/AST/Type.h	(revision 158757)
+++ include/clang/AST/Type.h	(working copy)
@@ -4533,6 +4533,21 @@
   QualType apply(const ASTContext &Context, const Type* T) const;
 };
 
+// OpenCL specific types.
+class OpenCLSamplerType : public Type {
+public:
+  OpenCLSamplerType() :  Type(OpenCLSampler, QualType(), false, false,
+                              /*VariablyModified=*/false,
+                              /*Unexpanded parameter pack=*/false) { }
+  bool isSugared() const { return false; }
+  QualType desugar() const { return QualType(this, 0); }
+  
+  static bool classof(const Type *T) {
+    return T->getTypeClass() == OpenCLSampler;
+  }
+  
+  static bool classof(const OpenCLSamplerType *) { return true; }
+};
 
 // Inline function definitions.
 
Index: include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- include/clang/AST/RecursiveASTVisitor.h	(revision 158757)
+++ include/clang/AST/RecursiveASTVisitor.h	(working copy)
@@ -973,7 +973,10 @@
 DEF_TRAVERSE_TYPE(AtomicType, {
     TRY_TO(TraverseType(T->getValueType()));
   })
-
+  
+  
+DEF_TRAVERSE_TYPE(OpenCLSamplerType, { })
+  
 #undef DEF_TRAVERSE_TYPE
 
 // ----------------- TypeLoc traversal -----------------
@@ -1142,10 +1145,11 @@
 
 DEF_TRAVERSE_TYPELOC(RecordType, { })
 DEF_TRAVERSE_TYPELOC(EnumType, { })
+DEF_TRAVERSE_TYPELOC(OpenCLSamplerType, { })
 DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, { })
 DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, { })
 DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, { })
-
+  
 // FIXME: use the loc for the template name?
 DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, {
     TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName()));
@@ -1201,11 +1205,11 @@
 DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType, {
     TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
   })
-
+ 
 DEF_TRAVERSE_TYPELOC(AtomicType, {
     TRY_TO(TraverseTypeLoc(TL.getValueLoc()));
   })
-
+  
 #undef DEF_TRAVERSE_TYPELOC
 
 // ----------------- Decl traversal -----------------
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h	(revision 158757)
+++ include/clang/AST/ASTContext.h	(working copy)
@@ -570,6 +570,7 @@
   CanQualType PseudoObjectTy, ARCUnbridgedCastTy;
   CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
   CanQualType ObjCBuiltinBoolTy;
+  QualType OpenCLSamplerTy;
 
   // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
   mutable QualType AutoDeductTy;     // Deduction against 'auto'.
@@ -1233,6 +1234,9 @@
   QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error,
                           unsigned *IntegerConstantArgs = 0) const;
 
+  // OpenCL specific types.
+  QualType getOpenCLSamplerType() const;
+  
 private:
   CanQualType getFromTargetType(unsigned Type) const;
   std::pair<uint64_t, unsigned> getTypeInfoImpl(const Type *T) const;
Index: include/clang/AST/TypeLoc.h
===================================================================
--- include/clang/AST/TypeLoc.h	(revision 158757)
+++ include/clang/AST/TypeLoc.h	(working copy)
@@ -1360,6 +1360,12 @@
                                                         ComplexType> {
 };
 
+// FIXME: location of the OpenCL sampler type.
+class OpenCLSamplerTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+                                                        OpenCLSamplerTypeLoc,
+                                                        OpenCLSamplerType> {
+};
+  
 struct TypeofLocInfo {
   SourceLocation TypeofLoc;
   SourceLocation LParenLoc;
Index: include/clang/Serialization/ASTBitCodes.h
===================================================================
--- include/clang/Serialization/ASTBitCodes.h	(revision 158757)
+++ include/clang/Serialization/ASTBitCodes.h	(working copy)
@@ -729,7 +729,9 @@
       /// \brief A UnaryTransformType record.
       TYPE_UNARY_TRANSFORM       = 39,
       /// \brief An AtomicType record.
-      TYPE_ATOMIC                = 40
+      TYPE_ATOMIC                = 40,
+      /// \brief A OpenCLSamplerType record.
+      TYPE_OPENCLSAMPLER         = 41
     };
 
     /// \brief The type IDs for special types constructed by semantic
Index: tools/libclang/RecursiveASTVisitor.h
===================================================================
--- tools/libclang/RecursiveASTVisitor.h	(revision 158757)
+++ tools/libclang/RecursiveASTVisitor.h	(working copy)
@@ -917,6 +917,8 @@
 DEF_TRAVERSE_TYPE(AtomicType, {
     TRY_TO(TraverseType(T->getValueType()));
   })
+  
+DEF_TRAVERSE_TYPE(OpenCLSamplerType, { })
 
 #undef DEF_TRAVERSE_TYPE
 
@@ -1150,6 +1152,8 @@
     TRY_TO(TraverseTypeLoc(TL.getValueLoc()));
   })
 
+DEF_TRAVERSE_TYPELOC(OpenCLSamplerType, { })
+  
 #undef DEF_TRAVERSE_TYPELOC
 
 // ----------------- Decl traversal -----------------
Index: tools/libclang/CIndex.cpp
===================================================================
--- tools/libclang/CIndex.cpp	(revision 158757)
+++ tools/libclang/CIndex.cpp	(working copy)
@@ -1573,6 +1573,7 @@
 DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParm, Type)
 DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParmPack, Type)
 DEFAULT_TYPELOC_IMPL(Auto, Type)
+DEFAULT_TYPELOC_IMPL(OpenCLSampler, Type)
 
 bool CursorVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) {
   // Visit the nested-name-specifier, if present.
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h	(revision 158757)
+++ lib/Sema/TreeTransform.h	(working copy)
@@ -4524,6 +4524,13 @@
 }
 
 template<typename Derived>
+QualType TreeTransform<Derived>::TransformOpenCLSamplerType(TypeLocBuilder &TLB,
+                                                    OpenCLSamplerTypeLoc TL) {
+  QualType Result = TL.getType();
+  return Result;
+}
+  
+template<typename Derived>
 QualType TreeTransform<Derived>::TransformInjectedClassNameType(
                                          TypeLocBuilder &TLB,
                                          InjectedClassNameTypeLoc TL) {
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp	(revision 158759)
+++ lib/Sema/SemaDecl.cpp	(working copy)
@@ -4098,6 +4098,33 @@
     // OpenCL __local address space.
     if (R.getAddressSpace() == LangAS::opencl_local)
       SC = SC_OpenCLWorkGroupLocal;
+    
+    if (isa<OpenCLSamplerType>(R.getTypePtr())) {
+      bool valid = false;
+      //  The sampler type can be used to declare a variable only
+      //  in the scope of a kernel function or in the program scope.
+      if (DC->isFunctionOrMethod()) {
+        FunctionDecl *FD = dyn_cast<FunctionDecl>(DC);
+        if (FD->hasAttr<OpenCLKernelAttr>()) {
+          valid = true;
+        }
+      } else if (DC->isTranslationUnit()) {
+        valid = true;
+      }
+      if (!valid) {
+        Diag(D.getIdentifierLoc(), diag::err_opencl_sampler_declaration);
+        D.setInvalidType();
+      } else {
+        // The sampler type may only be used with constant addr space  
+        // qualifier.
+        if (R.hasQualifiers()
+            && !((R.getAddressSpace() == LangAS::opencl_constant)
+            || R.isConstQualified())) {
+          Diag(D.getIdentifierLoc(), diag::err_opencl_sampler_qualifier);
+          D.setInvalidType();
+        }
+      }
+    }
   }
 
   bool isExplicitSpecialization = false;
@@ -9222,6 +9249,14 @@
     }
   }
 
+  if (!InvalidDecl) {
+    // Sampler types cannot be used to declare a field.
+    if (isa<OpenCLSamplerType>(T)) {
+      Diag(Loc, diag::err_opencl_type_field) << II << T;
+      InvalidDecl = true;
+    }
+  }
+  
   FieldDecl *NewFD = FieldDecl::Create(Context, Record, TSSL, Loc, II, T, TInfo,
                                        BitWidth, Mutable, InitStyle);
   if (InvalidDecl)
Index: lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- lib/Sema/SemaTemplateDeduction.cpp	(revision 158757)
+++ lib/Sema/SemaTemplateDeduction.cpp	(working copy)
@@ -1110,7 +1110,8 @@
     case Type::Enum:
     case Type::ObjCObject:
     case Type::ObjCInterface:
-    case Type::ObjCObjectPointer: {
+    case Type::ObjCObjectPointer:
+    case Type::OpenCLSampler: {
       if (TDF & TDF_SkipNonDependent)
         return Sema::TDK_Success;
       
@@ -4406,6 +4407,7 @@
   case Type::ObjCObject:
   case Type::ObjCObjectPointer:
   case Type::UnresolvedUsing:
+  case Type::OpenCLSampler:
 #define TYPE(Class, Base)
 #define ABSTRACT_TYPE(Class, Base)
 #define DEPENDENT_TYPE(Class, Base)
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp	(revision 158757)
+++ lib/Sema/SemaTemplate.cpp	(working copy)
@@ -3441,6 +3441,11 @@
   return Visit(T->getValueType());
 }
 
+bool UnnamedLocalNoLinkageFinder::VisitOpenCLSamplerType(
+                                                const OpenCLSamplerType* T) {
+  return false;
+}
+
 bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) {
   if (Tag->getDeclContext()->isFunctionOrMethod()) {
     S.Diag(SR.getBegin(),
Index: lib/Sema/DeclSpec.cpp
===================================================================
--- lib/Sema/DeclSpec.cpp	(revision 158759)
+++ lib/Sema/DeclSpec.cpp	(working copy)
@@ -267,6 +267,7 @@
     case TST_half:
     case TST_int:
     case TST_int128:
+    case TST_sampler_t:
     case TST_struct:
     case TST_union:
     case TST_unknown_anytype:
@@ -402,6 +403,7 @@
   case DeclSpec::TST_underlyingType: return "__underlying_type";
   case DeclSpec::TST_unknown_anytype: return "__unknown_anytype";
   case DeclSpec::TST_atomic: return "_Atomic";
+  case DeclSpec::TST_sampler_t:   return "sampler_t";
   case DeclSpec::TST_error:       return "(error)";
   }
   llvm_unreachable("Unknown typespec!");
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp	(revision 158757)
+++ lib/Sema/SemaType.cpp	(working copy)
@@ -631,6 +631,9 @@
         "Unknown TSS value");
       Result = Context.Char32Ty;
     break;
+  case DeclSpec::TST_sampler_t:
+      Result = Context.getOpenCLSamplerType();
+      break;
   case DeclSpec::TST_unspecified:
     // "<proto1,proto2>" is an objc qualified ID with a missing id.
     if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
@@ -999,7 +1002,7 @@
       // C90 doesn't have restrict, so it doesn't force us to produce a warning
       // in this case.
     }
-
+    
     Qualifiers Quals = Qualifiers::fromCVRMask(TypeQuals);
     Result = Context.getQualifiedType(Result, Quals);
   }
@@ -1132,6 +1135,13 @@
     return QualType();
   }
 
+  // Using the sampler types to declare a pointer is not allowed.
+  if (isa<OpenCLSamplerType>(T)) {
+    Diag(Loc, diag::err_opencl_type_pointer)
+    << getPrintableNameForEntity(Entity) << T;
+    return QualType();
+  }
+  
   assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType");
 
   // In ARC, it is forbidden to build pointers to unqualified pointers.
@@ -1281,6 +1291,13 @@
     return QualType();
   }
 
+  // Using the image and sampler types to declare an array is not allowed
+  if (isa<OpenCLSamplerType>(T)) {
+    Diag(Loc, diag::err_opencl_type_array)
+    << getPrintableNameForEntity(Entity) << T;
+    return QualType();
+  }
+  
   if (T->getContainedAutoType()) {
     Diag(Loc, diag::err_illegal_decl_array_of_auto)
       << getPrintableNameForEntity(Entity) << T;
@@ -2411,6 +2428,14 @@
           // Only the outermost chunk is marked noexcept, of course.
           EPI.ExceptionSpecType = EST_BasicNoexcept;
         }
+        
+        // Using the sampler types to declare a return value
+        // is not allowed.
+        if (LangOpts.OpenCL) {
+          if (isa<OpenCLSamplerType>(T.getTypePtr())) {
+            S.Diag(DeclType.Loc, diag::err_opencl_type_return) << T;
+          }
+        }
 
         T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(), EPI);
       }
Index: lib/Sema/SemaLookup.cpp
===================================================================
--- lib/Sema/SemaLookup.cpp	(revision 158757)
+++ lib/Sema/SemaLookup.cpp	(working copy)
@@ -2050,6 +2050,7 @@
     case Type::Vector:
     case Type::ExtVector:
     case Type::Complex:
+    case Type::OpenCLSampler:
       break;
 
     // If T is an Objective-C object or interface type, or a pointer to an 
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp	(revision 158757)
+++ lib/Sema/SemaExpr.cpp	(working copy)
@@ -5511,6 +5511,12 @@
   LHSType = Context.getCanonicalType(LHSType).getUnqualifiedType();
   RHSType = Context.getCanonicalType(RHSType).getUnqualifiedType();
 
+  // A special case: sampler constructor.
+  if (getLangOpts().OpenCL) {
+    if (isa<OpenCLSamplerType>(LHSType)) {
+      if (RHSType->isIntegerType()) return Compatible;
+    }
+  }
 
   // Common case: no conversion required.
   if (LHSType == RHSType) {
@@ -7466,6 +7472,10 @@
   case Expr::MLV_ConstQualified:
     Diag = diag::err_typecheck_assign_const;
 
+    // OpenCL sampler check, no need to do anything further.
+    if (S.getLangOpts().OpenCL && isa<OpenCLSamplerType>(E->getType()))
+      break;
+
     // Use a specialized diagnostic when we're assigning to an object
     // from an enclosing function or block.
     if (NonConstCaptureKind NCCK = isReferenceToNonConstCapture(S, E)) {
Index: lib/Sema/SemaTemplateVariadic.cpp
===================================================================
--- lib/Sema/SemaTemplateVariadic.cpp	(revision 158757)
+++ lib/Sema/SemaTemplateVariadic.cpp	(working copy)
@@ -680,6 +680,7 @@
   case TST_struct:
   case TST_class:
   case TST_auto:
+  case TST_sampler_t:
   case TST_unknown_anytype:
   case TST_error:
     break;
Index: lib/Sema/Sema.cpp
===================================================================
--- lib/Sema/Sema.cpp	(revision 158757)
+++ lib/Sema/Sema.cpp	(working copy)
@@ -273,6 +273,15 @@
   if (ExprTy == TypeTy)
     return Owned(E);
 
+  // A special case: attempting to initialize a sampler.
+  if (getLangOpts().OpenCL) {
+    const OpenCLSamplerType *tp = Ty.getTypePtr()->getAs<OpenCLSamplerType>();
+    if (tp != NULL) {
+      // Casting is not required - CodeGen will take care of it
+      return Owned(E); 
+    }
+  }
+
   if (getLangOpts().ObjCAutoRefCount)
     CheckObjCARCConversion(SourceRange(), Ty, E, CCK);
 
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp	(revision 158757)
+++ lib/AST/ASTImporter.cpp	(working copy)
@@ -841,6 +841,9 @@
     break;
   }
 
+  case Type::OpenCLSampler:
+    return true;
+      
   } // end switch
 
   return true;
Index: lib/AST/Type.cpp
===================================================================
--- lib/AST/Type.cpp	(revision 158757)
+++ lib/AST/Type.cpp	(working copy)
@@ -2111,8 +2111,10 @@
     return Cache::get(cast<ObjCObjectPointerType>(T)->getPointeeType());
   case Type::Atomic:
     return Cache::get(cast<AtomicType>(T)->getValueType());
+  case Type::OpenCLSampler:
+    return CachedProperties(NamedDecl::LinkageInfo(), false);
   }
-
+  
   llvm_unreachable("unhandled type class");
 }
 
Index: lib/AST/TypePrinter.cpp
===================================================================
--- lib/AST/TypePrinter.cpp	(revision 158757)
+++ lib/AST/TypePrinter.cpp	(working copy)
@@ -188,6 +188,7 @@
     case Type::ObjCObject:
     case Type::ObjCInterface:
     case Type::Atomic:
+    case Type::OpenCLSampler:
       CanPrefixQualifiers = true;
       break;
       
@@ -1228,6 +1229,13 @@
 void TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T, 
                                               raw_ostream &OS) { }
 
+void TypePrinter::printOpenCLSamplerBefore(const OpenCLSamplerType *T,
+                                     raw_ostream &OS) {
+  OS << "sampler_t";
+}
+void TypePrinter::printOpenCLSamplerAfter(const OpenCLSamplerType *T,
+                                           raw_ostream &OS) {}
+
 void TemplateSpecializationType::
   PrintTemplateArgumentList(raw_ostream &OS,
                             const TemplateArgumentListInfo &Args,
Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp	(revision 158757)
+++ lib/AST/MicrosoftMangle.cpp	(working copy)
@@ -1478,6 +1478,15 @@
     << Range;
 }
 
+void MicrosoftCXXNameMangler::mangleType(const OpenCLSamplerType *T,
+                                         SourceRange Range) {
+  DiagnosticsEngine &Diags = Context.getDiags();
+  unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+                                          "cannot mangle OpenCL sampler types yet");
+  Diags.Report(Range.getBegin(), DiagID)
+    << Range;
+}
+
 void MicrosoftMangleContext::mangleName(const NamedDecl *D,
                                         raw_ostream &Out) {
   assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
Index: lib/AST/ItaniumMangle.cpp
===================================================================
--- lib/AST/ItaniumMangle.cpp	(revision 158757)
+++ lib/AST/ItaniumMangle.cpp	(working copy)
@@ -856,6 +856,7 @@
     case Type::ObjCInterface:
     case Type::ObjCObjectPointer:
     case Type::Atomic:
+    case Type::OpenCLSampler:
       llvm_unreachable("type is illegal as a nested name specifier");
 
     case Type::SubstTemplateTypeParmPack:
@@ -2063,6 +2064,10 @@
   mangleType(T->getElementType());
 }
 
+void CXXNameMangler::mangleType(const OpenCLSamplerType *T) {
+  Out << "uSampler";
+}
+
 // ARM's ABI for Neon vector types specifies that they should be mangled as
 // if they are structs (to match ARM's initial implementation).  The
 // vector type must be one of the special types predefined by ARM.
Index: lib/AST/ExprClassification.cpp
===================================================================
--- lib/AST/ExprClassification.cpp	(revision 158757)
+++ lib/AST/ExprClassification.cpp	(working copy)
@@ -600,6 +600,15 @@
       return Cl::CM_ConstQualified;
   }
 
+  // OpenCL specific types.
+  if (Ctx.getLangOpts().OpenCL) {
+    const QualType ETy = E->getType();
+    const Type *ETyP = ETy.getTypePtr();
+    if (isa<OpenCLSamplerType>(ETyP)) {
+      return Cl::CM_ConstQualified;
+    }
+  }
+  
   return Cl::CM_Modifiable;
 }
 
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp	(revision 158757)
+++ lib/AST/ASTContext.cpp	(working copy)
@@ -498,6 +498,8 @@
 
   // half type (OpenCL 6.1.1.1) / ARM NEON __fp16
   InitBuiltinType(HalfTy, BuiltinType::Half);
+
+  OpenCLSamplerTy = QualType( new (*this, TypeAlignment)OpenCLSamplerType(), 0);
 }
 
 DiagnosticsEngine &ASTContext::getDiagnostics() const {
@@ -1125,7 +1127,12 @@
     }
   }
 
+    case Type::OpenCLSampler: {
+    Width = Target->getPointerWidth(0);
+    Align = Target->getPointerAlign(0);
+    break;
   }
+  }
 
   assert(llvm::isPowerOf2_32(Align) && "Alignment must be power of 2");
   return std::make_pair(Width, Align);
@@ -1757,6 +1764,7 @@
   case Type::SubstTemplateTypeParmPack:
   case Type::Auto:
   case Type::PackExpansion:
+  case Type::OpenCLSampler:
     llvm_unreachable("type should never be variably-modified");
 
   // These types can be variably-modified but should never need to
@@ -2084,6 +2092,10 @@
   return QualType(New, 0);
 }
 
+QualType ASTContext::getOpenCLSamplerType() const {
+  return OpenCLSamplerTy;
+}
+
 /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
 ///
 QualType
@@ -6325,8 +6337,10 @@
 
     return QualType();
   }
+  case Type::OpenCLSampler:
+    return QualType();
   }
-
+  
   llvm_unreachable("Invalid Type::Class!");
 }
 
Index: lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- lib/CodeGen/CodeGenFunction.cpp	(revision 158757)
+++ lib/CodeGen/CodeGenFunction.cpp	(working copy)
@@ -84,6 +84,7 @@
   case Type::FunctionNoProto:
   case Type::Enum:
   case Type::ObjCObjectPointer:
+  case Type::OpenCLSampler:
     return false;
 
   // Complexes, arrays, records, and Objective-C objects.
@@ -999,6 +1000,7 @@
     case Type::ObjCObject:
     case Type::ObjCInterface:
     case Type::ObjCObjectPointer:
+    case Type::OpenCLSampler:
       llvm_unreachable("type class is never variably-modified!");
 
     case Type::Pointer:
Index: lib/CodeGen/CodeGenTypes.cpp
===================================================================
--- lib/CodeGen/CodeGenTypes.cpp	(revision 158757)
+++ lib/CodeGen/CodeGenTypes.cpp	(working copy)
@@ -559,7 +559,12 @@
     ResultType = ConvertType(cast<AtomicType>(Ty)->getValueType());
     break;
   }
+      
+  case Type::OpenCLSampler: {
+    // FIXME: Should this be i32 with Constant Addr space?
+    ResultType = llvm::Type::getInt32Ty(getLLVMContext());
   }
+  }
   
   assert(ResultType && "Didn't convert a type?");
   
Index: lib/CodeGen/CGRTTI.cpp
===================================================================
--- lib/CodeGen/CGRTTI.cpp	(revision 158757)
+++ lib/CodeGen/CGRTTI.cpp	(working copy)
@@ -397,6 +397,9 @@
 #include "clang/AST/TypeNodes.def"
     llvm_unreachable("Non-canonical and dependent types shouldn't get here");
 
+  case Type::OpenCLSampler:
+    llvm_unreachable("OpenCL types shouldn't get here");
+      
   case Type::LValueReference:
   case Type::RValueReference:
     llvm_unreachable("References shouldn't get here");
@@ -604,6 +607,8 @@
     // abi::__fundamental_type_info adds no data members to std::type_info.
     break;
 
+  case Type::OpenCLSampler:
+    llvm_unreachable("OpenCL types shouldn't get here");
   case Type::LValueReference:
   case Type::RValueReference:
     llvm_unreachable("References shouldn't get here");
Index: lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- lib/CodeGen/CGDebugInfo.cpp	(revision 158757)
+++ lib/CodeGen/CGDebugInfo.cpp	(working copy)
@@ -1769,6 +1769,10 @@
   case Type::Atomic:
     return CreateType(cast<AtomicType>(Ty), Unit);
 
+      
+  case Type::OpenCLSampler:
+      llvm_unreachable("unsupported");
+      
   case Type::Attributed:
   case Type::TemplateSpecialization:
   case Type::Elaborated:
Index: lib/CodeGen/CGDecl.cpp
===================================================================
--- lib/CodeGen/CGDecl.cpp	(revision 158757)
+++ lib/CodeGen/CGDecl.cpp	(working copy)
@@ -111,6 +111,12 @@
   case SC_None:
   case SC_Auto:
   case SC_Register:
+      if (isa<OpenCLSamplerType>(D.getType())) {
+        // Emit a global "static" sampler declaration.
+        llvm::GlobalValue::LinkageTypes Linkage =
+        llvm::GlobalValue::InternalLinkage;
+        return EmitStaticVarDecl(D, Linkage);
+      }
     return EmitAutoVarDecl(D);
   case SC_Static: {
     llvm::GlobalValue::LinkageTypes Linkage =
@@ -184,7 +190,20 @@
     Name = GetStaticDeclName(*this, D, Separator);
 
   llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(Ty);
-  llvm::GlobalVariable *GV =
+  llvm::GlobalVariable *GV = 0;
+  
+  // Handle OpenCL sampler types.
+  if (getLangOpts().OpenCL) {
+    if (isa<OpenCLSamplerType>(D.getType().getTypePtr())) {
+      GV = new llvm::GlobalVariable(CGM.getModule(), LTy,
+                                    true, llvm::GlobalValue::ExternalLinkage,
+                                    0, Name, 0,
+                                    D.isThreadSpecified(),
+                                    CGM.getContext().getTargetAddressSpace(Ty));
+    }
+  }
+  
+  if (!GV)
     new llvm::GlobalVariable(CGM.getModule(), LTy,
                              Ty.isConstant(getContext()), Linkage,
                              CGM.EmitNullConstant(D.getType()), Name, 0,
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp	(revision 158757)
+++ lib/Parse/ParseDecl.cpp	(working copy)
@@ -2590,6 +2590,11 @@
                                      PrevSpec, DiagID);
       break;
 
+    case tok::kw_sampler_t:
+      isInvalid = DS.SetTypeSpecType(clang::TST_sampler_t, Loc,
+                                     PrevSpec, DiagID);
+      break;
+        
     // class-specifier:
     case tok::kw_class:
     case tok::kw_struct:
@@ -3369,6 +3374,7 @@
   case tok::kw__Decimal64:
   case tok::kw__Decimal128:
   case tok::kw___vector:
+  case tok::kw_sampler_t:
     
     // struct-or-union-specifier (C99) or class-specifier (C++)
   case tok::kw_class:
@@ -3440,6 +3446,7 @@
   case tok::kw__Decimal64:
   case tok::kw__Decimal128:
   case tok::kw___vector:
+  case tok::kw_sampler_t:
 
     // struct-or-union-specifier (C99) or class-specifier (C++)
   case tok::kw_class:
@@ -3577,6 +3584,7 @@
   case tok::kw__Decimal64:
   case tok::kw__Decimal128:
   case tok::kw___vector:
+  case tok::kw_sampler_t:
 
     // struct-or-union-specifier (C99) or class-specifier (C++)
   case tok::kw_class:
Index: lib/Serialization/ASTWriter.cpp
===================================================================
--- lib/Serialization/ASTWriter.cpp	(revision 158757)
+++ lib/Serialization/ASTWriter.cpp	(working copy)
@@ -399,6 +399,11 @@
   Code = TYPE_ATOMIC;
 }
 
+void ASTTypeWriter::VisitOpenCLSamplerType(const OpenCLSamplerType *T) {
+  Code = TYPE_OPENCLSAMPLER;
+}
+
+
 namespace {
 
 class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
@@ -614,6 +619,10 @@
   Writer.AddSourceLocation(TL.getLParenLoc(), Record);
   Writer.AddSourceLocation(TL.getRParenLoc(), Record);
 }
+void TypeLocWriter::VisitOpenCLSamplerTypeLoc(OpenCLSamplerTypeLoc
+                                              TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
 
 //===----------------------------------------------------------------------===//
 // ASTWriter Implementation
@@ -870,6 +879,7 @@
   RECORD(TYPE_ATTRIBUTED);
   RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK);
   RECORD(TYPE_ATOMIC);
+  RECORD(TYPE_OPENCLSAMPLER);
   RECORD(DECL_TYPEDEF);
   RECORD(DECL_ENUM);
   RECORD(DECL_RECORD);
Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp	(revision 158757)
+++ lib/Serialization/ASTReader.cpp	(working copy)
@@ -3839,6 +3839,10 @@
     return Context.getExtVectorType(ElementType, NumElements);
   }
 
+  case TYPE_OPENCLSAMPLER: {
+    return Context.getOpenCLSamplerType();
+  }
+      
   case TYPE_FUNCTION_NO_PROTO: {
     if (Record.size() != 6) {
       Error("incorrect encoding of no-proto function type");
@@ -4371,6 +4375,9 @@
   TL.setLParenLoc(ReadSourceLocation(Record, Idx));
   TL.setRParenLoc(ReadSourceLocation(Record, Idx));
 }
+void TypeLocReader::VisitOpenCLSamplerTypeLoc(OpenCLSamplerTypeLoc TL) {
+  TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
 
 TypeSourceInfo *ASTReader::GetTypeSourceInfo(ModuleFile &F,
                                              const RecordData &Record,
