diff --git a/Cython/Compiler/Builtin.py b/Cython/Compiler/Builtin.py
index c96f479a055875ff114bef66bce4753e989f0031..bb42a235b68737a8c644ce51dabf9f345502ccca 100644
--- a/Cython/Compiler/Builtin.py
+++ b/Cython/Compiler/Builtin.py
@@ -276,7 +276,10 @@ builtin_types_table = [
                                     BuiltinAttribute('imag', 'cval.imag', field_type = PyrexTypes.c_double_type),
                                     ]),
 
-    ("basestring",   "PyBaseString_Type",      []),
+    ("basestring", "PyBaseString_Type", [
+                                    BuiltinMethod("join",  "TO",   "T", "__Pyx_PyBaseString_Join",
+                                                  utility_code=UtilityCode.load("StringJoin", "StringTools.c")),
+                                    ]),
     ("bytearray", "PyByteArray_Type", []),
     ("bytes",   "PyBytes_Type",    [BuiltinMethod("__contains__",  "TO",   "b", "PySequence_Contains"),
                                     BuiltinMethod("join",  "TO",   "O", "__Pyx_PyBytes_Join",
diff --git a/Cython/Utility/StringTools.c b/Cython/Utility/StringTools.c
index 88f59963a1353ece301a2855dc9f978716c14eaa..67b36d37dd5f30f8ea8d3797a7cc9f919e995182 100644
--- a/Cython/Utility/StringTools.c
+++ b/Cython/Utility/StringTools.c
@@ -654,8 +654,10 @@ static CYTHON_INLINE char __Pyx_PyBytes_GetItemInt(PyObject* bytes, Py_ssize_t i
 
 #if PY_MAJOR_VERSION < 3
 #define __Pyx_PyString_Join __Pyx_PyBytes_Join
+#define __Pyx_PyBaseString_Join(s, v) (PyUnicode_CheckExact(s) ? PyUnicode_Join(s, v) : __Pyx_PyBytes_Join(s, v))
 #else
 #define __Pyx_PyString_Join PyUnicode_Join
+#define __Pyx_PyBaseString_Join PyUnicode_Join
 #endif
 
 #if CYTHON_COMPILING_IN_CPYTHON
diff --git a/tests/run/builtin_basestring.pyx b/tests/run/builtin_basestring.pyx
index d1e0e1c56acfd60ea829196ff137a811ed14f426..ceaa3212d4940247cd1cc68fd1eb45b5f576df94 100644
--- a/tests/run/builtin_basestring.pyx
+++ b/tests/run/builtin_basestring.pyx
@@ -1,4 +1,6 @@
 
+cimport cython
+
 import sys
 IS_PY3 = sys.version_info[0] >= 3
 
@@ -84,3 +86,23 @@ def basestring_typed_argument(basestring obj):
     TypeError: ...got S...
     """
     return obj
+
+
+@cython.test_assert_path_exists(
+    "//SimpleCallNode",
+    "//SimpleCallNode//NoneCheckNode",
+    "//SimpleCallNode//AttributeNode[@is_py_attr = false]")
+def basestring_join(basestring s, *values):
+    """
+    >>> print(basestring_join(ustring, 'a', 'b', 'c'))
+    aabcdefbabcdefc
+    >>> print(basestring_join(sstring, 'a', 'b', 'c'))
+    aabcdefbabcdefc
+    >>> if IS_PY3: print('abcdefabcdefabcdef')
+    ... else: print(basestring_join(bstring, bstring, bstring).decode('utf8'))
+    abcdefabcdefabcdef
+    >>> basestring_join(None, 'a', 'b', 'c')
+    Traceback (most recent call last):
+    AttributeError: 'NoneType' object has no attribute 'join'
+    """
+    return s.join(values)