diff --git a/doc/runtime_queue.rst b/doc/runtime_queue.rst
index b4567953c889acdaafd9c49bc8d04d2de745bbc5..178a0c504c09342e4efc1dade2db28632051fdf6 100644
--- a/doc/runtime_queue.rst
+++ b/doc/runtime_queue.rst
@@ -13,15 +13,26 @@ Command Queue
     Create a new command queue. *properties* is a bit field
     consisting of :class:`command_queue_properties` values.
 
-    if *device* is None, one of the devices in *context* is chosen
+    If *device* is None, one of the devices in *context* is chosen
     in an implementation-defined manner.
 
+    *properties* may be a bitwise combination of values from
+    :class:`queue_properties` (or *None* which is equivalent to
+    passing *0*). This is compatible with both OpenCL 1.x and 2.x.
+
+    For OpenCL 2.0 and above, *properties* may also be a sequence
+    of keys and values from :class:`queue_properties` as accepted
+    by :c:func:`clCreateCommandQueueWithProperties` (see the OpenCL
+    spec for details). The trailing *0* is added automatically
+    and does not need to be included.
+
     A :class:`CommandQueue` may be used as a context manager, like this::
 
         with cl.CommandQueue(self.cl_context) as queue:
             enqueue_stuff(queue, ...)
 
-    :meth:`finish` is automatically called at the end of the context.
+    :meth:`finish` is automatically called at the end of the ``with``-delimited
+    context.
 
     .. versionadded:: 2013.1
 
diff --git a/src/wrap_cl.hpp b/src/wrap_cl.hpp
index b9753134825cc960c54e64082f12801b93238366..bcac5a38220018207f86a08b6eaf59417cf63c98 100644
--- a/src/wrap_cl.hpp
+++ b/src/wrap_cl.hpp
@@ -51,6 +51,7 @@
 #include <mutex>
 #include <condition_variable>
 
+#include <cstdio>
 #include <stdexcept>
 #include <iostream>
 #include <vector>
@@ -1028,6 +1029,47 @@ namespace pyopencl
             throw error("Context.get_info", CL_INVALID_VALUE);
         }
       }
+
+
+      // not exposed to python
+      int get_hex_platform_version() const
+      {
+        std::vector<cl_device_id> devices;
+        PYOPENCL_GET_VEC_INFO(Context, m_context, CL_CONTEXT_DEVICES, devices);
+
+        if (devices.size() == 0)
+          throw error("Context._get_hex_version", CL_INVALID_VALUE,
+              "platform has no devices");
+
+        cl_platform_id plat;
+
+        PYOPENCL_CALL_GUARDED(clGetDeviceInfo,
+            (devices[0], CL_DEVICE_PLATFORM, sizeof(plat), &plat, nullptr));
+
+        std::string plat_version;
+        {
+          size_t param_value_size;
+          PYOPENCL_CALL_GUARDED(clGetPlatformInfo,
+              (plat, CL_PLATFORM_VERSION, 0, 0, &param_value_size));
+
+          std::vector<char> param_value(param_value_size);
+          PYOPENCL_CALL_GUARDED(clGetPlatformInfo,
+              (plat, CL_PLATFORM_VERSION, param_value_size,
+               param_value.empty( ) ? nullptr : &param_value.front(), &param_value_size));
+
+          plat_version =
+              param_value.empty( ) ? "" : std::string(&param_value.front(), param_value_size-1);
+        }
+
+        int major_ver, minor_ver;
+        errno = 0;
+        int match_count = sscanf(plat_version.c_str(), "OpenCL %d.%d ", &major_ver, &minor_ver);
+        if (errno || match_count != 2)
+          throw error("Context._get_hex_version", CL_INVALID_VALUE,
+              "Platform version string did not have expected format");
+
+        return major_ver << 12 | minor_ver << 4;
+      }
   };
 
 
@@ -1183,8 +1225,8 @@ namespace pyopencl
 
       command_queue(
           const context &ctx,
-          const device *py_dev=0,
-          cl_command_queue_properties props=0)
+          const device *py_dev=nullptr,
+          py::object py_props=py::none())
       {
         cl_device_id dev;
         if (py_dev)
@@ -1199,20 +1241,100 @@ namespace pyopencl
           dev = devs[0];
         }
 
