diff --git a/cpu/cpujit.py b/cpu/cpujit.py
index cb840d3db2cd78dc90bc0613cf389de7371fb814..536c0a36ed0e19c1f714ca1632ea9118c1fdc231 100644
--- a/cpu/cpujit.py
+++ b/cpu/cpujit.py
@@ -397,7 +397,7 @@ def build_ctypes_argument_list(parameter_specification, argument_dict):
 
                 if FieldType.is_indexed(symbolic_field):
                     index_arr_shapes.add(field_arr.shape[:symbolic_field.spatial_dimensions])
-                elif not FieldType.is_buffer(symbolic_field):
+                elif FieldType.is_generic(symbolic_field):
                     array_shapes.add(field_arr.shape[:symbolic_field.spatial_dimensions])
 
             elif arg.is_field_shape_argument:
diff --git a/field.py b/field.py
index 58f13cb94ded95c0aa779ec0ebd57a45314545d6..632c454be7fee0e4226f36f753300e393108f1ac 100644
--- a/field.py
+++ b/field.py
@@ -87,6 +87,9 @@ class FieldType(Enum):
     INDEXED = 1
     # communication buffer, used for (un)packing data in communication.
     BUFFER = 2
+    # unsafe fields may be accessed in an absolute fashion - the index depends on the data
+    # and thus may lead to out-of-bounds accesses
+    CUSTOM = 3
 
     @staticmethod
     def is_generic(field):
@@ -103,6 +106,11 @@ class FieldType(Enum):
         assert isinstance(field, Field)
         return field.field_type == FieldType.BUFFER
 
+    @staticmethod
+    def is_custom(field):
+        assert isinstance(field, Field)
+        return field.field_type == FieldType.CUSTOM
+
 
 class Field:
     """
@@ -367,6 +375,7 @@ class Field:
         return Field.Access(self, offset)
 
     def absolute_access(self, offset, index):
+        assert FieldType.is_custom(self)
         return Field.Access(self, offset, index, is_absolute_access=True)
 
     def __call__(self, *args, **kwargs):
@@ -582,10 +591,16 @@ class Field:
 
         def _latex(self, _):
             n = self._field.latex_name if self._field.latex_name else self._field.name
-            if self._superscript:
-                return "{{%s}_{%s}^{%s}}" % (n, self._offsetName, self._superscript)
+            offset_str = ",".join([sp.latex(o) for o in self.offsets])
+            if self.is_absolute_access:
+                offset_str = "\\mathbf{}".format(offset_str)
+            elif self.field.spatial_dimensions > 1:
+                offset_str = "({})".format(offset_str)
+
+            if self.index and self.index != (0,):
+                return "{{%s}_{%s}^{%s}}" % (n, offset_str, self.index if len(self.index) > 1 else self.index[0])
             else:
-                return "{{%s}_{%s}}" % (n, self._offsetName)
+                return "{{%s}_{%s}}" % (n, offset_str)
 
 
 def get_layout_from_strides(strides: Sequence[int], index_dimension_ids: Optional[List[int]] = None):
diff --git a/gpucuda/cudajit.py b/gpucuda/cudajit.py
index 1127ecadcb1bc744a06037b11b17c3501d26a814..70f757a0578ea582ee38677baa2bed093125c804 100644
--- a/gpucuda/cudajit.py
+++ b/gpucuda/cudajit.py
@@ -132,7 +132,7 @@ def _check_arguments(parameter_specification, argument_dict):
 
                 if FieldType.is_indexed(symbolic_field):
                     index_arr_shapes.add(field_arr.shape[:symbolic_field.spatial_dimensions])
-                elif not FieldType.is_buffer(symbolic_field):
+                elif FieldType.is_generic(symbolic_field):
                     array_shapes.add(field_arr.shape[:symbolic_field.spatial_dimensions])
 
     if len(array_shapes) > 1: