Emacs has no way of knowing when the shell actually changes its directory. This is an intrinsic limitation of Unix. So it tries to guess by recognizing ‘cd’ commands. If you type cd followed by a directory name with a variable reference (cd $HOME/bin) or with a shell metacharacter (cd ../lib*), Emacs will fail to correctly guess the shell’s new current directory. A huge variety of fixes and enhancements to shell mode for this problem have been written to handle this problem (see Finding a package with particular functionality).
You can tell Emacs the shell’s current directory with the command M-x dirs.