-        cl_int status_code;
-        PYOPENCL_PRINT_CALL_TRACE("clCreateCommandQueue");
+        int hex_plat_version = ctx.get_hex_platform_version();
+        printf("plat version code: %d\n", hex_plat_version);
+
+        bool props_given_as_numeric;
+        cl_command_queue_properties num_props;
+        if (py_props.is_none())
+        {
+          num_props = 0;
+          props_given_as_numeric = true;
+        }
+        else
+        {
+          try
+          {
+            num_props = py::cast<cl_command_queue_properties>(py_props);
+            props_given_as_numeric = true;
+          }
+          catch (py::cast_error &)
+          {
+            props_given_as_numeric = false;
+          }
+        }
+
+        if (props_given_as_numeric)
+        {
+#if PYOPENCL_CL_VERSION >= 0x2000
+          if (hex_plat_version  >= 0x2000)
+          {
+            cl_queue_properties props_list[] = { CL_QUEUE_PROPERTIES, num_props, 0 };
+
+            cl_int status_code;
+
+            PYOPENCL_PRINT_CALL_TRACE("clCreateCommandQueueWithProperties");
+            m_queue = clCreateCommandQueueWithProperties(
+                ctx.data(), dev, props_list, &status_code);
+
+            if (status_code != CL_SUCCESS)
+              throw pyopencl::error("CommandQueue", status_code);
+          }
+          else
+#endif
+          {
+            cl_int status_code;
+
+            PYOPENCL_PRINT_CALL_TRACE("clCreateCommandQueue");
 #if defined(__GNUG__) && !defined(__clang__)
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
 #endif
-        m_queue = clCreateCommandQueue(
-            ctx.data(), dev, props, &status_code);
+            m_queue = clCreateCommandQueue(
+                ctx.data(), dev, num_props, &status_code);
 #if defined(__GNUG__) && !defined(__clang__)
 #pragma GCC diagnostic pop
+#endif
+            if (status_code != CL_SUCCESS)
+              throw pyopencl::error("CommandQueue", status_code);
+          }
+        }
+        else
+        {
+#if PYOPENCL_CL_VERSION >= 0x2000
+            throw error("CommandQueue", CL_INVALID_VALUE,
+                "queue properties given as an iterable, "
+                "which is only allowed when PyOpenCL was built "
+                "against an OpenCL 2+ header");
 #endif
 
-        if (status_code != CL_SUCCESS)
-          throw pyopencl::error("CommandQueue", status_code);
+          if (hex_plat_version  < 0x2000)
+          {
+            std::cerr <<
+                "queue properties given as an iterable, "
+                "which uses an OpenCL 2+-only interface, "
+                "but the context's platform does not "
+                "declare OpenCL 2 support. Proceeding "
+                "as asked, but the next think you see "
+                "may be a crash." << std:: endl;
+          }
+
+          cl_queue_properties props[py::len(py_props) + 1];
+          {
+            size_t i = 0;
+            for (auto prop: py_props)
+              props[i++] = py::cast<cl_queue_properties>(prop);
+            props[i++] = 0;
+          }
+
+          cl_int status_code;
+          PYOPENCL_PRINT_CALL_TRACE("clCreateCommandQueueWithProperties");
+          m_queue = clCreateCommandQueueWithProperties(
+              ctx.data(), dev, props, &status_code);
+
+          if (status_code != CL_SUCCESS)
+            throw pyopencl::error("CommandQueue", status_code);
+        }
       }
 
       ~command_queue()
diff --git a/src/wrap_cl_part_1.cpp b/src/wrap_cl_part_1.cpp
index 2927c8c12d0686b0defa6692c5e420bcb5bf115d..6309f98a5916f8d5a5f53aed39d032a5dc2dc8a5 100644
--- a/src/wrap_cl_part_1.cpp
+++ b/src/wrap_cl_part_1.cpp
@@ -80,11 +80,10 @@ void pyopencl_expose_part_1(py::module &m)
     typedef command_queue cls;
     py::class_<cls, std::shared_ptr<cls>>(m, "CommandQueue", py::dynamic_attr())
       .def(
-        py::init<const context &,
-          const device *, cl_command_queue_properties>(),
+        py::init<const context &, const device *, py::object>(),
         py::arg("context"),
-        py::arg("device")=py::none(),
-        py::arg("properties")=0)
+        py::arg("device").none(true)=py::none(),
+        py::arg("properties")=py::cast(0))
       .DEF_SIMPLE_METHOD(get_info)
 #if PYOPENCL_CL_VERSION < 0x1010
       .DEF_SIMPLE_METHOD(set_property)