diff -r 198cf88374c8 src/ex_docmd.c
--- a/src/ex_docmd.c	Sun Jun 09 20:51:00 2013 +0200
+++ b/src/ex_docmd.c	Mon Jun 10 23:35:48 2013 +0800
@@ -3574,7 +3574,7 @@
 	case CMD_lcd:
 	case CMD_lchdir:
 	    if (xp->xp_context == EXPAND_FILES)
-		xp->xp_context = EXPAND_DIRECTORIES;
+		xp->xp_context = EXPAND_DIR_IN_CDPATH;
 	    break;
 	case CMD_help:
 	    xp->xp_context = EXPAND_HELP;
diff -r 198cf88374c8 src/ex_getln.c
--- a/src/ex_getln.c	Sun Jun 09 20:51:00 2013 +0200
+++ b/src/ex_getln.c	Mon Jun 10 23:35:48 2013 +0800
@@ -4195,6 +4195,7 @@
 
     if (context != EXPAND_FILES
 	    && context != EXPAND_FILES_IN_PATH
+	    && context != EXPAND_DIR_IN_CDPATH
 	    && context != EXPAND_SHELLCMD
 	    && context != EXPAND_DIRECTORIES)
     {
@@ -4526,7 +4527,8 @@
 
     if (xp->xp_context == EXPAND_FILES
 	    || xp->xp_context == EXPAND_DIRECTORIES
-	    || xp->xp_context == EXPAND_FILES_IN_PATH)
+	    || xp->xp_context == EXPAND_FILES_IN_PATH
+	    || xp->xp_context == EXPAND_DIR_IN_CDPATH)
     {
 	/*
 	 * Expand file or directory names.
@@ -4558,6 +4560,8 @@
 	    flags |= EW_FILE;
 	else if (xp->xp_context == EXPAND_FILES_IN_PATH)
 	    flags |= (EW_FILE | EW_PATH);
+	else if (xp->xp_context == EXPAND_DIR_IN_CDPATH)
+	    flags |= (EW_DIR | EW_CDPATH);
 	else
 	    flags = (flags | EW_DIR) & ~EW_FILE;
 	if (options & WILD_ICASE)
diff -r 198cf88374c8 src/misc1.c
--- a/src/misc1.c	Sun Jun 09 20:51:00 2013 +0200
+++ b/src/misc1.c	Mon Jun 10 23:35:48 2013 +0800
@@ -10006,10 +10006,10 @@
 #if defined(FEAT_SEARCHPATH)
 static int find_previous_pathsep __ARGS((char_u *path, char_u **psep));
 static int is_unique __ARGS((char_u *maybe_unique, garray_T *gap, int i));
-static void expand_path_option __ARGS((char_u *curdir, garray_T	*gap));
+static void expand_path_option __ARGS((char_u *curdir, garray_T *gap, char_u *option));
 static char_u *get_path_cutoff __ARGS((char_u *fname, garray_T *gap));
-static void uniquefy_paths __ARGS((garray_T *gap, char_u *pattern));
-static int expand_in_path __ARGS((garray_T *gap, char_u	*pattern, int flags));
+static void uniquefy_paths __ARGS((garray_T *gap, char_u *pattern, char_u *option));
+static int expand_in_path __ARGS((garray_T *gap, char_u *pattern, int flags));
 
 /*
  * Moves "*psep" back to the previous path separator in "path".
@@ -10080,12 +10080,11 @@
  * expanding each into their equivalent path(s).
  */
     static void
-expand_path_option(curdir, gap)
+expand_path_option(curdir, gap, path_option)
     char_u	*curdir;
     garray_T	*gap;
-{
-    char_u	*path_option = *curbuf->b_p_path == NUL
-						  ? p_path : curbuf->b_p_path;
+    char_u	*path_option;
+{
     char_u	*buf;
     char_u	*p;
     int		len;
@@ -10202,9 +10201,10 @@
  * that matches the pattern. Beware, this is at least O(n^2) wrt "gap->ga_len".
  */
     static void
-uniquefy_paths(gap, pattern)
+uniquefy_paths(gap, pattern, option)
     garray_T	*gap;
     char_u	*pattern;
+    char_u	*option;
 {
     int		i;
     int		len;
@@ -10247,7 +10247,7 @@
     if ((curdir = alloc((int)(MAXPATHL))) == NULL)
 	goto theend;
     mch_dirname(curdir, MAXPATHL);
-    expand_path_option(curdir, &path_ga);
+    expand_path_option(curdir, &path_ga, option);
 
     in_curdir = (char_u **)alloc_clear(gap->ga_len * sizeof(char_u *));
     if (in_curdir == NULL)
@@ -10381,13 +10381,18 @@
     char_u	*s;	/* start */
     char_u	*e;	/* end */
     char_u	*paths = NULL;
+    char_u	*path_option;
 
     if ((curdir = alloc((unsigned)MAXPATHL)) == NULL)
 	return 0;
     mch_dirname(curdir, MAXPATHL);
 
     ga_init2(&path_ga, (int)sizeof(char_u *), 1);
-    expand_path_option(curdir, &path_ga);
+    if (flags & EW_FILE)
+	path_option = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
+    else if (flags & EW_DIR)
+	path_option = p_cdpath;
+    expand_path_option(curdir, &path_ga, path_option);
     vim_free(curdir);
     if (path_ga.ga_len == 0)
 	return 0;
@@ -10566,7 +10571,7 @@
 	    if (mch_has_exp_wildcard(p))
 	    {
 #if defined(FEAT_SEARCHPATH)
-		if ((flags & EW_PATH)
+		if ((flags & EW_PATH || flags & EW_CDPATH)
 			&& !mch_isFullName(p)
 			&& !(p[0] == '.'
 			    && (vim_ispathsep(p[1])
@@ -10603,8 +10608,13 @@
 	}
 
 #if defined(FEAT_SEARCHPATH)
-	if (did_expand_in_path && ga.ga_len > 0 && (flags & EW_PATH))
-	    uniquefy_paths(&ga, p);
+	if (did_expand_in_path && ga.ga_len > 0)
+	{
+	    if (flags & EW_PATH)
+		uniquefy_paths(&ga, p, *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path);
+	    else if (flags & EW_CDPATH)
+		uniquefy_paths(&ga, p, p_cdpath);
+	}
 #endif
 	if (p != pat[i])
 	    vim_free(p);
diff -r 198cf88374c8 src/vim.h
--- a/src/vim.h	Sun Jun 09 20:51:00 2013 +0200
+++ b/src/vim.h	Mon Jun 10 23:35:48 2013 +0800
@@ -784,6 +784,7 @@
 #define EXPAND_HISTORY		41
 #define EXPAND_USER		42
 #define EXPAND_SYNTIME		43
+#define EXPAND_DIR_IN_CDPATH	44
 
 /* Values for exmode_active (0 is no exmode) */
 #define EXMODE_NORMAL		1
@@ -821,6 +822,7 @@
 #define EW_ICASE	0x100	/* ignore case */
 #define EW_NOERROR	0x200	/* no error for bad regexp */
 #define EW_NOTWILD	0x400	/* add match with literal name if exists */
+#define EW_CDPATH	0x800   /* search in 'cdpath' */
 /* Note: mostly EW_NOTFOUND and EW_SILENT are mutually exclusive: EW_NOTFOUND
  * is used when executing commands and EW_SILENT for interactive expanding. */
 
